django-nativemojo 0.1.10__py3-none-any.whl → 0.1.16__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 (276) hide show
  1. django_nativemojo-0.1.16.dist-info/METADATA +138 -0
  2. django_nativemojo-0.1.16.dist-info/RECORD +302 -0
  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 +651 -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/migrations/0006_add_device_tracking_models.py +72 -0
  10. mojo/apps/account/migrations/0007_delete_userdevicelocation.py +16 -0
  11. mojo/apps/account/migrations/0008_userdevicelocation.py +33 -0
  12. mojo/apps/account/migrations/0009_geolocatedip_subnet.py +18 -0
  13. mojo/apps/account/migrations/0010_group_avatar.py +20 -0
  14. mojo/apps/account/migrations/0011_user_org_registereddevice_pushconfig_and_more.py +118 -0
  15. mojo/apps/account/migrations/0012_remove_pushconfig_apns_key_file_and_more.py +21 -0
  16. mojo/apps/account/migrations/0013_pushconfig_test_mode_alter_pushconfig_apns_enabled_and_more.py +28 -0
  17. mojo/apps/account/migrations/0014_notificationdelivery_data_payload_and_more.py +48 -0
  18. mojo/apps/account/models/__init__.py +2 -0
  19. mojo/apps/account/models/device.py +281 -0
  20. mojo/apps/account/models/group.py +319 -15
  21. mojo/apps/account/models/member.py +29 -5
  22. mojo/apps/account/models/push/__init__.py +4 -0
  23. mojo/apps/account/models/push/config.py +112 -0
  24. mojo/apps/account/models/push/delivery.py +93 -0
  25. mojo/apps/account/models/push/device.py +66 -0
  26. mojo/apps/account/models/push/template.py +99 -0
  27. mojo/apps/account/models/user.py +369 -19
  28. mojo/apps/account/rest/__init__.py +2 -0
  29. mojo/apps/account/rest/device.py +39 -0
  30. mojo/apps/account/rest/group.py +9 -0
  31. mojo/apps/account/rest/push.py +187 -0
  32. mojo/apps/account/rest/user.py +100 -6
  33. mojo/apps/account/services/__init__.py +1 -0
  34. mojo/apps/account/services/push.py +363 -0
  35. mojo/apps/aws/migrations/0001_initial.py +206 -0
  36. mojo/apps/aws/migrations/0002_emaildomain_can_recv_emaildomain_can_send_and_more.py +28 -0
  37. mojo/apps/aws/migrations/0003_mailbox_is_domain_default_mailbox_is_system_default_and_more.py +31 -0
  38. mojo/apps/aws/migrations/0004_s3bucket.py +39 -0
  39. mojo/apps/aws/migrations/0005_alter_emaildomain_region_delete_s3bucket.py +21 -0
  40. mojo/apps/aws/models/__init__.py +19 -0
  41. mojo/apps/aws/models/email_attachment.py +99 -0
  42. mojo/apps/aws/models/email_domain.py +218 -0
  43. mojo/apps/aws/models/email_template.py +132 -0
  44. mojo/apps/aws/models/incoming_email.py +197 -0
  45. mojo/apps/aws/models/mailbox.py +288 -0
  46. mojo/apps/aws/models/sent_message.py +175 -0
  47. mojo/apps/aws/rest/__init__.py +7 -0
  48. mojo/apps/aws/rest/email.py +33 -0
  49. mojo/apps/aws/rest/email_ops.py +183 -0
  50. mojo/apps/aws/rest/messages.py +32 -0
  51. mojo/apps/aws/rest/s3.py +64 -0
  52. mojo/apps/aws/rest/send.py +101 -0
  53. mojo/apps/aws/rest/sns.py +403 -0
  54. mojo/apps/aws/rest/templates.py +19 -0
  55. mojo/apps/aws/services/__init__.py +32 -0
  56. mojo/apps/aws/services/email.py +390 -0
  57. mojo/apps/aws/services/email_ops.py +548 -0
  58. mojo/apps/docit/__init__.py +6 -0
  59. mojo/apps/docit/markdown_plugins/syntax_highlight.py +25 -0
  60. mojo/apps/docit/markdown_plugins/toc.py +12 -0
  61. mojo/apps/docit/migrations/0001_initial.py +113 -0
  62. mojo/apps/docit/migrations/0002_alter_book_modified_by_alter_page_modified_by.py +26 -0
  63. mojo/apps/docit/migrations/0003_alter_book_group.py +20 -0
  64. mojo/apps/docit/models/__init__.py +17 -0
  65. mojo/apps/docit/models/asset.py +231 -0
  66. mojo/apps/docit/models/book.py +227 -0
  67. mojo/apps/docit/models/page.py +319 -0
  68. mojo/apps/docit/models/page_revision.py +203 -0
  69. mojo/apps/docit/rest/__init__.py +10 -0
  70. mojo/apps/docit/rest/asset.py +17 -0
  71. mojo/apps/docit/rest/book.py +22 -0
  72. mojo/apps/docit/rest/page.py +22 -0
  73. mojo/apps/docit/rest/page_revision.py +17 -0
  74. mojo/apps/docit/services/__init__.py +11 -0
  75. mojo/apps/docit/services/docit.py +315 -0
  76. mojo/apps/docit/services/markdown.py +44 -0
  77. mojo/apps/fileman/README.md +8 -8
  78. mojo/apps/fileman/backends/base.py +76 -70
  79. mojo/apps/fileman/backends/filesystem.py +86 -86
  80. mojo/apps/fileman/backends/s3.py +409 -108
  81. mojo/apps/fileman/migrations/0001_initial.py +106 -0
  82. mojo/apps/fileman/migrations/0002_filemanager_parent_alter_filemanager_max_file_size.py +24 -0
  83. mojo/apps/fileman/migrations/0003_remove_file_fileman_fil_upload__c4bc35_idx_and_more.py +25 -0
  84. mojo/apps/fileman/migrations/0004_remove_file_original_filename_and_more.py +39 -0
  85. mojo/apps/fileman/migrations/0005_alter_file_upload_token.py +18 -0
  86. mojo/apps/fileman/migrations/0006_file_download_url_filemanager_forever_urls.py +23 -0
  87. mojo/apps/fileman/migrations/0007_remove_filemanager_forever_urls_and_more.py +22 -0
  88. mojo/apps/fileman/migrations/0008_file_category.py +18 -0
  89. mojo/apps/fileman/migrations/0009_rename_file_path_file_storage_file_path.py +18 -0
  90. mojo/apps/fileman/migrations/0010_filerendition.py +33 -0
  91. mojo/apps/fileman/migrations/0011_alter_filerendition_original_file.py +19 -0
  92. mojo/apps/fileman/models/__init__.py +1 -5
  93. mojo/apps/fileman/models/file.py +240 -58
  94. mojo/apps/fileman/models/manager.py +427 -31
  95. mojo/apps/fileman/models/rendition.py +118 -0
  96. mojo/apps/fileman/renderer/__init__.py +111 -0
  97. mojo/apps/fileman/renderer/audio.py +403 -0
  98. mojo/apps/fileman/renderer/base.py +205 -0
  99. mojo/apps/fileman/renderer/document.py +404 -0
  100. mojo/apps/fileman/renderer/image.py +222 -0
  101. mojo/apps/fileman/renderer/utils.py +297 -0
  102. mojo/apps/fileman/renderer/video.py +304 -0
  103. mojo/apps/fileman/rest/__init__.py +1 -18
  104. mojo/apps/fileman/rest/upload.py +22 -32
  105. mojo/apps/fileman/signals.py +58 -0
  106. mojo/apps/fileman/tasks.py +254 -0
  107. mojo/apps/fileman/utils/__init__.py +40 -16
  108. mojo/apps/incident/migrations/0005_incidenthistory.py +39 -0
  109. mojo/apps/incident/migrations/0006_alter_incident_state.py +18 -0
  110. mojo/apps/incident/migrations/0007_event_uid.py +18 -0
  111. mojo/apps/incident/migrations/0008_ticket_ticketnote.py +55 -0
  112. mojo/apps/incident/migrations/0009_incident_status.py +18 -0
  113. mojo/apps/incident/migrations/0010_event_country_code.py +18 -0
  114. mojo/apps/incident/migrations/0011_incident_country_code.py +18 -0
  115. mojo/apps/incident/migrations/0012_alter_incident_status.py +18 -0
  116. mojo/apps/incident/models/__init__.py +2 -0
  117. mojo/apps/incident/models/event.py +35 -0
  118. mojo/apps/incident/models/history.py +36 -0
  119. mojo/apps/incident/models/incident.py +3 -1
  120. mojo/apps/incident/models/ticket.py +62 -0
  121. mojo/apps/incident/reporter.py +21 -1
  122. mojo/apps/incident/rest/__init__.py +1 -0
  123. mojo/apps/incident/rest/event.py +7 -1
  124. mojo/apps/incident/rest/ticket.py +43 -0
  125. mojo/apps/jobs/__init__.py +489 -0
  126. mojo/apps/jobs/adapters.py +24 -0
  127. mojo/apps/jobs/cli.py +616 -0
  128. mojo/apps/jobs/daemon.py +370 -0
  129. mojo/apps/jobs/examples/sample_jobs.py +376 -0
  130. mojo/apps/jobs/examples/webhook_examples.py +203 -0
  131. mojo/apps/jobs/handlers/__init__.py +5 -0
  132. mojo/apps/jobs/handlers/webhook.py +317 -0
  133. mojo/apps/jobs/job_engine.py +734 -0
  134. mojo/apps/jobs/keys.py +203 -0
  135. mojo/apps/jobs/local_queue.py +363 -0
  136. mojo/apps/jobs/management/__init__.py +3 -0
  137. mojo/apps/jobs/management/commands/__init__.py +3 -0
  138. mojo/apps/jobs/manager.py +1327 -0
  139. mojo/apps/jobs/migrations/0001_initial.py +97 -0
  140. mojo/apps/jobs/migrations/0002_alter_job_max_retries_joblog.py +39 -0
  141. mojo/apps/jobs/models/__init__.py +6 -0
  142. mojo/apps/jobs/models/job.py +441 -0
  143. mojo/apps/jobs/rest/__init__.py +2 -0
  144. mojo/apps/jobs/rest/control.py +466 -0
  145. mojo/apps/jobs/rest/jobs.py +421 -0
  146. mojo/apps/jobs/scheduler.py +571 -0
  147. mojo/apps/jobs/services/__init__.py +6 -0
  148. mojo/apps/jobs/services/job_actions.py +465 -0
  149. mojo/apps/jobs/settings.py +209 -0
  150. mojo/apps/logit/migrations/0004_alter_log_level.py +18 -0
  151. mojo/apps/logit/models/log.py +7 -1
  152. mojo/apps/metrics/__init__.py +8 -1
  153. mojo/apps/metrics/redis_metrics.py +198 -0
  154. mojo/apps/metrics/rest/__init__.py +3 -0
  155. mojo/apps/metrics/rest/categories.py +266 -0
  156. mojo/apps/metrics/rest/helpers.py +48 -0
  157. mojo/apps/metrics/rest/permissions.py +99 -0
  158. mojo/apps/metrics/rest/values.py +277 -0
  159. mojo/apps/metrics/utils.py +19 -2
  160. mojo/decorators/auth.py +6 -1
  161. mojo/decorators/http.py +47 -3
  162. mojo/helpers/aws/__init__.py +45 -0
  163. mojo/helpers/aws/ec2.py +804 -0
  164. mojo/helpers/aws/iam.py +748 -0
  165. mojo/helpers/aws/inbound_email.py +309 -0
  166. mojo/helpers/aws/kms.py +413 -0
  167. mojo/helpers/aws/s3.py +451 -11
  168. mojo/helpers/aws/ses.py +483 -0
  169. mojo/helpers/aws/ses_domain.py +959 -0
  170. mojo/helpers/aws/sns.py +461 -0
  171. mojo/helpers/crypto/__init__.py +1 -1
  172. mojo/helpers/crypto/utils.py +15 -0
  173. mojo/helpers/dates.py +18 -0
  174. mojo/helpers/location/__init__.py +2 -0
  175. mojo/helpers/location/countries.py +262 -0
  176. mojo/helpers/location/geolocation.py +196 -0
  177. mojo/helpers/logit.py +37 -0
  178. mojo/helpers/redis/__init__.py +2 -0
  179. mojo/helpers/redis/adapter.py +606 -0
  180. mojo/helpers/redis/client.py +48 -0
  181. mojo/helpers/redis/pool.py +225 -0
  182. mojo/helpers/request.py +8 -0
  183. mojo/helpers/response.py +14 -2
  184. mojo/helpers/settings/__init__.py +2 -0
  185. mojo/helpers/{settings.py → settings/helper.py} +1 -37
  186. mojo/helpers/settings/parser.py +132 -0
  187. mojo/middleware/auth.py +1 -1
  188. mojo/middleware/cors.py +40 -0
  189. mojo/middleware/logging.py +131 -12
  190. mojo/middleware/mojo.py +10 -0
  191. mojo/models/rest.py +494 -65
  192. mojo/models/secrets.py +98 -3
  193. mojo/serializers/__init__.py +106 -0
  194. mojo/serializers/core/__init__.py +90 -0
  195. mojo/serializers/core/cache/__init__.py +121 -0
  196. mojo/serializers/core/cache/backends.py +518 -0
  197. mojo/serializers/core/cache/base.py +102 -0
  198. mojo/serializers/core/cache/disabled.py +181 -0
  199. mojo/serializers/core/cache/memory.py +287 -0
  200. mojo/serializers/core/cache/redis.py +533 -0
  201. mojo/serializers/core/cache/utils.py +454 -0
  202. mojo/serializers/core/manager.py +550 -0
  203. mojo/serializers/core/serializer.py +475 -0
  204. mojo/serializers/examples/settings.py +322 -0
  205. mojo/serializers/formats/csv.py +393 -0
  206. mojo/serializers/formats/localizers.py +509 -0
  207. mojo/serializers/{models.py → simple.py} +38 -15
  208. mojo/serializers/suggested_improvements.md +388 -0
  209. testit/client.py +1 -1
  210. testit/helpers.py +35 -4
  211. testit/runner.py +23 -6
  212. django_nativemojo-0.1.10.dist-info/METADATA +0 -96
  213. django_nativemojo-0.1.10.dist-info/RECORD +0 -194
  214. mojo/apps/metrics/rest/db.py +0 -0
  215. mojo/apps/notify/README.md +0 -91
  216. mojo/apps/notify/README_NOTIFICATIONS.md +0 -566
  217. mojo/apps/notify/admin.py +0 -52
  218. mojo/apps/notify/handlers/example_handlers.py +0 -516
  219. mojo/apps/notify/handlers/ses/__init__.py +0 -25
  220. mojo/apps/notify/handlers/ses/bounce.py +0 -0
  221. mojo/apps/notify/handlers/ses/complaint.py +0 -25
  222. mojo/apps/notify/handlers/ses/message.py +0 -86
  223. mojo/apps/notify/management/commands/__init__.py +0 -1
  224. mojo/apps/notify/management/commands/process_notifications.py +0 -370
  225. mojo/apps/notify/mod +0 -0
  226. mojo/apps/notify/models/__init__.py +0 -12
  227. mojo/apps/notify/models/account.py +0 -128
  228. mojo/apps/notify/models/attachment.py +0 -24
  229. mojo/apps/notify/models/bounce.py +0 -68
  230. mojo/apps/notify/models/complaint.py +0 -40
  231. mojo/apps/notify/models/inbox.py +0 -113
  232. mojo/apps/notify/models/inbox_message.py +0 -173
  233. mojo/apps/notify/models/outbox.py +0 -129
  234. mojo/apps/notify/models/outbox_message.py +0 -288
  235. mojo/apps/notify/models/template.py +0 -30
  236. mojo/apps/notify/providers/aws.py +0 -73
  237. mojo/apps/notify/rest/ses.py +0 -0
  238. mojo/apps/notify/utils/__init__.py +0 -2
  239. mojo/apps/notify/utils/notifications.py +0 -404
  240. mojo/apps/notify/utils/parsing.py +0 -202
  241. mojo/apps/notify/utils/render.py +0 -144
  242. mojo/apps/tasks/README.md +0 -118
  243. mojo/apps/tasks/__init__.py +0 -11
  244. mojo/apps/tasks/manager.py +0 -489
  245. mojo/apps/tasks/rest/__init__.py +0 -2
  246. mojo/apps/tasks/rest/hooks.py +0 -0
  247. mojo/apps/tasks/rest/tasks.py +0 -62
  248. mojo/apps/tasks/runner.py +0 -174
  249. mojo/apps/tasks/tq_handlers.py +0 -14
  250. mojo/helpers/aws/setup_email.py +0 -0
  251. mojo/helpers/redis.py +0 -10
  252. mojo/models/meta.py +0 -262
  253. mojo/ws4redis/README.md +0 -174
  254. mojo/ws4redis/__init__.py +0 -2
  255. mojo/ws4redis/client.py +0 -283
  256. mojo/ws4redis/connection.py +0 -327
  257. mojo/ws4redis/exceptions.py +0 -32
  258. mojo/ws4redis/redis.py +0 -183
  259. mojo/ws4redis/servers/base.py +0 -86
  260. mojo/ws4redis/servers/django.py +0 -171
  261. mojo/ws4redis/servers/uwsgi.py +0 -63
  262. mojo/ws4redis/settings.py +0 -45
  263. mojo/ws4redis/utf8validator.py +0 -128
  264. mojo/ws4redis/websocket.py +0 -403
  265. {django_nativemojo-0.1.10.dist-info → django_nativemojo-0.1.16.dist-info}/LICENSE +0 -0
  266. {django_nativemojo-0.1.10.dist-info → django_nativemojo-0.1.16.dist-info}/NOTICE +0 -0
  267. {django_nativemojo-0.1.10.dist-info → django_nativemojo-0.1.16.dist-info}/WHEEL +0 -0
  268. /mojo/apps/{notify → aws}/__init__.py +0 -0
  269. /mojo/apps/{notify/handlers → aws/migrations}/__init__.py +0 -0
  270. /mojo/apps/{notify/management → docit/markdown_plugins}/__init__.py +0 -0
  271. /mojo/apps/{notify/providers → docit/migrations}/__init__.py +0 -0
  272. /mojo/apps/{notify/rest → fileman/migrations}/__init__.py +0 -0
  273. /mojo/{ws4redis/servers → apps/jobs/examples}/__init__.py +0 -0
  274. /mojo/apps/{fileman/models/render.py → jobs/migrations/__init__.py} +0 -0
  275. /mojo/{serializers → rest}/openapi.py +0 -0
  276. /mojo/{apps/fileman/rest/__init__ → serializers/formats/__init__.py} +0 -0
