django-nativemojo 0.1.10__py3-none-any.whl → 0.1.15__py3-none-any.whl

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.
Files changed (120) hide show
  1. django_nativemojo-0.1.15.dist-info/METADATA +136 -0
  2. {django_nativemojo-0.1.10.dist-info → django_nativemojo-0.1.15.dist-info}/RECORD +105 -65
  3. mojo/__init__.py +1 -1
  4. mojo/apps/account/management/__init__.py +5 -0
  5. mojo/apps/account/management/commands/__init__.py +6 -0
  6. mojo/apps/account/management/commands/serializer_admin.py +531 -0
  7. mojo/apps/account/migrations/0004_user_avatar.py +20 -0
  8. mojo/apps/account/migrations/0005_group_last_activity.py +18 -0
  9. mojo/apps/account/models/group.py +25 -7
  10. mojo/apps/account/models/member.py +15 -4
  11. mojo/apps/account/models/user.py +197 -20
  12. mojo/apps/account/rest/group.py +1 -0
  13. mojo/apps/account/rest/user.py +6 -2
  14. mojo/apps/aws/rest/__init__.py +1 -0
  15. mojo/apps/aws/rest/s3.py +64 -0
  16. mojo/apps/fileman/README.md +8 -8
  17. mojo/apps/fileman/backends/base.py +76 -70
  18. mojo/apps/fileman/backends/filesystem.py +86 -86
  19. mojo/apps/fileman/backends/s3.py +200 -108
  20. mojo/apps/fileman/migrations/0001_initial.py +106 -0
  21. mojo/apps/fileman/migrations/0002_filemanager_parent_alter_filemanager_max_file_size.py +24 -0
  22. mojo/apps/fileman/migrations/0003_remove_file_fileman_fil_upload__c4bc35_idx_and_more.py +25 -0
  23. mojo/apps/fileman/migrations/0004_remove_file_original_filename_and_more.py +39 -0
  24. mojo/apps/fileman/migrations/0005_alter_file_upload_token.py +18 -0
  25. mojo/apps/fileman/migrations/0006_file_download_url_filemanager_forever_urls.py +23 -0
  26. mojo/apps/fileman/migrations/0007_remove_filemanager_forever_urls_and_more.py +22 -0
  27. mojo/apps/fileman/migrations/0008_file_category.py +18 -0
  28. mojo/apps/fileman/migrations/0009_rename_file_path_file_storage_file_path.py +18 -0
  29. mojo/apps/fileman/migrations/0010_filerendition.py +33 -0
  30. mojo/apps/fileman/migrations/0011_alter_filerendition_original_file.py +19 -0
  31. mojo/apps/fileman/models/__init__.py +1 -5
  32. mojo/apps/fileman/models/file.py +204 -58
  33. mojo/apps/fileman/models/manager.py +161 -31
  34. mojo/apps/fileman/models/rendition.py +118 -0
  35. mojo/apps/fileman/renderer/__init__.py +111 -0
  36. mojo/apps/fileman/renderer/audio.py +403 -0
  37. mojo/apps/fileman/renderer/base.py +205 -0
  38. mojo/apps/fileman/renderer/document.py +404 -0
  39. mojo/apps/fileman/renderer/image.py +222 -0
  40. mojo/apps/fileman/renderer/utils.py +297 -0
  41. mojo/apps/fileman/renderer/video.py +304 -0
  42. mojo/apps/fileman/rest/__init__.py +1 -18
  43. mojo/apps/fileman/rest/upload.py +22 -32
  44. mojo/apps/fileman/signals.py +58 -0
  45. mojo/apps/fileman/tasks.py +254 -0
  46. mojo/apps/fileman/utils/__init__.py +40 -16
  47. mojo/apps/incident/migrations/0005_incidenthistory.py +39 -0
  48. mojo/apps/incident/migrations/0006_alter_incident_state.py +18 -0
  49. mojo/apps/incident/models/__init__.py +1 -0
  50. mojo/apps/incident/models/history.py +36 -0
  51. mojo/apps/incident/models/incident.py +1 -1
  52. mojo/apps/incident/reporter.py +3 -1
  53. mojo/apps/incident/rest/event.py +7 -1
  54. mojo/apps/logit/migrations/0004_alter_log_level.py +18 -0
  55. mojo/apps/logit/models/log.py +4 -1
  56. mojo/apps/metrics/utils.py +2 -2
  57. mojo/apps/notify/handlers/ses/message.py +1 -1
  58. mojo/apps/notify/providers/aws.py +2 -2
  59. mojo/apps/tasks/__init__.py +34 -1
  60. mojo/apps/tasks/manager.py +200 -45
  61. mojo/apps/tasks/rest/tasks.py +24 -10
  62. mojo/apps/tasks/runner.py +283 -18
  63. mojo/apps/tasks/task.py +99 -0
  64. mojo/apps/tasks/tq_handlers.py +118 -0
  65. mojo/decorators/auth.py +6 -1
  66. mojo/decorators/http.py +7 -2
  67. mojo/helpers/aws/__init__.py +41 -0
  68. mojo/helpers/aws/ec2.py +804 -0
  69. mojo/helpers/aws/iam.py +748 -0
  70. mojo/helpers/aws/s3.py +451 -11
  71. mojo/helpers/aws/ses.py +483 -0
  72. mojo/helpers/aws/sns.py +461 -0
  73. mojo/helpers/crypto/__pycache__/hash.cpython-310.pyc +0 -0
  74. mojo/helpers/crypto/__pycache__/sign.cpython-310.pyc +0 -0
  75. mojo/helpers/crypto/__pycache__/utils.cpython-310.pyc +0 -0
  76. mojo/helpers/dates.py +18 -0
  77. mojo/helpers/response.py +6 -2
  78. mojo/helpers/settings/__init__.py +2 -0
  79. mojo/helpers/{settings.py → settings/helper.py} +1 -37
  80. mojo/helpers/settings/parser.py +132 -0
  81. mojo/middleware/logging.py +1 -1
  82. mojo/middleware/mojo.py +5 -0
  83. mojo/models/rest.py +261 -46
  84. mojo/models/secrets.py +13 -4
  85. mojo/serializers/__init__.py +100 -0
  86. mojo/serializers/advanced/README.md +363 -0
  87. mojo/serializers/advanced/__init__.py +247 -0
  88. mojo/serializers/advanced/formats/__init__.py +28 -0
  89. mojo/serializers/advanced/formats/csv.py +416 -0
  90. mojo/serializers/advanced/formats/excel.py +516 -0
  91. mojo/serializers/advanced/formats/json.py +239 -0
  92. mojo/serializers/advanced/formats/localizers.py +509 -0
  93. mojo/serializers/advanced/formats/response.py +485 -0
  94. mojo/serializers/advanced/serializer.py +568 -0
  95. mojo/serializers/manager.py +501 -0
  96. mojo/serializers/optimized.py +618 -0
  97. mojo/serializers/settings_example.py +322 -0
  98. mojo/serializers/{models.py → simple.py} +38 -15
  99. testit/helpers.py +21 -4
  100. django_nativemojo-0.1.10.dist-info/METADATA +0 -96
  101. mojo/apps/metrics/rest/db.py +0 -0
  102. mojo/helpers/aws/setup_email.py +0 -0
  103. mojo/ws4redis/README.md +0 -174
  104. mojo/ws4redis/__init__.py +0 -2
  105. mojo/ws4redis/client.py +0 -283
  106. mojo/ws4redis/connection.py +0 -327
  107. mojo/ws4redis/exceptions.py +0 -32
  108. mojo/ws4redis/redis.py +0 -183
  109. mojo/ws4redis/servers/base.py +0 -86
  110. mojo/ws4redis/servers/django.py +0 -171
  111. mojo/ws4redis/servers/uwsgi.py +0 -63
  112. mojo/ws4redis/settings.py +0 -45
  113. mojo/ws4redis/utf8validator.py +0 -128
  114. mojo/ws4redis/websocket.py +0 -403
  115. {django_nativemojo-0.1.10.dist-info → django_nativemojo-0.1.15.dist-info}/LICENSE +0 -0
  116. {django_nativemojo-0.1.10.dist-info → django_nativemojo-0.1.15.dist-info}/NOTICE +0 -0
  117. {django_nativemojo-0.1.10.dist-info → django_nativemojo-0.1.15.dist-info}/WHEEL +0 -0
  118. /mojo/{ws4redis/servers → apps/aws}/__init__.py +0 -0
  119. /mojo/apps/{fileman/models/render.py → aws/models/__init__.py} +0 -0
  120. /mojo/apps/fileman/{rest/__init__ → migrations/__init__.py} +0 -0
