Spaces:
Running
Running
Update src/utils.py
Browse files- src/utils.py +106 -1
src/utils.py
CHANGED
|
@@ -7,6 +7,8 @@ from typing import Any, Dict, List, Optional
|
|
| 7 |
from urllib.parse import urlencode
|
| 8 |
import aiohttp
|
| 9 |
import asyncio
|
|
|
|
|
|
|
| 10 |
|
| 11 |
def json_serializer(obj: Any) -> str:
|
| 12 |
"""
|
|
@@ -281,4 +283,107 @@ def retry_on_exception(max_retries: int = 3, delay: float = 1.0, exceptions: tup
|
|
| 281 |
Returns:
|
| 282 |
Decorated function
|
| 283 |
"""
|
| 284 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
from urllib.parse import urlencode
|
| 8 |
import aiohttp
|
| 9 |
import asyncio
|
| 10 |
+
import functools
|
| 11 |
+
import time
|
| 12 |
|
| 13 |
def json_serializer(obj: Any) -> str:
|
| 14 |
"""
|
|
|
|
| 283 |
Returns:
|
| 284 |
Decorated function
|
| 285 |
"""
|
| 286 |
+
def decorator(func):
|
| 287 |
+
@functools.wraps(func)
|
| 288 |
+
def wrapper(*args, **kwargs):
|
| 289 |
+
for attempt in range(max_retries):
|
| 290 |
+
try:
|
| 291 |
+
return func(*args, **kwargs)
|
| 292 |
+
except exceptions as e:
|
| 293 |
+
if attempt == max_retries - 1:
|
| 294 |
+
raise e
|
| 295 |
+
time.sleep(delay * (2 ** attempt)) # Exponential backoff
|
| 296 |
+
return None
|
| 297 |
+
return wrapper
|
| 298 |
+
return decorator
|
| 299 |
+
|
| 300 |
+
def batch_process(items: List, batch_size: int = 10):
|
| 301 |
+
"""
|
| 302 |
+
Process items in batches.
|
| 303 |
+
|
| 304 |
+
Args:
|
| 305 |
+
items: List of items to process
|
| 306 |
+
batch_size: Size of each batch
|
| 307 |
+
|
| 308 |
+
Yields:
|
| 309 |
+
Batches of items
|
| 310 |
+
"""
|
| 311 |
+
for i in range(0, len(items), batch_size):
|
| 312 |
+
yield items[i:i + batch_size]
|
| 313 |
+
|
| 314 |
+
def safe_get(dictionary: Dict, keys: List[str], default: Any = None) -> Any:
|
| 315 |
+
"""
|
| 316 |
+
Safely get nested dictionary value.
|
| 317 |
+
|
| 318 |
+
Args:
|
| 319 |
+
dictionary: Dictionary to search
|
| 320 |
+
keys: List of keys to traverse
|
| 321 |
+
default: Default value if key not found
|
| 322 |
+
|
| 323 |
+
Returns:
|
| 324 |
+
Value or default
|
| 325 |
+
"""
|
| 326 |
+
current = dictionary
|
| 327 |
+
for key in keys:
|
| 328 |
+
if isinstance(current, dict) and key in current:
|
| 329 |
+
current = current[key]
|
| 330 |
+
else:
|
| 331 |
+
return default
|
| 332 |
+
return current
|
| 333 |
+
|
| 334 |
+
def format_bytes(size: float) -> str:
|
| 335 |
+
"""
|
| 336 |
+
Format bytes to human readable string.
|
| 337 |
+
|
| 338 |
+
Args:
|
| 339 |
+
size: Size in bytes
|
| 340 |
+
|
| 341 |
+
Returns:
|
| 342 |
+
Formatted string
|
| 343 |
+
"""
|
| 344 |
+
for unit in ['B', 'KB', 'MB', 'GB', 'TB']:
|
| 345 |
+
if size < 1024.0:
|
| 346 |
+
return f"{size:.2f} {unit}"
|
| 347 |
+
size /= 1024.0
|
| 348 |
+
return f"{size:.2f} PB"
|
| 349 |
+
|
| 350 |
+
def generate_conversation_id() -> str:
|
| 351 |
+
"""
|
| 352 |
+
Generate a unique conversation ID.
|
| 353 |
+
|
| 354 |
+
Returns:
|
| 355 |
+
Unique conversation ID string
|
| 356 |
+
"""
|
| 357 |
+
import uuid
|
| 358 |
+
return f"conv_{uuid.uuid4().hex[:16]}"
|
| 359 |
+
|
| 360 |
+
def validate_email(email: str) -> bool:
|
| 361 |
+
"""
|
| 362 |
+
Validate email format.
|
| 363 |
+
|
| 364 |
+
Args:
|
| 365 |
+
email: Email to validate
|
| 366 |
+
|
| 367 |
+
Returns:
|
| 368 |
+
True if valid email, False otherwise
|
| 369 |
+
"""
|
| 370 |
+
import re
|
| 371 |
+
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
|
| 372 |
+
return re.match(pattern, email) is not None
|
| 373 |
+
|
| 374 |
+
def get_platform_info() -> Dict[str, Any]:
|
| 375 |
+
"""
|
| 376 |
+
Get platform information.
|
| 377 |
+
|
| 378 |
+
Returns:
|
| 379 |
+
Platform information dictionary
|
| 380 |
+
"""
|
| 381 |
+
import platform
|
| 382 |
+
return {
|
| 383 |
+
'system': platform.system(),
|
| 384 |
+
'release': platform.release(),
|
| 385 |
+
'version': platform.version(),
|
| 386 |
+
'machine': platform.machine(),
|
| 387 |
+
'processor': platform.processor(),
|
| 388 |
+
'python_version': platform.python_version()
|
| 389 |
+
}
|