mojo/models/secrets.py CHANGED
@@ -11,12 +11,18 @@ class MojoSecrets(models.Model):
11
11
 
12
12
  mojo_secrets = models.TextField(blank=True, null=True, default=None)
13
13
  _exposed_secrets = None
14
+ _secrets_changed = False
14
15
 
15
16
  def set_secrets(self, value):
17
+ self.debug("Setting secrets", repr(value))
18
+ if isinstance(value, str):
19
+ value = objict.from_json(value)
16
20
  self._exposed_secrets = merge_dicts(self.secrets, value)
21
+ self._secrets_changed = True
17
22
 
18
23
  def set_secret(self, key, value):
19
24
  self.secrets[key] = value
25
+ self._secrets_changed = True
20
26
 
21
27
  def get_secret(self, key, default=None):
22
28
  return self.secrets.get(key, default)
@@ -24,6 +30,7 @@ class MojoSecrets(models.Model):
24
30
  def clear_secrets(self):
25
31
  self.mojo_secrets = None
26
32
  self._exposed_secrets = objict()
33
+ self._secrets_changed = True
27
34
 
28
35
  @property
29
36
  def secrets(self):
@@ -44,10 +51,79 @@ class MojoSecrets(models.Model):
44
51
  return salt
45
52
 
46
53
  def save_secrets(self):