@@ -0,0 +1,501 @@
1
+ """
2
+ Serializer Manager for Django-MOJO
3
+
4
+ Provides a unified interface for switching between different serializers and managing
5
+ serialization strategies across the application. Supports:
6
+
7
+ - Multiple serializer backends (simple, advanced, optimized, custom)
8
+ - Runtime serializer switching
9
+ - Performance monitoring and comparison
10
+ - Configuration via Django settings
11
+ - Fallback mechanisms for robustness
12
+ - Easy integration with MojoModel REST operations
13
+
14
+ Usage:
15
+ # Use default configured serializer
16
+ manager = SerializerManager()
17
+ serializer = manager.get_serializer(instance, graph="list")
18
+
19
+ # Force specific serializer
20
+ serializer = manager.get_serializer(instance, serializer_type="optimized")
21
+
22
+ # Performance comparison
23
+ results = manager.benchmark_serializers(queryset)
24
+ """
25
+
26
+ import time
27
+ import importlib
28
+ from typing import Dict, Any, Optional, Type, Union, List
29
+ from threading import RLock
30
+
31
+ from django.conf import settings
32
+ from django.db.models import QuerySet, Model
33
+ from django.http import HttpResponse
34
+
35
+ from mojo.helpers import logit
36
+
37
+ logger = logit.get_logger("serializer_manager", "serializer_manager.log")
38
+
39
+ # Thread-safe lock for serializer registry operations
40
+ _registry_lock = RLock()
41
+
42
+ # Default serializer configurations
43
+ DEFAULT_SERIALIZERS = {
44
+ 'simple': 'mojo.serializers.simple.GraphSerializer',
45
+ 'optimized': 'mojo.serializers.optimized.OptimizedGraphSerializer',
46
+ 'advanced': 'mojo.serializers.advanced.AdvancedGraphSerializer',
47
+ }
48
+
49
+ # Global serializer registry
50
+ _SERIALIZER_REGISTRY = {}
51
+
52
+ # Performance tracking
53
+ _PERFORMANCE_DATA = {
54
+ 'serializer_usage': {},
55
+ 'performance_history': [],
56
+ 'benchmark_results': {}
57
+ }
58
+
59
+
60
+ class SerializerRegistry:
61
+ """Registry for managing available serializers."""
62
+
63
+ def __init__(self):
64
+ self.serializers = {}
65
+ self.default_serializer = None
66
+ self.lock = RLock()
67
+
68
+ def register(self, name: str, serializer_class_or_path: Union[str, Type],
69
+ description: str = None, is_default: bool = False):
70
+ """
71
+ Register a serializer.
72
+
73
+ :param name: Unique name for the serializer
74
+ :param serializer_class_or_path: Serializer class or import path string
75
+ :param description: Optional description
76
+ :param is_default: Set as default serializer
77
+ """
78
+ with self.lock:
79
+ # Handle string import path
80
+ if isinstance(serializer_class_or_path, str):
81
+ try:
82
+ module_path, class_name = serializer_class_or_path.rsplit('.', 1)
83
+ module = importlib.import_module(module_path)
84
+ serializer_class = getattr(module, class_name)
85
+ except (ImportError, AttributeError) as e:
86
+ logger.error(f"Failed to import serializer '{serializer_class_or_path}': {e}")
87
+ return False
88
+ else:
89
+ serializer_class = serializer_class_or_path
90
+
91
+ self.serializers[name] = {
92
+ 'class': serializer_class,
93
+ 'description': description or f"{name} serializer",
94
+ 'registered_at': time.time()
95
+ }
96
+
97
+ if is_default or self.default_serializer is None:
98
+ self.default_serializer = name
99
+
100
+ logger.info(f"Registered serializer: {name}")
101
+ return True
102
+
103
+ def get(self, name: str):
104
+ """Get serializer class by name."""
105
+ with self.lock:
106
+ serializer_info = self.serializers.get(name)
107
+ return serializer_info['class'] if serializer_info else None
108
+
109
+ def list_serializers(self):
110
+ """List all registered serializers."""
111
+ with self.lock:
112
+ return {
113
+ name: {
114
+ 'description': info['description'],
115
+ 'class_name': info['class'].__name__,
116
+ 'is_default': name == self.default_serializer
117
+ }
118
+ for name, info in self.serializers.items()
119
+ }
120
+
121
+ def get_default(self):
122
+ """Get the default serializer name."""
123
+ with self.lock:
124
+ return self.default_serializer
125
+
126
+ def set_default(self, name: str):
127
+ """Set default serializer."""
128
+ with self.lock:
129
+ if name in self.serializers:
130
+ self.default_serializer = name
131
+ logger.info(f"Default serializer set to: {name}")
132
+ return True
133
+ return False
134
+
135
+
136
+ # Global serializer registry
137
+ _registry = SerializerRegistry()
138
+
139
+
140
+ class SerializerManager:
141
+ """
142
+ Main serializer manager providing unified interface for all serialization operations.
143
+ """
144
+
145
+ def __init__(self, default_serializer: str = None, enable_performance_tracking: bool = True):
146
+ """
147
+ Initialize serializer manager.
148
+
149
+ :param default_serializer: Override default serializer
150
+ :param enable_performance_tracking: Enable performance monitoring
151
+ """
152
+ self.default_serializer = default_serializer
153
+ self.performance_tracking = enable_performance_tracking
154
+ self.registry = _registry
155
+
156
+ # Initialize default serializers if not already done
157
+ self._ensure_default_serializers()
158
+
159
+ # Load configuration from Django settings
160
+ self._load_configuration()
161
+
162
+ def _ensure_default_serializers(self):
163
+ """Ensure default serializers are registered."""
164
+ if not self.registry.serializers:
165
+ for name, import_path in DEFAULT_SERIALIZERS.items():
166
+ self.registry.register(
167
+ name=name,
168
+ serializer_class_or_path=import_path,
169
+ is_default=(name == 'optimized') # Set optimized as default
170
+ )
171
+
172
+ def _load_configuration(self):
173
+ """Load configuration from Django settings."""
174
+ # Get default serializer from settings
175
+ default_from_settings = getattr(settings, 'MOJO_DEFAULT_SERIALIZER', None)
176
+ if default_from_settings and not self.default_serializer:
177
+ self.default_serializer = default_from_settings
178
+
179
+ # Register custom serializers from settings
180
+ custom_serializers = getattr(settings, 'MOJO_CUSTOM_SERIALIZERS', {})
181
+ for name, config in custom_serializers.items():
182
+ if isinstance(config, str):
183
+ # Simple string path
184
+ self.registry.register(name, config)
185
+ elif isinstance(config, dict):
186
+ # Detailed configuration
187
+ self.registry.register(
188
+ name=name,
189
+ serializer_class_or_path=config.get('class'),
190
+ description=config.get('description'),
191
+ is_default=config.get('is_default', False)
192
+ )
193
+
194
+ def get_serializer(self, instance, graph: str = "default", many: bool = None,
195
+ serializer_type: str = None, **kwargs):
196
+ """
197
+ Get appropriate serializer for the given instance and parameters.
198
+
199
+ :param instance: Model instance, QuerySet, or list of objects
200
+ :param graph: Graph configuration name
201
+ :param many: Force many=True for list serialization
202
+ :param serializer_type: Override serializer type
203
+ :param kwargs: Additional serializer arguments
204
+ :return: Configured serializer instance
205
+ """
206
+ # Determine serializer type
207
+ if serializer_type is None:
208
+ serializer_type = self.default_serializer or self.registry.get_default()
209
+
210
+ # Get serializer class
211
+ serializer_class = self.registry.get(serializer_type)
212
+ if serializer_class is None:
213
+ logger.warning(f"Serializer '{serializer_type}' not found, using default")
214
+ serializer_type = self.registry.get_default()
215
+ serializer_class = self.registry.get(serializer_type)
216
+
217
+ if serializer_class is None:
218
+ raise ValueError("No serializer available")
219
+
220
+ # Auto-detect many parameter for QuerySets
221
+ if many is None and isinstance(instance, QuerySet):
222
+ many = True
223
+
224
+ # Track usage for performance monitoring
225
+ if self.performance_tracking:
226
+ self._track_usage(serializer_type, instance)
227
+
228
+ # Create and return serializer instance
229
+ try:
230
+ return serializer_class(instance, graph=graph, many=many, **kwargs)
231
+ except Exception as e:
232
+ logger.error(f"Failed to create serializer '{serializer_type}': {e}")
233
+ # Fallback to simple serializer
234
+ fallback_class = self.registry.get('simple')
235
+ if fallback_class and fallback_class != serializer_class:
236
+ logger.info("Falling back to simple serializer")
237
+ return fallback_class(instance, graph=graph, many=many)
238
+ raise
239
+
240
+ def serialize(self, instance, graph: str = "default", many: bool = None,
241
+ serializer_type: str = None, **kwargs):
242
+ """
243
+ Direct serialization method.
244
+
245
+ :param instance: Object(s) to serialize
246
+ :param graph: Graph configuration
247
+ :param many: Force many=True
248
+ :param serializer_type: Override serializer type
249
+ :param kwargs: Additional arguments
250
+ :return: Serialized data
251
+ """
252
+ serializer = self.get_serializer(
253
+ instance=instance,
254
+ graph=graph,
255
+ many=many,
256
+ serializer_type=serializer_type,
257
+ **kwargs
258
+ )
259
+ return serializer.serialize()
260
+
261
+ def to_json(self, instance, graph: str = "default", many: bool = None,
262
+ serializer_type: str = None, **kwargs):
263
+ """
264
+ Serialize to JSON string.
265
+
266
+ :param instance: Object(s) to serialize
267
+ :param graph: Graph configuration
268
+ :param many: Force many=True
269
+ :param serializer_type: Override serializer type
270
+ :param kwargs: Additional JSON arguments
271
+ :return: JSON string
272
+ """
273
+ serializer = self.get_serializer(
274
+ instance=instance,
275
+ graph=graph,
276
+ many=many,
277
+ serializer_type=serializer_type
278
+ )
279
+ return serializer.to_json(**kwargs)
280
+
281
+ def to_response(self, instance, request, graph: str = "default", many: bool = None,
282
+ serializer_type: str = None, **kwargs):
283
+ """
284
+ Serialize to HTTP response.
285
+
286
+ :param instance: Object(s) to serialize
287
+ :param request: Django request object
288
+ :param graph: Graph configuration
289
+ :param many: Force many=True
290
+ :param serializer_type: Override serializer type
291
+ :param kwargs: Additional response arguments
292
+ :return: HttpResponse
293
+ """
294
+ serializer = self.get_serializer(
295
+ instance=instance,
296
+ graph=graph,
297
+ many=many,
298
+ serializer_type=serializer_type
299
+ )
300
+ return serializer.to_response(request, **kwargs)
301
+
302
+ def benchmark_serializers(self, instance, graph: str = "default",
303
+ serializer_types: List[str] = None, iterations: int = 10):
304
+ """
305
+ Benchmark multiple serializers for performance comparison.
306
+
307
+ :param instance: Test instance or queryset
308
+ :param graph: Graph configuration to test
309
+ :param serializer_types: List of serializers to test (default: all)
310
+ :param iterations: Number of iterations per serializer
311
+ :return: Benchmark results
312
+ """
313
+ if serializer_types is None:
314
+ serializer_types = list(self.registry.list_serializers().keys())
315
+
316
+ results = {}
317
+
318
+ for serializer_type in serializer_types:
319
+ logger.info(f"Benchmarking {serializer_type} serializer...")
320
+
321
+ times = []
322
+ errors = 0
323
+
324
+ for i in range(iterations):
325
+ try:
326
+ start_time = time.perf_counter()
327
+
328
+ serializer = self.get_serializer(
329
+ instance=instance,
330
+ graph=graph,
331
+ serializer_type=serializer_type
332
+ )
333
+ data = serializer.serialize()
334
+ json_output = serializer.to_json()
335
+
336
+ end_time = time.perf_counter()
337
+ times.append(end_time - start_time)
338
+
339
+ except Exception as e:
340
+ logger.error(f"Benchmark error for {serializer_type}: {e}")
341
+ errors += 1
342
+
343
+ if times:
344
+ results[serializer_type] = {
345
+ 'min_time': min(times),
346
+ 'max_time': max(times),
347
+ 'avg_time': sum(times) / len(times),
348
+ 'total_time': sum(times),
349
+ 'iterations': len(times),
350
+ 'errors': errors,
351
+ 'objects_per_second': len(times) / sum(times) if sum(times) > 0 else 0
352
+ }
353
+ else:
354
+ results[serializer_type] = {
355
+ 'error': 'All iterations failed',
356
+ 'errors': errors
357
+ }
358
+
359
+ # Store benchmark results
360
+ if self.performance_tracking:
361
+ _PERFORMANCE_DATA['benchmark_results'][time.time()] = results
362
+
363
+ return results
364
+
365
+ def get_performance_stats(self):
366
+ """Get performance statistics for all serializers."""
367
+ stats = {
368
+ 'usage_stats': _PERFORMANCE_DATA['serializer_usage'].copy(),
369
+ 'registered_serializers': self.registry.list_serializers(),
370
+ 'default_serializer': self.registry.get_default()
371
+ }
372
+
373
+ # Add serializer-specific stats
374
+ for name in self.registry.serializers.keys():
375
+ serializer_class = self.registry.get(name)
376
+ if hasattr(serializer_class, 'get_performance_stats'):
377
+ try:
378
+ stats[f'{name}_stats'] = serializer_class.get_performance_stats()
379
+ except Exception as e:
380
+ logger.warning(f"Failed to get stats for {name}: {e}")
381
+
382
+ return stats
383
+
384
+ def clear_caches(self, serializer_type: str = None):
385
+ """
386
+ Clear caches for specified serializer or all serializers.
387
+
388
+ :param serializer_type: Specific serializer to clear, or None for all
389
+ """
390
+ if serializer_type:
391
+ serializer_class = self.registry.get(serializer_type)
392
+ if serializer_class and hasattr(serializer_class, 'clear_caches'):
393
+ serializer_class.clear_caches()
394
+ logger.info(f"Cleared caches for {serializer_type}")
395
+ else:
396
+ # Clear all serializer caches
397
+ for name in self.registry.serializers.keys():
398
+ serializer_class = self.registry.get(name)
399
+ if serializer_class and hasattr(serializer_class, 'clear_caches'):
400
+ try:
401
+ serializer_class.clear_caches()
402
+ except Exception as e:
403
+ logger.warning(f"Failed to clear cache for {name}: {e}")
404
+ logger.info("Cleared all serializer caches")
405
+
406
+ def register_serializer(self, name: str, serializer_class_or_path: Union[str, Type],
407
+ description: str = None, is_default: bool = False):
408
+ """
409
+ Register a new serializer.
410
+
411
+ :param name: Unique serializer name
412
+ :param serializer_class_or_path: Serializer class or import path
413
+ :param description: Optional description
414
+ :param is_default: Set as default serializer
415
+ :return: True if successful
416
+ """
417
+ return self.registry.register(name, serializer_class_or_path, description, is_default)
418
+
419
+ def set_default_serializer(self, name: str):
420
+ """
421
+ Set the default serializer.
422
+
423
+ :param name: Serializer name
424
+ :return: True if successful
425
+ """
426
+ success = self.registry.set_default(name)
427
+ if success:
428
+ self.default_serializer = name
429
+ return success
430
+
431
+ def _track_usage(self, serializer_type: str, instance):
432
+ """Track serializer usage for performance monitoring."""
433
+ if not self.performance_tracking:
434
+ return
435
+
436
+ usage_key = f"{serializer_type}"
437
+ if usage_key not in _PERFORMANCE_DATA['serializer_usage']:
438
+ _PERFORMANCE_DATA['serializer_usage'][usage_key] = {
439
+ 'count': 0,
440
+ 'last_used': None,
441
+ 'total_objects': 0
442
+ }
443
+
444
+ stats = _PERFORMANCE_DATA['serializer_usage'][usage_key]
445
+ stats['count'] += 1
446
+ stats['last_used'] = time.time()
447
+
448
+ # Count objects being serialized
449
+ if isinstance(instance, QuerySet):
450
+ try:
451
+ stats['total_objects'] += instance.count()
452
+ except Exception:
453
+ stats['total_objects'] += 1
454
+ elif isinstance(instance, (list, tuple)):
455
+ stats['total_objects'] += len(instance)
456
+ else:
457
+ stats['total_objects'] += 1
458
+
459
+
460
+ # Global manager instance
461
+ _default_manager = None
462
+
463
+ def get_serializer_manager():
464
+ """Get the global serializer manager instance."""
465
+ global _default_manager
466
+ if _default_manager is None:
467
+ _default_manager = SerializerManager()
468
+ return _default_manager
469
+
470
+ def register_serializer(name: str, serializer_class_or_path: Union[str, Type],
471
+ description: str = None, is_default: bool = False):
472
+ """Register a serializer globally."""
473
+ return get_serializer_manager().register_serializer(name, serializer_class_or_path, description, is_default)
474
+
475
+ def set_default_serializer(name: str):
476
+ """Set the global default serializer."""
477
+ return get_serializer_manager().set_default_serializer(name)
478
+
479
+ def serialize(instance, graph: str = "default", many: bool = None, serializer_type: str = None, **kwargs):
480
+ """Global serialize function."""
481
+ return get_serializer_manager().serialize(instance, graph, many, serializer_type, **kwargs)
482
+
483
+ def to_json(instance, graph: str = "default", many: bool = None, serializer_type: str = None, **kwargs):
484
+ """Global to_json function."""
485
+ return get_serializer_manager().to_json(instance, graph, many, serializer_type, **kwargs)
486
+
487
+ def to_response(instance, request, graph: str = "default", many: bool = None, serializer_type: str = None, **kwargs):
488
+ """Global to_response function."""
489
+ return get_serializer_manager().to_response(instance, request, graph, many, serializer_type, **kwargs)
490
+
491
+ def get_performance_stats():
492
+ """Get global performance statistics."""
493
+ return get_serializer_manager().get_performance_stats()
494
+
495
+ def clear_serializer_caches(serializer_type: str = None):
496
+ """Clear serializer caches globally."""
497
+ return get_serializer_manager().clear_caches(serializer_type)
498
+
499
+ def benchmark_serializers(instance, graph: str = "default", serializer_types: List[str] = None, iterations: int = 10):
500
+ """Benchmark serializers globally."""
501
+ return get_serializer_manager().benchmark_serializers(instance, graph, serializer_types, iterations)