ucn 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ucn might be problematic. Click here for more details.
- package/.claude/skills/ucn/SKILL.md +77 -0
- package/LICENSE +21 -0
- package/README.md +135 -0
- package/cli/index.js +2437 -0
- package/core/discovery.js +513 -0
- package/core/imports.js +558 -0
- package/core/output.js +1274 -0
- package/core/parser.js +279 -0
- package/core/project.js +3261 -0
- package/index.js +52 -0
- package/languages/go.js +653 -0
- package/languages/index.js +267 -0
- package/languages/java.js +826 -0
- package/languages/javascript.js +1346 -0
- package/languages/python.js +667 -0
- package/languages/rust.js +950 -0
- package/languages/utils.js +457 -0
- package/package.json +42 -0
- package/test/fixtures/go/go.mod +3 -0
- package/test/fixtures/go/main.go +257 -0
- package/test/fixtures/go/service.go +187 -0
- package/test/fixtures/java/DataService.java +279 -0
- package/test/fixtures/java/Main.java +287 -0
- package/test/fixtures/java/Utils.java +199 -0
- package/test/fixtures/java/pom.xml +6 -0
- package/test/fixtures/javascript/main.js +109 -0
- package/test/fixtures/javascript/package.json +1 -0
- package/test/fixtures/javascript/service.js +88 -0
- package/test/fixtures/javascript/utils.js +67 -0
- package/test/fixtures/python/main.py +198 -0
- package/test/fixtures/python/pyproject.toml +3 -0
- package/test/fixtures/python/service.py +166 -0
- package/test/fixtures/python/utils.py +118 -0
- package/test/fixtures/rust/Cargo.toml +3 -0
- package/test/fixtures/rust/main.rs +253 -0
- package/test/fixtures/rust/service.rs +210 -0
- package/test/fixtures/rust/utils.rs +154 -0
- package/test/fixtures/typescript/main.ts +154 -0
- package/test/fixtures/typescript/package.json +1 -0
- package/test/fixtures/typescript/repository.ts +149 -0
- package/test/fixtures/typescript/types.ts +114 -0
- package/test/parser.test.js +3661 -0
- package/test/public-repos-test.js +477 -0
- package/test/systematic-test.js +619 -0
- package/ucn.js +8 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for data manipulation.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Helper function that processes input.
|
|
7
|
+
* @param {any} input - The input to process
|
|
8
|
+
* @returns {any} The processed output
|
|
9
|
+
*/
|
|
10
|
+
function helper(input) {
|
|
11
|
+
return formatData(input);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Format data for output.
|
|
16
|
+
*/
|
|
17
|
+
function formatData(data) {
|
|
18
|
+
if (Array.isArray(data)) {
|
|
19
|
+
return data.map(item => formatItem(item));
|
|
20
|
+
}
|
|
21
|
+
return formatItem(data);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Format a single item.
|
|
26
|
+
*/
|
|
27
|
+
function formatItem(item) {
|
|
28
|
+
return {
|
|
29
|
+
...item,
|
|
30
|
+
formatted: true
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Utility function for string operations.
|
|
36
|
+
*/
|
|
37
|
+
const utilFunc = (str) => {
|
|
38
|
+
return str.trim().toLowerCase();
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Deep clone an object.
|
|
43
|
+
*/
|
|
44
|
+
function deepClone(obj) {
|
|
45
|
+
return JSON.parse(JSON.stringify(obj));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Merge multiple objects.
|
|
50
|
+
*/
|
|
51
|
+
function mergeObjects(...objects) {
|
|
52
|
+
return objects.reduce((acc, obj) => ({ ...acc, ...obj }), {});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Unused function (for deadcode detection)
|
|
56
|
+
function unusedHelper() {
|
|
57
|
+
return 'never called';
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
module.exports = {
|
|
61
|
+
helper,
|
|
62
|
+
formatData,
|
|
63
|
+
formatItem,
|
|
64
|
+
utilFunc,
|
|
65
|
+
deepClone,
|
|
66
|
+
mergeObjects
|
|
67
|
+
};
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Main Python test fixtures.
|
|
3
|
+
Tests classes, decorators, type hints, and async functions.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from typing import List, Optional, Dict, Any, Callable, TypeVar, Generic
|
|
7
|
+
from dataclasses import dataclass, field
|
|
8
|
+
from enum import Enum
|
|
9
|
+
import asyncio
|
|
10
|
+
|
|
11
|
+
from .utils import format_data, validate_input, deep_merge
|
|
12
|
+
from .service import DataService, ServiceConfig
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Status(Enum):
|
|
16
|
+
"""Task status enumeration."""
|
|
17
|
+
PENDING = "pending"
|
|
18
|
+
ACTIVE = "active"
|
|
19
|
+
COMPLETED = "completed"
|
|
20
|
+
FAILED = "failed"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass
|
|
24
|
+
class Task:
|
|
25
|
+
"""Task data class."""
|
|
26
|
+
id: str
|
|
27
|
+
name: str
|
|
28
|
+
status: Status = Status.PENDING
|
|
29
|
+
priority: int = 1
|
|
30
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
T = TypeVar('T', bound=Task)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class TaskManager(Generic[T]):
|
|
37
|
+
"""Generic task manager class."""
|
|
38
|
+
|
|
39
|
+
def __init__(self, config: Optional[ServiceConfig] = None):
|
|
40
|
+
"""Initialize the task manager."""
|
|
41
|
+
self.config = config or ServiceConfig()
|
|
42
|
+
self.tasks: List[T] = []
|
|
43
|
+
self.service = DataService(self.config)
|
|
44
|
+
|
|
45
|
+
def add_task(self, task: T) -> None:
|
|
46
|
+
"""Add a task to the manager."""
|
|
47
|
+
validated = validate_input(task)
|
|
48
|
+
self.tasks.append(validated)
|
|
49
|
+
|
|
50
|
+
def get_task(self, task_id: str) -> Optional[T]:
|
|
51
|
+
"""Get a task by ID."""
|
|
52
|
+
for task in self.tasks:
|
|
53
|
+
if task.id == task_id:
|
|
54
|
+
return task
|
|
55
|
+
return None
|
|
56
|
+
|
|
57
|
+
def get_tasks(self, filter_fn: Optional[Callable[[T], bool]] = None) -> List[T]:
|
|
58
|
+
"""Get all tasks, optionally filtered."""
|
|
59
|
+
if filter_fn:
|
|
60
|
+
return [t for t in self.tasks if filter_fn(t)]
|
|
61
|
+
return self.tasks.copy()
|
|
62
|
+
|
|
63
|
+
def update_task(self, task_id: str, **updates) -> Optional[T]:
|
|
64
|
+
"""Update a task by ID."""
|
|
65
|
+
task = self.get_task(task_id)
|
|
66
|
+
if task:
|
|
67
|
+
for key, value in updates.items():
|
|
68
|
+
if hasattr(task, key):
|
|
69
|
+
setattr(task, key, value)
|
|
70
|
+
return task
|
|
71
|
+
return None
|
|
72
|
+
|
|
73
|
+
def delete_task(self, task_id: str) -> bool:
|
|
74
|
+
"""Delete a task by ID."""
|
|
75
|
+
task = self.get_task(task_id)
|
|
76
|
+
if task:
|
|
77
|
+
self.tasks.remove(task)
|
|
78
|
+
return True
|
|
79
|
+
return False
|
|
80
|
+
|
|
81
|
+
async def sync_tasks(self) -> int:
|
|
82
|
+
"""Sync tasks with the service."""
|
|
83
|
+
count = 0
|
|
84
|
+
for task in self.tasks:
|
|
85
|
+
await self.service.save(task)
|
|
86
|
+
count += 1
|
|
87
|
+
return count
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def create_task(name: str, priority: int = 1) -> Task:
|
|
91
|
+
"""Factory function to create a task."""
|
|
92
|
+
import uuid
|
|
93
|
+
return Task(
|
|
94
|
+
id=str(uuid.uuid4()),
|
|
95
|
+
name=name,
|
|
96
|
+
priority=priority
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def filter_by_status(tasks: List[Task], status: Status) -> List[Task]:
|
|
101
|
+
"""Filter tasks by status."""
|
|
102
|
+
return [t for t in tasks if t.status == status]
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def filter_by_priority(tasks: List[Task], min_priority: int) -> List[Task]:
|
|
106
|
+
"""Filter tasks by minimum priority."""
|
|
107
|
+
return [t for t in tasks if t.priority >= min_priority]
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
async def process_tasks_async(tasks: List[Task]) -> List[Dict[str, Any]]:
|
|
111
|
+
"""Process tasks asynchronously."""
|
|
112
|
+
results = []
|
|
113
|
+
for task in tasks:
|
|
114
|
+
result = await process_single_task(task)
|
|
115
|
+
results.append(result)
|
|
116
|
+
return results
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
async def process_single_task(task: Task) -> Dict[str, Any]:
|
|
120
|
+
"""Process a single task."""
|
|
121
|
+
await asyncio.sleep(0.01) # Simulate async work
|
|
122
|
+
return format_data(task)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def with_logging(func: Callable) -> Callable:
|
|
126
|
+
"""Decorator that adds logging."""
|
|
127
|
+
def wrapper(*args, **kwargs):
|
|
128
|
+
print(f"Calling {func.__name__}")
|
|
129
|
+
result = func(*args, **kwargs)
|
|
130
|
+
print(f"Finished {func.__name__}")
|
|
131
|
+
return result
|
|
132
|
+
return wrapper
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def with_retry(retries: int = 3):
|
|
136
|
+
"""Decorator factory for retry logic."""
|
|
137
|
+
def decorator(func: Callable) -> Callable:
|
|
138
|
+
def wrapper(*args, **kwargs):
|
|
139
|
+
last_error = None
|
|
140
|
+
for i in range(retries):
|
|
141
|
+
try:
|
|
142
|
+
return func(*args, **kwargs)
|
|
143
|
+
except Exception as e:
|
|
144
|
+
last_error = e
|
|
145
|
+
raise last_error
|
|
146
|
+
return wrapper
|
|
147
|
+
return decorator
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
@with_logging
|
|
151
|
+
def logged_function(x: int) -> int:
|
|
152
|
+
"""A function with logging decorator."""
|
|
153
|
+
return x * 2
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class TaskProcessor:
|
|
157
|
+
"""Process tasks with various strategies."""
|
|
158
|
+
|
|
159
|
+
def __init__(self, manager: TaskManager):
|
|
160
|
+
self.manager = manager
|
|
161
|
+
|
|
162
|
+
def process_all(self) -> List[Dict[str, Any]]:
|
|
163
|
+
"""Process all tasks."""
|
|
164
|
+
tasks = self.manager.get_tasks()
|
|
165
|
+
return [self._process(t) for t in tasks]
|
|
166
|
+
|
|
167
|
+
def process_pending(self) -> List[Dict[str, Any]]:
|
|
168
|
+
"""Process only pending tasks."""
|
|
169
|
+
tasks = self.manager.get_tasks(
|
|
170
|
+
lambda t: t.status == Status.PENDING
|
|
171
|
+
)
|
|
172
|
+
return [self._process(t) for t in tasks]
|
|
173
|
+
|
|
174
|
+
def _process(self, task: Task) -> Dict[str, Any]:
|
|
175
|
+
"""Internal processing method."""
|
|
176
|
+
data = format_data(task)
|
|
177
|
+
return deep_merge(data, {"processed": True})
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
# Unused function for deadcode detection
|
|
181
|
+
def unused_function():
|
|
182
|
+
"""This function is never called."""
|
|
183
|
+
return "never used"
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
__all__ = [
|
|
187
|
+
'Status',
|
|
188
|
+
'Task',
|
|
189
|
+
'TaskManager',
|
|
190
|
+
'TaskProcessor',
|
|
191
|
+
'create_task',
|
|
192
|
+
'filter_by_status',
|
|
193
|
+
'filter_by_priority',
|
|
194
|
+
'process_tasks_async',
|
|
195
|
+
'with_logging',
|
|
196
|
+
'with_retry',
|
|
197
|
+
'logged_function',
|
|
198
|
+
]
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Service layer for data operations.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Any, Dict, List, Optional, TypeVar, Generic
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
import asyncio
|
|
8
|
+
|
|
9
|
+
from .utils import format_data, validate_input
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class ServiceConfig:
|
|
14
|
+
"""Configuration for services."""
|
|
15
|
+
api_url: str = "https://api.example.com"
|
|
16
|
+
timeout: int = 5000
|
|
17
|
+
retries: int = 3
|
|
18
|
+
debug: bool = False
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
T = TypeVar('T')
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class DataService(Generic[T]):
|
|
25
|
+
"""Generic data service."""
|
|
26
|
+
|
|
27
|
+
def __init__(self, config: Optional[ServiceConfig] = None):
|
|
28
|
+
self.config = config or ServiceConfig()
|
|
29
|
+
self._storage: Dict[str, T] = {}
|
|
30
|
+
|
|
31
|
+
async def save(self, entity: T) -> None:
|
|
32
|
+
"""Save an entity."""
|
|
33
|
+
validate_input(entity)
|
|
34
|
+
entity_id = self._get_id(entity)
|
|
35
|
+
self._storage[entity_id] = entity
|
|
36
|
+
|
|
37
|
+
async def find(self, entity_id: str) -> Optional[T]:
|
|
38
|
+
"""Find an entity by ID."""
|
|
39
|
+
return self._storage.get(entity_id)
|
|
40
|
+
|
|
41
|
+
async def find_all(self) -> List[T]:
|
|
42
|
+
"""Find all entities."""
|
|
43
|
+
return list(self._storage.values())
|
|
44
|
+
|
|
45
|
+
async def delete(self, entity_id: str) -> bool:
|
|
46
|
+
"""Delete an entity."""
|
|
47
|
+
if entity_id in self._storage:
|
|
48
|
+
del self._storage[entity_id]
|
|
49
|
+
return True
|
|
50
|
+
return False
|
|
51
|
+
|
|
52
|
+
def _get_id(self, entity: T) -> str:
|
|
53
|
+
"""Get the ID of an entity."""
|
|
54
|
+
if hasattr(entity, 'id'):
|
|
55
|
+
return str(entity.id)
|
|
56
|
+
raise ValueError("Entity must have an 'id' attribute")
|
|
57
|
+
|
|
58
|
+
def clear(self) -> None:
|
|
59
|
+
"""Clear all stored entities."""
|
|
60
|
+
self._storage.clear()
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class CacheService:
|
|
64
|
+
"""Caching service."""
|
|
65
|
+
|
|
66
|
+
def __init__(self, ttl: int = 300):
|
|
67
|
+
self.ttl = ttl
|
|
68
|
+
self._cache: Dict[str, Any] = {}
|
|
69
|
+
self._timestamps: Dict[str, float] = {}
|
|
70
|
+
|
|
71
|
+
def get(self, key: str) -> Optional[Any]:
|
|
72
|
+
"""Get a value from cache."""
|
|
73
|
+
if key in self._cache:
|
|
74
|
+
return self._cache[key]
|
|
75
|
+
return None
|
|
76
|
+
|
|
77
|
+
def set(self, key: str, value: Any) -> None:
|
|
78
|
+
"""Set a value in cache."""
|
|
79
|
+
import time
|
|
80
|
+
self._cache[key] = value
|
|
81
|
+
self._timestamps[key] = time.time()
|
|
82
|
+
|
|
83
|
+
def delete(self, key: str) -> bool:
|
|
84
|
+
"""Delete a value from cache."""
|
|
85
|
+
if key in self._cache:
|
|
86
|
+
del self._cache[key]
|
|
87
|
+
del self._timestamps[key]
|
|
88
|
+
return True
|
|
89
|
+
return False
|
|
90
|
+
|
|
91
|
+
def clear(self) -> None:
|
|
92
|
+
"""Clear the cache."""
|
|
93
|
+
self._cache.clear()
|
|
94
|
+
self._timestamps.clear()
|
|
95
|
+
|
|
96
|
+
def cleanup_expired(self) -> int:
|
|
97
|
+
"""Remove expired entries."""
|
|
98
|
+
import time
|
|
99
|
+
now = time.time()
|
|
100
|
+
expired = [
|
|
101
|
+
key for key, ts in self._timestamps.items()
|
|
102
|
+
if now - ts > self.ttl
|
|
103
|
+
]
|
|
104
|
+
for key in expired:
|
|
105
|
+
self.delete(key)
|
|
106
|
+
return len(expired)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class ApiClient:
|
|
110
|
+
"""HTTP API client."""
|
|
111
|
+
|
|
112
|
+
def __init__(self, config: ServiceConfig):
|
|
113
|
+
self.config = config
|
|
114
|
+
self.base_url = config.api_url
|
|
115
|
+
|
|
116
|
+
async def get(self, path: str) -> Dict[str, Any]:
|
|
117
|
+
"""Make a GET request."""
|
|
118
|
+
url = self._build_url(path)
|
|
119
|
+
return await self._request('GET', url)
|
|
120
|
+
|
|
121
|
+
async def post(self, path: str, data: Dict[str, Any]) -> Dict[str, Any]:
|
|
122
|
+
"""Make a POST request."""
|
|
123
|
+
url = self._build_url(path)
|
|
124
|
+
return await self._request('POST', url, data)
|
|
125
|
+
|
|
126
|
+
async def put(self, path: str, data: Dict[str, Any]) -> Dict[str, Any]:
|
|
127
|
+
"""Make a PUT request."""
|
|
128
|
+
url = self._build_url(path)
|
|
129
|
+
return await self._request('PUT', url, data)
|
|
130
|
+
|
|
131
|
+
async def delete(self, path: str) -> Dict[str, Any]:
|
|
132
|
+
"""Make a DELETE request."""
|
|
133
|
+
url = self._build_url(path)
|
|
134
|
+
return await self._request('DELETE', url)
|
|
135
|
+
|
|
136
|
+
def _build_url(self, path: str) -> str:
|
|
137
|
+
"""Build the full URL."""
|
|
138
|
+
if path.startswith('http'):
|
|
139
|
+
return path
|
|
140
|
+
return f"{self.base_url}{path}"
|
|
141
|
+
|
|
142
|
+
async def _request(
|
|
143
|
+
self,
|
|
144
|
+
method: str,
|
|
145
|
+
url: str,
|
|
146
|
+
data: Optional[Dict[str, Any]] = None
|
|
147
|
+
) -> Dict[str, Any]:
|
|
148
|
+
"""Make an HTTP request."""
|
|
149
|
+
# Simulated request
|
|
150
|
+
await asyncio.sleep(0.01)
|
|
151
|
+
return {
|
|
152
|
+
"status": 200,
|
|
153
|
+
"method": method,
|
|
154
|
+
"url": url,
|
|
155
|
+
"data": data
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def create_service(config: Optional[ServiceConfig] = None) -> DataService:
|
|
160
|
+
"""Factory function to create a data service."""
|
|
161
|
+
return DataService(config)
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def create_api_client(config: Optional[ServiceConfig] = None) -> ApiClient:
|
|
165
|
+
"""Factory function to create an API client."""
|
|
166
|
+
return ApiClient(config or ServiceConfig())
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Utility functions for data manipulation.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Any, Dict, List, TypeVar, Union
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
T = TypeVar('T')
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def format_data(data: Any) -> Dict[str, Any]:
|
|
12
|
+
"""Format data into a dictionary."""
|
|
13
|
+
if hasattr(data, '__dict__'):
|
|
14
|
+
return {k: v for k, v in data.__dict__.items() if not k.startswith('_')}
|
|
15
|
+
elif isinstance(data, dict):
|
|
16
|
+
return data.copy()
|
|
17
|
+
else:
|
|
18
|
+
return {"value": data}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def validate_input(data: T) -> T:
|
|
22
|
+
"""Validate input data."""
|
|
23
|
+
if data is None:
|
|
24
|
+
raise ValueError("Input cannot be None")
|
|
25
|
+
return data
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def deep_merge(base: Dict[str, Any], updates: Dict[str, Any]) -> Dict[str, Any]:
|
|
29
|
+
"""Deep merge two dictionaries."""
|
|
30
|
+
result = base.copy()
|
|
31
|
+
for key, value in updates.items():
|
|
32
|
+
if key in result and isinstance(result[key], dict) and isinstance(value, dict):
|
|
33
|
+
result[key] = deep_merge(result[key], value)
|
|
34
|
+
else:
|
|
35
|
+
result[key] = value
|
|
36
|
+
return result
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def flatten_list(nested: List[List[T]]) -> List[T]:
|
|
40
|
+
"""Flatten a nested list."""
|
|
41
|
+
result = []
|
|
42
|
+
for item in nested:
|
|
43
|
+
if isinstance(item, list):
|
|
44
|
+
result.extend(flatten_list(item))
|
|
45
|
+
else:
|
|
46
|
+
result.append(item)
|
|
47
|
+
return result
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def chunk_list(items: List[T], size: int) -> List[List[T]]:
|
|
51
|
+
"""Split a list into chunks of given size."""
|
|
52
|
+
return [items[i:i + size] for i in range(0, len(items), size)]
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def safe_get(obj: Dict[str, Any], path: str, default: Any = None) -> Any:
|
|
56
|
+
"""Safely get a nested value from a dictionary."""
|
|
57
|
+
keys = path.split('.')
|
|
58
|
+
current = obj
|
|
59
|
+
for key in keys:
|
|
60
|
+
if isinstance(current, dict) and key in current:
|
|
61
|
+
current = current[key]
|
|
62
|
+
else:
|
|
63
|
+
return default
|
|
64
|
+
return current
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def transform_keys(data: Dict[str, Any], transformer: callable) -> Dict[str, Any]:
|
|
68
|
+
"""Transform all keys in a dictionary."""
|
|
69
|
+
return {transformer(k): v for k, v in data.items()}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def snake_to_camel(name: str) -> str:
|
|
73
|
+
"""Convert snake_case to camelCase."""
|
|
74
|
+
components = name.split('_')
|
|
75
|
+
return components[0] + ''.join(x.title() for x in components[1:])
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def camel_to_snake(name: str) -> str:
|
|
79
|
+
"""Convert camelCase to snake_case."""
|
|
80
|
+
result = []
|
|
81
|
+
for char in name:
|
|
82
|
+
if char.isupper():
|
|
83
|
+
result.append('_')
|
|
84
|
+
result.append(char.lower())
|
|
85
|
+
else:
|
|
86
|
+
result.append(char)
|
|
87
|
+
return ''.join(result).lstrip('_')
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class DataTransformer:
|
|
91
|
+
"""Class for transforming data."""
|
|
92
|
+
|
|
93
|
+
def __init__(self):
|
|
94
|
+
self.transformations = []
|
|
95
|
+
|
|
96
|
+
def add_transformation(self, fn: callable) -> 'DataTransformer':
|
|
97
|
+
"""Add a transformation function."""
|
|
98
|
+
self.transformations.append(fn)
|
|
99
|
+
return self
|
|
100
|
+
|
|
101
|
+
def transform(self, data: Any) -> Any:
|
|
102
|
+
"""Apply all transformations."""
|
|
103
|
+
result = data
|
|
104
|
+
for fn in self.transformations:
|
|
105
|
+
result = fn(result)
|
|
106
|
+
return result
|
|
107
|
+
|
|
108
|
+
def clear(self) -> None:
|
|
109
|
+
"""Clear all transformations."""
|
|
110
|
+
self.transformations = []
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
# Helper function that uses other utilities
|
|
114
|
+
def process_and_format(data: Any) -> Dict[str, Any]:
|
|
115
|
+
"""Process data and format it."""
|
|
116
|
+
validated = validate_input(data)
|
|
117
|
+
formatted = format_data(validated)
|
|
118
|
+
return formatted
|