47
- if self._exposed_secrets:
48
- self.mojo_secrets = crypto.encrypt( self._exposed_secrets, self._get_secrets_password())
54
+ if self._secrets_changed:
55
+ if self._exposed_secrets:
56
+ self.mojo_secrets = crypto.encrypt( self._exposed_secrets, self._get_secrets_password())
57
+ else:
58
+ self.mojo_secrets = None
59
+ self._secrets_changed = False
60
+
61
+ def save(self, *args, **kwargs):
62
+ if self.pk is not None:
63
+ self.save_secrets()
64
+ super().save(*args, **kwargs)
49
65
  else:
50
- self.mojo_secrets = None
66
+ super().save(*args, **kwargs)
67
+ self.save_secrets()
68
+ super().save()
69
+
70
+
71
+
72
+ class KSMSecrets(models.Model):
73
+ """Base model class for adding secrets to a model using AWS KMS (envelope encryption)."""
74
+ class Meta:
75
+ abstract = True
76
+
77
+ mojo_secrets = models.TextField(blank=True, null=True, default=None)
78
+ _exposed_secrets = None
79
+ _secrets_changed = False
80
+ _kms_cache = {}
81
+
82
+ def set_secrets(self, value):
83
+ self.debug("Setting secrets", repr(value))
84
+ if isinstance(value, str):
85
+ value = objict.from_json(value)
86
+ self._exposed_secrets = merge_dicts(self.secrets, value)
87
+ self._secrets_changed = True
88
+
89
+ def set_secret(self, key, value):
90
+ self.secrets[key] = value
91
+ self._secrets_changed = True
92
+
93
+ def get_secret(self, key, default=None):
94
+ return self.secrets.get(key, default)
95
+
96
+ def clear_secrets(self):
97
+ self.mojo_secrets = None
98
+ self._exposed_secrets = objict()
99
+ self._secrets_changed = True
100
+
101
+ @property
102
+ def secrets(self):
103
+ if self._exposed_secrets is not None:
104
+ return self._exposed_secrets
105
+ if self.mojo_secrets is None or self.pk is None:
106
+ self._exposed_secrets = objict()
107
+ return self._exposed_secrets
108
+ if self._exposed_secrets is None:
109
+ try:
110
+ data = self._get_kms().decrypt_dict_field(self._kms_context(), self.mojo_secrets)
111
+ # convert to objict mapping
112
+ self._exposed_secrets = objict.from_dict(data)
113
+ except Exception:
114
+ # On failure, expose empty to avoid leaking details
115
+ self._exposed_secrets = objict()
116
+ return self._exposed_secrets
117
+
118
+ def save_secrets(self):
119
+ if self._secrets_changed:
120
+ if self._exposed_secrets:
121
+ # objict behaves like a dict; KMSHelper accepts dict
122
+ blob = self._get_kms().encrypt_field(self._kms_context(), self._exposed_secrets)
123
+ self.mojo_secrets = blob
124
+ else:
125
+ self.mojo_secrets = None
126
+ self._secrets_changed = False
51
127
 
52
128
  def save(self, *args, **kwargs):
53
129
  if self.pk is not None:
@@ -57,3 +133,22 @@ class MojoSecrets(models.Model):
57
133
  super().save(*args, **kwargs)
58
134
  self.save_secrets()
59
135
  super().save()
136
+
137
+ @classmethod
138
+ def _get_kms(cls):
139
+ kms_key_id = settings.get("KMS_KEY_ID", None)
140
+ region = settings.get("AWS_REGION", settings.get("AWS_DEFAULT_REGION", "us-east-1"))
141
+ if not kms_key_id:
142
+ raise RuntimeError("KMS_KEY_ID must be configured to use KSMSecrets")
143
+ cache_key = (kms_key_id, region)
144
+ helper = cls._kms_cache.get(cache_key)
145
+ if helper is None:
146
+ from mojo.helpers.aws.kms import KMSHelper
147
+ helper = KMSHelper(kms_key_id=kms_key_id, region_name=region)
148
+ cls._kms_cache[cache_key] = helper
149
+ return helper
150
+
151
+ def _kms_context(self):
152
+ # Bind to app_label.Model.<pk>.mojo_secrets for contextual integrity
153
+ app_label = getattr(self._meta, "app_label", self.__class__.__module__.split(".")[0])
154
+ return f"{app_label}.{self.__class__.__name__}.{self.pk}.mojo_secrets"
@@ -0,0 +1,106 @@
1
+ """
2
+ Django-MOJO Serializers Package
3
+
4
+ Provides high-performance serialization for Django models with RestMeta.GRAPHS support.
5
+ Includes multiple serializer backends optimized for different use cases:
6
+
7
+ - OptimizedGraphSerializer: Ultra-fast with intelligent caching (default)
8
+ - GraphSerializer: Simple and reliable fallback
9
+ - AdvancedGraphSerializer: Feature-rich with multiple format support
10
+
11
+ Usage:
12
+ from mojo.serializers import serialize, to_json, to_response
13
+
14
+ # Quick serialization
15
+ data = serialize(instance, graph="detail")
16
+ json_str = to_json(queryset, graph="list")
17
+ response = to_response(instance, request, graph="default")
18
+
19
+ # Direct serializer access
20
+ from mojo.serializers import OptimizedGraphSerializer
21
+ serializer = OptimizedGraphSerializer(instance, graph="detail")
22
+ data = serializer.serialize()
23
+ """
24
+
25
+ # Core serializer classes
26
+ from .simple import GraphSerializer
27
+
28
+ # New optimized core system (default)
29
+ from .core import (
30
+ OptimizedGraphSerializer,
31
+ SerializerManager,
32
+ get_serializer_manager,
33
+ register_serializer,
34
+ set_default_serializer,
35
+ serialize,
36
+ to_json,
37
+ to_response,
38
+ get_performance_stats,
39
+ clear_serializer_caches,
40
+ benchmark_serializers,
41
+ HAS_UJSON,
42
+ UJSON_VERSION
43
+ )
44
+
45
+ # Advanced serializer (optional - may not be available)
46
+ try:
47
+ from .advanced import AdvancedGraphSerializer
48
+ except ImportError:
49
+ AdvancedGraphSerializer = None
50
+
51
+ # Version and metadata
52
+ __version__ = "2.0.0"
53
+ __author__ = "Django-MOJO Team"
54
+
55
+ # Default exports
56
+ __all__ = [
57
+ # Core serializer classes
58
+ 'GraphSerializer',
59
+ 'OptimizedGraphSerializer',
60
+ 'AdvancedGraphSerializer',
61
+
62
+ # Manager
63
+ 'SerializerManager',
64
+ 'get_serializer_manager',
65
+
66
+ # Registration functions
67
+ 'register_serializer',
68
+ 'set_default_serializer',
69
+
70
+ # Convenience functions
71
+ 'serialize',
72
+ 'to_json',
73
+ 'to_response',
74
+
75
+ # Performance monitoring
76
+ 'get_performance_stats',
77
+ 'clear_serializer_caches',
78
+ 'benchmark_serializers',
79
+
80
+ # Performance info
81
+ 'HAS_UJSON',
82
+ 'UJSON_VERSION',
83
+ ]
84
+
85
+ # Initialize default manager on import
86
+ _manager = get_serializer_manager()
87
+
88
+ # Convenience shortcuts at package level
89
+ def get_serializer(instance, graph="default", many=None, serializer_type=None, **kwargs):
90
+ """Get configured serializer instance."""
91
+ return _manager.get_serializer(instance, graph, many, serializer_type, **kwargs)
92
+
93
+ def list_serializers():
94
+ """List all registered serializers."""
95
+ return _manager.registry.list_serializers()
96
+
97
+ def get_default_serializer():
98
+ """Get the current default serializer name."""
99
+ return _manager.registry.get_default()
100
+
101
+ # Add shortcuts to exports
102
+ __all__.extend([
103
+ 'get_serializer',
104
+ 'list_serializers',
105
+ 'get_default_serializer'
106
+ ])
@@ -0,0 +1,90 @@
1
+ """
2
+ Django-MOJO Core Serializers
3
+
4
+ High-performance serialization system with intelligent caching and RestMeta.GRAPHS support.
5
+ This is the optimized serializer implementation with pluggable cache backends.
6
+
7
+ Main Components:
8
+ - OptimizedGraphSerializer: Ultra-fast serializer with smart caching
9
+ - SerializerManager: Unified interface for all serializer backends
10
+ - Cache backends: Memory and Redis-based caching systems
11
+
12
+ Usage:
13
+ from mojo.serializers.core import OptimizedGraphSerializer, SerializerManager
14
+
15
+ # Direct usage
16
+ serializer = OptimizedGraphSerializer(instance, graph="detail")
17
+ data = serializer.serialize()
18
+
19
+ # Via manager
20
+ manager = SerializerManager()
21
+ serializer = manager.get_serializer(instance, graph="list")
22
+ """
23
+
24
+ # Import core components
25
+ from .serializer import OptimizedGraphSerializer
26
+ from .manager import (
27
+ SerializerManager,
28
+ get_serializer_manager,
29
+ register_serializer,
30
+ set_default_serializer,
31
+ serialize,
32
+ to_json,
33
+ to_response,
34
+ get_performance_stats,
35
+ clear_serializer_caches,
36
+ benchmark_serializers,
37
+ list_serializers,
38
+ HAS_UJSON,
39
+ UJSON_VERSION
40
+ )
41
+
42
+ # Import cache system
43
+ from .cache import (
44
+ get_cache_backend,
45
+ get_cache_key,
46
+ get_model_cache_ttl,
47
+ get_cache_stats,
48
+ clear_all_caches,
49
+ HAS_UJSON,
50
+ UJSON_VERSION
51
+ )
52
+
53
+ # Core serializer exports
54
+ __all__ = [
55
+ # Main serializer
56
+ 'OptimizedGraphSerializer',
57
+
58
+ # Manager
59
+ 'SerializerManager',
60
+ 'get_serializer_manager',
61
+
62
+ # Registration functions
63
+ 'register_serializer',
64
+ 'set_default_serializer',
65
+
66
+ # Convenience functions
67
+ 'serialize',
68
+ 'to_json',
69
+ 'to_response',
70
+
71
+ # Performance monitoring
72
+ 'get_performance_stats',
73
+ 'clear_serializer_caches',
74
+ 'benchmark_serializers',
75
+ 'list_serializers',
76
+
77
+ # Cache system
78
+ 'get_cache_backend',
79
+ 'get_cache_key',
80
+ 'get_model_cache_ttl',
81
+ 'get_cache_stats',
82
+ 'clear_all_caches',
83
+
84
+ # Performance info
85
+ 'HAS_UJSON',
86
+ 'UJSON_VERSION',
87
+ ]
88
+
89
+ # Version info
90
+ __version__ = "1.0.0"
@@ -0,0 +1,121 @@
1
+ """
2
+ Django-MOJO Cache System for Serializers
3
+
4
+ Provides pluggable cache backends for high-performance serialization with intelligent
5
+ TTL management based on RestMeta.GRAPHS configuration.
6
+
7
+ Supported Backends:
8
+ - MemoryCacheBackend: In-process LRU cache with TTL support
9
+ - RedisCacheBackend: Distributed Redis-based caching (future)
10
+ - DisabledCacheBackend: No-op cache for development/testing
11
+
12
+ Key Features:
13
+ - RestMeta.cache_ttl configuration per model/graph
14
+ - LRU eviction with configurable size limits
15
+ - JSON serialization for Redis compatibility
16
+ - Thread-safe operations
17
+ - Safe defaults (cache_ttl=0 means no caching)
18
+
19
+ Usage:
20
+ from mojo.serializers.core.cache import get_cache_backend
21
+
22
+ cache = get_cache_backend()
23
+
24
+ # Get cached item (returns None if not found/expired)
25
+ data = cache.get("Event_123_default")
26
+
27
+ # Set with TTL from RestMeta configuration
28
+ cache.set("Event_123_default", serialized_data, ttl=300)
29
+
30
+ Configuration:
31
+ MOJO_SERIALIZER_CACHE = {
32
+ 'backend': 'memory', # 'memory', 'redis', 'disabled'
33
+ 'memory': {
34
+ 'max_size': 5000,
35
+ 'enable_stats': True
36
+ },
37
+ 'redis': { # Future implementation
38
+ 'host': 'localhost',
39
+ 'port': 6379,
40
+ 'key_prefix': 'mojo:serializer:'
41
+ }
42
+ }
43
+
44
+ RestMeta Configuration:
45
+ class MyModel(MojoModel):
46
+ class RestMeta:
47
+ GRAPHS = {
48
+ "default": {
49
+ "fields": ["id", "name"],
50
+ "cache_ttl": 300 # 5 minutes
51
+ },
52
+ "realtime": {
53
+ "fields": ["id", "status"],
54
+ "cache_ttl": 0 # No caching (default)
55
+ }
56
+ }
57
+ """
58
+
59
+ from .base import CacheBackend
60
+ from .memory import MemoryCacheBackend
61
+ from .redis import RedisCacheBackend
62
+ from .disabled import DisabledCacheBackend
63
+ from .backends import (
64
+ get_cache_backend,
65
+ create_cache_backend,
66
+ reset_cache_backend,
67
+ get_available_backends,
68
+ test_backend_connectivity,
69
+ get_cache_health,
70
+ validate_cache_config
71
+ )
72
+
73
+ from .utils import (
74
+ get_cache_key,
75
+ get_model_cache_ttl,
76
+ get_cache_stats,
77
+ clear_all_caches
78
+ )
79
+
80
+ # Check ujson availability for performance optimization
81
+ try:
82
+ import ujson
83
+ HAS_UJSON = True
84
+ UJSON_VERSION = getattr(ujson, '__version__', 'unknown')
85
+ except ImportError:
86
+ ujson = None
87
+ HAS_UJSON = False
88
+ UJSON_VERSION = None
89
+
90
+ # Main exports
91
+ __all__ = [
92
+ # Backend classes
93
+ 'CacheBackend',
94
+ 'MemoryCacheBackend',
95
+ 'RedisCacheBackend',
96
+ 'DisabledCacheBackend',
97
+
98
+ # Factory functions
99
+ 'get_cache_backend',
100
+ 'create_cache_backend',
101
+ 'reset_cache_backend',
102
+
103
+ # Backend management
104
+ 'get_available_backends',
105
+ 'test_backend_connectivity',
106
+ 'get_cache_health',
107
+ 'validate_cache_config',
108
+
109
+ # Utilities
110
+ 'get_cache_key',
111
+ 'get_model_cache_ttl',
112
+ 'get_cache_stats',
113
+ 'clear_all_caches',
114
+
115
+ # Performance info
116
+ 'HAS_UJSON',
117
+ 'UJSON_VERSION',
118
+ ]
119
+
120
+ # Version info
121
+ __version__ = "1.0.0"