django-nativemojo 0.1.15__py3-none-any.whl → 0.1.17__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 (221) hide show
  1. {django_nativemojo-0.1.15.dist-info → django_nativemojo-0.1.17.dist-info}/METADATA +3 -2
  2. django_nativemojo-0.1.17.dist-info/RECORD +302 -0
  3. mojo/__init__.py +1 -1
  4. mojo/apps/account/management/commands/serializer_admin.py +121 -1
  5. mojo/apps/account/migrations/0006_add_device_tracking_models.py +72 -0
  6. mojo/apps/account/migrations/0007_delete_userdevicelocation.py +16 -0
  7. mojo/apps/account/migrations/0008_userdevicelocation.py +33 -0
  8. mojo/apps/account/migrations/0009_geolocatedip_subnet.py +18 -0
  9. mojo/apps/account/migrations/0010_group_avatar.py +20 -0
  10. mojo/apps/account/migrations/0011_user_org_registereddevice_pushconfig_and_more.py +118 -0
  11. mojo/apps/account/migrations/0012_remove_pushconfig_apns_key_file_and_more.py +21 -0
  12. mojo/apps/account/migrations/0013_pushconfig_test_mode_alter_pushconfig_apns_enabled_and_more.py +28 -0
  13. mojo/apps/account/migrations/0014_notificationdelivery_data_payload_and_more.py +48 -0
  14. mojo/apps/account/models/__init__.py +2 -0
  15. mojo/apps/account/models/device.py +279 -0
  16. mojo/apps/account/models/group.py +294 -8
  17. mojo/apps/account/models/member.py +14 -1
  18. mojo/apps/account/models/push/__init__.py +4 -0
  19. mojo/apps/account/models/push/config.py +112 -0
  20. mojo/apps/account/models/push/delivery.py +93 -0
  21. mojo/apps/account/models/push/device.py +66 -0
  22. mojo/apps/account/models/push/template.py +99 -0
  23. mojo/apps/account/models/user.py +190 -17
  24. mojo/apps/account/rest/__init__.py +2 -0
  25. mojo/apps/account/rest/device.py +39 -0
  26. mojo/apps/account/rest/group.py +8 -0
  27. mojo/apps/account/rest/push.py +187 -0
  28. mojo/apps/account/rest/user.py +95 -5
  29. mojo/apps/account/services/__init__.py +1 -0
  30. mojo/apps/account/services/push.py +363 -0
  31. mojo/apps/aws/migrations/0001_initial.py +206 -0
  32. mojo/apps/aws/migrations/0002_emaildomain_can_recv_emaildomain_can_send_and_more.py +28 -0
  33. mojo/apps/aws/migrations/0003_mailbox_is_domain_default_mailbox_is_system_default_and_more.py +31 -0
  34. mojo/apps/aws/migrations/0004_s3bucket.py +39 -0
  35. mojo/apps/aws/migrations/0005_alter_emaildomain_region_delete_s3bucket.py +21 -0
  36. mojo/apps/aws/models/__init__.py +19 -0
  37. mojo/apps/aws/models/email_attachment.py +99 -0
  38. mojo/apps/aws/models/email_domain.py +218 -0
  39. mojo/apps/aws/models/email_template.py +132 -0
  40. mojo/apps/aws/models/incoming_email.py +197 -0
  41. mojo/apps/aws/models/mailbox.py +288 -0
  42. mojo/apps/aws/models/sent_message.py +175 -0
  43. mojo/apps/aws/rest/__init__.py +6 -0
  44. mojo/apps/aws/rest/email.py +33 -0
  45. mojo/apps/aws/rest/email_ops.py +183 -0
  46. mojo/apps/aws/rest/messages.py +32 -0
  47. mojo/apps/aws/rest/send.py +101 -0
  48. mojo/apps/aws/rest/sns.py +403 -0
  49. mojo/apps/aws/rest/templates.py +19 -0
  50. mojo/apps/aws/services/__init__.py +32 -0
  51. mojo/apps/aws/services/email.py +390 -0
  52. mojo/apps/aws/services/email_ops.py +548 -0
  53. mojo/apps/docit/__init__.py +6 -0
  54. mojo/apps/docit/markdown_plugins/syntax_highlight.py +25 -0
  55. mojo/apps/docit/markdown_plugins/toc.py +12 -0
  56. mojo/apps/docit/migrations/0001_initial.py +113 -0
  57. mojo/apps/docit/migrations/0002_alter_book_modified_by_alter_page_modified_by.py +26 -0
  58. mojo/apps/docit/migrations/0003_alter_book_group.py +20 -0
  59. mojo/apps/docit/models/__init__.py +17 -0
  60. mojo/apps/docit/models/asset.py +231 -0
  61. mojo/apps/docit/models/book.py +227 -0
  62. mojo/apps/docit/models/page.py +319 -0
  63. mojo/apps/docit/models/page_revision.py +203 -0
  64. mojo/apps/docit/rest/__init__.py +10 -0
  65. mojo/apps/docit/rest/asset.py +17 -0
  66. mojo/apps/docit/rest/book.py +22 -0
  67. mojo/apps/docit/rest/page.py +22 -0
  68. mojo/apps/docit/rest/page_revision.py +17 -0
  69. mojo/apps/docit/services/__init__.py +11 -0
  70. mojo/apps/docit/services/docit.py +315 -0
  71. mojo/apps/docit/services/markdown.py +44 -0
  72. mojo/apps/fileman/backends/s3.py +209 -0
  73. mojo/apps/fileman/models/file.py +45 -9
  74. mojo/apps/fileman/models/manager.py +269 -3
  75. mojo/apps/incident/migrations/0007_event_uid.py +18 -0
  76. mojo/apps/incident/migrations/0008_ticket_ticketnote.py +55 -0
  77. mojo/apps/incident/migrations/0009_incident_status.py +18 -0
  78. mojo/apps/incident/migrations/0010_event_country_code.py +18 -0
  79. mojo/apps/incident/migrations/0011_incident_country_code.py +18 -0
  80. mojo/apps/incident/migrations/0012_alter_incident_status.py +18 -0
  81. mojo/apps/incident/models/__init__.py +1 -0
  82. mojo/apps/incident/models/event.py +35 -0
  83. mojo/apps/incident/models/incident.py +2 -0
  84. mojo/apps/incident/models/ticket.py +62 -0
  85. mojo/apps/incident/reporter.py +21 -3
  86. mojo/apps/incident/rest/__init__.py +1 -0
  87. mojo/apps/incident/rest/ticket.py +43 -0
  88. mojo/apps/jobs/__init__.py +489 -0
  89. mojo/apps/jobs/adapters.py +24 -0
  90. mojo/apps/jobs/cli.py +616 -0
  91. mojo/apps/jobs/daemon.py +370 -0
  92. mojo/apps/jobs/examples/sample_jobs.py +376 -0
  93. mojo/apps/jobs/examples/webhook_examples.py +203 -0
  94. mojo/apps/jobs/handlers/__init__.py +5 -0
  95. mojo/apps/jobs/handlers/webhook.py +317 -0
  96. mojo/apps/jobs/job_engine.py +734 -0
  97. mojo/apps/jobs/keys.py +203 -0
  98. mojo/apps/jobs/local_queue.py +363 -0
  99. mojo/apps/jobs/management/__init__.py +3 -0
  100. mojo/apps/jobs/management/commands/__init__.py +3 -0
  101. mojo/apps/jobs/manager.py +1327 -0
  102. mojo/apps/jobs/migrations/0001_initial.py +97 -0
  103. mojo/apps/jobs/migrations/0002_alter_job_max_retries_joblog.py +39 -0
  104. mojo/apps/jobs/models/__init__.py +6 -0
  105. mojo/apps/jobs/models/job.py +441 -0
  106. mojo/apps/jobs/rest/__init__.py +2 -0
  107. mojo/apps/jobs/rest/control.py +466 -0
  108. mojo/apps/jobs/rest/jobs.py +421 -0
  109. mojo/apps/jobs/scheduler.py +571 -0
  110. mojo/apps/jobs/services/__init__.py +6 -0
  111. mojo/apps/jobs/services/job_actions.py +465 -0
  112. mojo/apps/jobs/settings.py +209 -0
  113. mojo/apps/logit/models/log.py +3 -0
  114. mojo/apps/metrics/__init__.py +8 -1
  115. mojo/apps/metrics/redis_metrics.py +198 -0
  116. mojo/apps/metrics/rest/__init__.py +3 -0
  117. mojo/apps/metrics/rest/categories.py +266 -0
  118. mojo/apps/metrics/rest/helpers.py +48 -0
  119. mojo/apps/metrics/rest/permissions.py +99 -0
  120. mojo/apps/metrics/rest/values.py +277 -0
  121. mojo/apps/metrics/utils.py +17 -0
  122. mojo/decorators/http.py +40 -1
  123. mojo/helpers/aws/__init__.py +11 -7
  124. mojo/helpers/aws/inbound_email.py +309 -0
  125. mojo/helpers/aws/kms.py +413 -0
  126. mojo/helpers/aws/ses_domain.py +959 -0
  127. mojo/helpers/crypto/__init__.py +1 -1
  128. mojo/helpers/crypto/utils.py +15 -0
  129. mojo/helpers/location/__init__.py +2 -0
  130. mojo/helpers/location/countries.py +262 -0
  131. mojo/helpers/location/geolocation.py +196 -0
  132. mojo/helpers/logit.py +37 -0
  133. mojo/helpers/redis/__init__.py +2 -0
  134. mojo/helpers/redis/adapter.py +606 -0
  135. mojo/helpers/redis/client.py +48 -0
  136. mojo/helpers/redis/pool.py +225 -0
  137. mojo/helpers/request.py +8 -0
  138. mojo/helpers/response.py +8 -0
  139. mojo/middleware/auth.py +1 -1
  140. mojo/middleware/cors.py +40 -0
  141. mojo/middleware/logging.py +131 -12
  142. mojo/middleware/mojo.py +5 -0
  143. mojo/models/rest.py +271 -57
  144. mojo/models/secrets.py +86 -0
  145. mojo/serializers/__init__.py +16 -10
  146. mojo/serializers/core/__init__.py +90 -0
  147. mojo/serializers/core/cache/__init__.py +121 -0
  148. mojo/serializers/core/cache/backends.py +518 -0
  149. mojo/serializers/core/cache/base.py +102 -0
  150. mojo/serializers/core/cache/disabled.py +181 -0
  151. mojo/serializers/core/cache/memory.py +287 -0
  152. mojo/serializers/core/cache/redis.py +533 -0
  153. mojo/serializers/core/cache/utils.py +454 -0
  154. mojo/serializers/{manager.py → core/manager.py} +53 -4
  155. mojo/serializers/core/serializer.py +475 -0
  156. mojo/serializers/{advanced/formats → formats}/csv.py +116 -139
  157. mojo/serializers/suggested_improvements.md +388 -0
  158. testit/client.py +1 -1
  159. testit/helpers.py +14 -0
  160. testit/runner.py +23 -6
  161. django_nativemojo-0.1.15.dist-info/RECORD +0 -234
  162. mojo/apps/notify/README.md +0 -91
  163. mojo/apps/notify/README_NOTIFICATIONS.md +0 -566
  164. mojo/apps/notify/admin.py +0 -52
  165. mojo/apps/notify/handlers/example_handlers.py +0 -516
  166. mojo/apps/notify/handlers/ses/__init__.py +0 -25
  167. mojo/apps/notify/handlers/ses/complaint.py +0 -25
  168. mojo/apps/notify/handlers/ses/message.py +0 -86
  169. mojo/apps/notify/management/commands/__init__.py +0 -1
  170. mojo/apps/notify/management/commands/process_notifications.py +0 -370
  171. mojo/apps/notify/mod +0 -0
  172. mojo/apps/notify/models/__init__.py +0 -12
  173. mojo/apps/notify/models/account.py +0 -128
  174. mojo/apps/notify/models/attachment.py +0 -24
  175. mojo/apps/notify/models/bounce.py +0 -68
  176. mojo/apps/notify/models/complaint.py +0 -40
  177. mojo/apps/notify/models/inbox.py +0 -113
  178. mojo/apps/notify/models/inbox_message.py +0 -173
  179. mojo/apps/notify/models/outbox.py +0 -129
  180. mojo/apps/notify/models/outbox_message.py +0 -288
  181. mojo/apps/notify/models/template.py +0 -30
  182. mojo/apps/notify/providers/aws.py +0 -73
  183. mojo/apps/notify/rest/ses.py +0 -0
  184. mojo/apps/notify/utils/__init__.py +0 -2
  185. mojo/apps/notify/utils/notifications.py +0 -404
  186. mojo/apps/notify/utils/parsing.py +0 -202
  187. mojo/apps/notify/utils/render.py +0 -144
  188. mojo/apps/tasks/README.md +0 -118
  189. mojo/apps/tasks/__init__.py +0 -44
  190. mojo/apps/tasks/manager.py +0 -644
  191. mojo/apps/tasks/rest/__init__.py +0 -2
  192. mojo/apps/tasks/rest/hooks.py +0 -0
  193. mojo/apps/tasks/rest/tasks.py +0 -76
  194. mojo/apps/tasks/runner.py +0 -439
  195. mojo/apps/tasks/task.py +0 -99
  196. mojo/apps/tasks/tq_handlers.py +0 -132
  197. mojo/helpers/crypto/__pycache__/hash.cpython-310.pyc +0 -0
  198. mojo/helpers/crypto/__pycache__/sign.cpython-310.pyc +0 -0
  199. mojo/helpers/crypto/__pycache__/utils.cpython-310.pyc +0 -0
  200. mojo/helpers/redis.py +0 -10
  201. mojo/models/meta.py +0 -262
  202. mojo/serializers/advanced/README.md +0 -363
  203. mojo/serializers/advanced/__init__.py +0 -247
  204. mojo/serializers/advanced/formats/__init__.py +0 -28
  205. mojo/serializers/advanced/formats/excel.py +0 -516
  206. mojo/serializers/advanced/formats/json.py +0 -239
  207. mojo/serializers/advanced/formats/response.py +0 -485
  208. mojo/serializers/advanced/serializer.py +0 -568
  209. mojo/serializers/optimized.py +0 -618
  210. {django_nativemojo-0.1.15.dist-info → django_nativemojo-0.1.17.dist-info}/LICENSE +0 -0
  211. {django_nativemojo-0.1.15.dist-info → django_nativemojo-0.1.17.dist-info}/NOTICE +0 -0
  212. {django_nativemojo-0.1.15.dist-info → django_nativemojo-0.1.17.dist-info}/WHEEL +0 -0
  213. /mojo/apps/{notify → aws/migrations}/__init__.py +0 -0
  214. /mojo/apps/{notify/handlers → docit/markdown_plugins}/__init__.py +0 -0
  215. /mojo/apps/{notify/management → docit/migrations}/__init__.py +0 -0
  216. /mojo/apps/{notify/providers → jobs/examples}/__init__.py +0 -0
  217. /mojo/apps/{notify/rest → jobs/migrations}/__init__.py +0 -0
  218. /mojo/{serializers → rest}/openapi.py +0 -0
  219. /mojo/serializers/{settings_example.py → examples/settings.py} +0 -0
  220. /mojo/{apps/notify/handlers/ses/bounce.py → serializers/formats/__init__.py} +0 -0
  221. /mojo/serializers/{advanced/formats → formats}/localizers.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: django-nativemojo
3
- Version: 0.1.15
3
+ Version: 0.1.17
4
4
  Summary: A REST framework for DJANGO with some extra apps that make it easy to provide a secure robust graph like RESIT API.
5
5
  License: MIT
6
6
  Author: MOJO Dev Team
@@ -14,10 +14,11 @@ Classifier: Programming Language :: Python :: 3.11
14
14
  Classifier: Programming Language :: Python :: 3.12
15
15
  Classifier: Programming Language :: Python :: 3.13
16
16
  Requires-Dist: django (>=4.2.18,<6.0.0)
17
- Requires-Dist: django-cors-headers (>=4.7.0,<5.0.0)
18
17
  Requires-Dist: faker (>=35.2.0,<36.0.0)
19
18
  Requires-Dist: gevent (>=25.5.1,<26.0.0)
19
+ Requires-Dist: mistune (>=3.0.2,<4.0.0)
20
20
  Requires-Dist: pycryptodome (>=3.21.0,<4.0.0)
21
+ Requires-Dist: pygments (>=2.18.0,<3.0.0)
21
22
  Requires-Dist: pyjwt (>=2.10.1,<3.0.0)
22
23
  Requires-Dist: pyobjict (>=2.0.2,<4.0.0)
23
24
  Requires-Dist: pytz (>=2025.1,<2026.0)
@@ -0,0 +1,302 @@
1
+ mojo/__init__.py,sha256=l3KDedy4Wqw4d58E6wYfwI7_tHYcfa9h0puyYad_I_M,71
2
+ mojo/apps/account/__init__.py,sha256=RwxmQqhA0Pub7VSpEHplzPYjfPBBzioocJeQ8pCNeZ4,46
3
+ mojo/apps/account/admin.py,sha256=sE4GxFX9-g-vvNWf22LOqlbQdKK47O9sKP-ohdBpmiE,3026
4
+ mojo/apps/account/apps.py,sha256=CCK2aJu19BpDq_uDI8DIqJFbRmfudzY9KZWahcbYLbE,539
5
+ mojo/apps/account/management/__init__.py,sha256=vSTSprFOr42paP838wrW23zVG44yA0koBfInXVwKQ0A,121
6
+ mojo/apps/account/management/commands/__init__.py,sha256=QsFr7gQcuPOvlg_VvSRnhQV-meDaqkCufBjucsLEaPI,199
7
+ mojo/apps/account/management/commands/serializer_admin.py,sha256=rAxayxJVrOPLQKsX2CzHOd2WgsCyC7hjXn1yNyIqZjM,24666
8
+ mojo/apps/account/migrations/0001_initial.py,sha256=qOwAHtdgyTI-ZGGOnC2ZUn-NSqlyp1z5c6uXvCZBbNE,4220
9
+ mojo/apps/account/migrations/0002_user_is_email_verified_user_is_phone_verified.py,sha256=tBGQ9p7ADhFGGTOXDBslXK5Q4igfpbjI3j1IXqq5064,549
10
+ mojo/apps/account/migrations/0003_group_mojo_secrets_user_mojo_secrets.py,sha256=il2zEdYBGgnUa1ybes3AGPx1RykenlnXr-1nIlhVawU,616
11
+ mojo/apps/account/migrations/0004_user_avatar.py,sha256=yUfyY7nOWIZrw2EfuGmrFbWMr40fW117dpFw3gVLXDI,589
12
+ mojo/apps/account/migrations/0005_group_last_activity.py,sha256=l68nR0UoewXAonqKdbbzB8k4BqHQPuZZj1MmAWZ8Ryc,413
13
+ mojo/apps/account/migrations/0006_add_device_tracking_models.py,sha256=_G6IC_9NS4Vmv_MLwdV1SuNuULxZopnpBT1LeYaFrrU,3944
14
+ mojo/apps/account/migrations/0007_delete_userdevicelocation.py,sha256=-bvKXfoCXsjdLLgTpOvpD788_5nsS6OIkWgpmBqfGQo,316
15
+ mojo/apps/account/migrations/0008_userdevicelocation.py,sha256=R6q2t6HySmIbkT2tk2LMs-O-zW-s0ebt4squ1fACBFU,1492
16
+ mojo/apps/account/migrations/0009_geolocatedip_subnet.py,sha256=K6b2mQsj71fgjM2e_5LcAZwfIHPWmAPm1VwIsdU5LOA,431
17
+ mojo/apps/account/migrations/0010_group_avatar.py,sha256=sq-bzkGR7IyODkpOIm09qCdWTkbX9rMNkNxM3tccaVQ,573
18
+ mojo/apps/account/migrations/0011_user_org_registereddevice_pushconfig_and_more.py,sha256=94XeRJqJs4xB1bt1r7cICP8kTNh_MorJ-RFVppvVRxg,7828
19
+ mojo/apps/account/migrations/0012_remove_pushconfig_apns_key_file_and_more.py,sha256=Jb8WSyLuDarF-7OJfDqp0gUQee4YG14CCDFNM0yhdfA,482
20
+ mojo/apps/account/migrations/0013_pushconfig_test_mode_alter_pushconfig_apns_enabled_and_more.py,sha256=0VfBEp4JpXTN0OIKiRcVby8jR60MB46tuyBL_dXTpI4,949
21
+ mojo/apps/account/migrations/0014_notificationdelivery_data_payload_and_more.py,sha256=TFRGWd1_pKetvIIx3jTkuy1YpM7x8ycTKBHDt-ZdjFQ,1783
22
+ mojo/apps/account/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
+ mojo/apps/account/models/__init__.py,sha256=TYLsLPqurKYNFqqZbOnQzukQLHWe0vznJmZpQ5ezdMw,236
24
+ mojo/apps/account/models/device.py,sha256=78NVqKlvJ-4jNfZcWstvwsQ79xccv4YZJAj95gfbS0c,10361
25
+ mojo/apps/account/models/group.py,sha256=ZNHlG6nut72p2qG2wki5O9v31tx2wdiIG3ezWwFr7d8,13086
26
+ mojo/apps/account/models/member.py,sha256=7H78AgA1WAnqyggH0SolnyfUJHsvHVVyzdk0FMJX4mE,4097
27
+ mojo/apps/account/models/pkey.py,sha256=sSHixJTi7HwjJ-p3CB2UePGQLb0zV4UshS01xi8uykE,687
28
+ mojo/apps/account/models/push/__init__.py,sha256=7goek0WV4Jf5CaSriQKAR6YTnBwOS015AdzhD5J2U_E,154
29
+ mojo/apps/account/models/push/config.py,sha256=Re3A2_Mpw6LlSJcITDVvoJJV3cBNSFOqbnHdMPj2qvQ,4532
30
+ mojo/apps/account/models/push/delivery.py,sha256=gW_wipuifrJzGc41zOxrqn6Bafd6ddA3n9SBm0CxstM,3735
31
+ mojo/apps/account/models/push/device.py,sha256=8RVVK1K8LTR2W0_wZPHYxJir_aXnKO8zP-yREK_rHRU,2616
32
+ mojo/apps/account/models/push/template.py,sha256=VnQ0EPTdEF-YvKaPu1QADkp5Assv3OwoYEvgkiaJ--M,4073
33
+ mojo/apps/account/models/user.py,sha256=czyZfBJy213M7IvqCUU-C70vbPgmUCbVVfyM1nuBFRk,21507
34
+ mojo/apps/account/rest/__init__.py,sha256=AHerCTR2wqOQFeN5rUtbR-qN5tvLVer4MjixadJkc7g,97
35
+ mojo/apps/account/rest/device.py,sha256=qRyFR9HkQ8PqGbwR5ZEioky-v_sGy67Vbp-7Iy2oHDA,1248
36
+ mojo/apps/account/rest/group.py,sha256=Syi8hV8HozwzQS-_qNip0MQcBtxCn-W10i0o4kcb24M,1105
37
+ mojo/apps/account/rest/push.py,sha256=8JCf-JXFJpxMhHgAGvaVn2ZKauY80UlkCc5-qgdScz0,5832
38
+ mojo/apps/account/rest/user.py,sha256=jBAxuReJZMRNwjdDTx80HvpAOO8WET1ZXlS6JwsaG18,5550
39
+ mojo/apps/account/services/__init__.py,sha256=fdA9ScIbYS0DJPixwTPjKWhuh8FTC15nGFq7m7EOCNE,29
40
+ mojo/apps/account/services/push.py,sha256=WtRXJm9p3Ry9WhP39g5ebcuZ-o_CdL5kes_LNi6Osxw,14016
41
+ mojo/apps/account/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
+ mojo/apps/account/utils/jwtoken.py,sha256=7EMC08oDB9oeasv_7nishUNrE-QTls-Mv2n4yAa9euk,2714
43
+ mojo/apps/account/utils/passkeys.py,sha256=vUsXroe4SYcst4L7-eRWDR21l-yVYMOKa1-yWFNKfPo,2343
44
+ mojo/apps/aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
45
+ mojo/apps/aws/migrations/0001_initial.py,sha256=6CbIyLTswAh9Wgbz6QmKZ7FevTwuiQM_c8-RVc67ZFA,14543
46
+ mojo/apps/aws/migrations/0002_emaildomain_can_recv_emaildomain_can_send_and_more.py,sha256=y5EORDmBgotDYCVdJif_pbCUDSSiQ0l6YoOqN7i6p2A,959
47
+ mojo/apps/aws/migrations/0003_mailbox_is_domain_default_mailbox_is_system_default_and_more.py,sha256=xbUZ-aPc3d5IFXpZNwcquns-GF2CrBRJmH0LHInPwgc,1106
48
+ mojo/apps/aws/migrations/0004_s3bucket.py,sha256=17eizmVX6WpYIO_zBivNdcY5f-myhqpFwRZW0QTaUFM,1986
49
+ mojo/apps/aws/migrations/0005_alter_emaildomain_region_delete_s3bucket.py,sha256=akgZsF9ah58Mo_tZNc1e-57KiKKrSTjbreKFJq0s7LY,514
50
+ mojo/apps/aws/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
51
+ mojo/apps/aws/models/__init__.py,sha256=ZfSWBSWt95ce5y6cI-kCk6SK7on-5w2fjJNuEu_Z92A,404
52
+ mojo/apps/aws/models/email_attachment.py,sha256=03yXgQo7Yuj54VBWKqnKdQ7AO3Y4MiSmLrxGbeThBok,2852
53
+ mojo/apps/aws/models/email_domain.py,sha256=CmULUky_RVacazy9bXxv1b_Iu8obPWG9Sx8xMrHa5xo,7116
54
+ mojo/apps/aws/models/email_template.py,sha256=9E1P3tHlYJWvBB3mGIpTfhdkEVU2WRxIvzrJSxM8l6s,4299
55
+ mojo/apps/aws/models/incoming_email.py,sha256=Nhkqp9dqAGAZyt6nS3xZf5oPdzEEvBerDNQx5COWYNc,5875
56
+ mojo/apps/aws/models/mailbox.py,sha256=5liCWEm8dYDyYCE-CDoP7wZHUERVSTEZ7qREw4Wf8cg,10334
57
+ mojo/apps/aws/models/sent_message.py,sha256=bsvPqrKZyu3qCgHbOg1uUh_Obu_8LYzldNttNXuE4Fg,5279
58
+ mojo/apps/aws/rest/__init__.py,sha256=3gdRhP4CJDy2s0H-w8XHgllb08E5Q_NFKIYH7AlSdXg,152
59
+ mojo/apps/aws/rest/email.py,sha256=BcHngkq7yv8TKdKzGpC-lmXVqbxPp3HtBuTPPVHl4TU,848
60
+ mojo/apps/aws/rest/email_ops.py,sha256=2M97QvwOgDomclbNVdH8dXpKclu1jAId5a3q1HFY2vA,6941
61
+ mojo/apps/aws/rest/messages.py,sha256=dY977YdCPOWTXw5hpIIfglGiQOw-VFJPy6-Uy41XBZw,965
62
+ mojo/apps/aws/rest/s3.py,sha256=jt9F3gd8aih0H-I6RKEBLLYHiw-D-aMWtWWY8lfYCfg,2541
63
+ mojo/apps/aws/rest/send.py,sha256=7ozIcec_hrD2V55enJ-nZmfj2Tg89RXhqmSVf0oMW_s,4356
64
+ mojo/apps/aws/rest/sns.py,sha256=W08uAks8DZ5mQQDd6Xtci5Kz4zDfta-rMpavPCVQUcs,15102
65
+ mojo/apps/aws/rest/templates.py,sha256=Y1IKZR9ZJje9xsrSa7SZd9Z6fui8UDoY4rkvzQexfIw,507
66
+ mojo/apps/aws/services/__init__.py,sha256=ua23H1vSBDSG3DJFQdFAxPTxmLUA2vzsNK80DsWiq6s,828
67
+ mojo/apps/aws/services/email.py,sha256=4bnMmzGtHACLZC58Wmeu93MDOdWXbKBTutpLXUGgxb8,14079
68
+ mojo/apps/aws/services/email_ops.py,sha256=J-OcZFZEPVLEl2MsVK1FQisY3IxAmQpnyp2BUozohqs,20175
69
+ mojo/apps/docit/__init__.py,sha256=3PRmMb-irOjt8OJQT3x48GNKWKoHcHRIdEqH3Zw-mzY,184
70
+ mojo/apps/docit/markdown_plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
71
+ mojo/apps/docit/markdown_plugins/syntax_highlight.py,sha256=fCsMqTR6f88ULBB3ARDqAXTq8Z2Hn8g7bBO1vzX_i24,846
72
+ mojo/apps/docit/markdown_plugins/toc.py,sha256=-AWsg5bPpsXt3-DVnEQxFcC6nBkWP0-Uz-9MOVJ7pIg,428
73
+ mojo/apps/docit/migrations/0001_initial.py,sha256=w01bIjMOPYcEy9PcE01jC33IScabx_O-R_1vn3_qF-U,8468
74
+ mojo/apps/docit/migrations/0002_alter_book_modified_by_alter_page_modified_by.py,sha256=kMkAEEZ8RdoPU-r8os39FhYEh6BpEqCODC3NzYpGBJY,990
75
+ mojo/apps/docit/migrations/0003_alter_book_group.py,sha256=w1KAh6vl1zMk44w0YIvmo-O-dNjKivJ0RhXAIISeqzo,659
76
+ mojo/apps/docit/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
77
+ mojo/apps/docit/models/__init__.py,sha256=9ogNhXUt8h_m0b2O-POHOxUfaO19Dn1PF4b5tRaMaDU,247
78
+ mojo/apps/docit/models/asset.py,sha256=BL73eWnZEKYQqAvL024DDA1YS9ExDC-_4X384WjCfBY,6712
79
+ mojo/apps/docit/models/book.py,sha256=wSVzCcML_KD88EdM-wrk21Pgcj2eABGBfL_p9p_74JU,7150
80
+ mojo/apps/docit/models/page.py,sha256=efewSf_FK_MygF7UTBLExqcqFHKsZnOt3O2rfXJJCaY,10241
81
+ mojo/apps/docit/models/page_revision.py,sha256=EEznVqiqRzvgB80MSQrTwa9vKOINgRFiDfaCJxRPl_c,6229
82
+ mojo/apps/docit/rest/__init__.py,sha256=vPtShwGXJvKNJ3wgIVFt20RA-oAb73TCytV16JF1Yd8,188
83
+ mojo/apps/docit/rest/asset.py,sha256=e5OvvzEUgdCIgXubr2WiKlTr2Nhiqzb1C77xwZ_X5bA,531
84
+ mojo/apps/docit/rest/book.py,sha256=tbHSqBS1bVEKoCVvnmV3SAdOr9gg0WqAzMLylhXST9I,585
85
+ mojo/apps/docit/rest/page.py,sha256=X8ddbUm5b5K2OtHUOT8ocvtiUwQmO_psxWho8C1_2xM,585
86
+ mojo/apps/docit/rest/page_revision.py,sha256=PLLaijjj6H-kGD8687OfnhmVID6EkOgdzxms2SajdmU,591
87
+ mojo/apps/docit/services/__init__.py,sha256=AMR1H_at7kboSw6sH755_ZMlwPGu6NQ2gmqsFDHB0AA,140
88
+ mojo/apps/docit/services/docit.py,sha256=6dV9CD_6kH8XTfFYbekCVrP-_Y3lQ7-wIXxDkeQSCgQ,11123
89
+ mojo/apps/docit/services/markdown.py,sha256=ma8i3TbMq9WlGLl0CoQp_-V_3N-6XRBcYJAviibESEA,1351
90
+ mojo/apps/fileman/README.md,sha256=vuld7Ek0kDO0WU3jgaZDmjj8pYxF674WkrPvW6X1Cfg,14106
91
+ mojo/apps/fileman/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
92
+ mojo/apps/fileman/apps.py,sha256=evFaBnGp90BZWgAe00fOYjdZ--5msi_vW8zjHgVct1Y,383
93
+ mojo/apps/fileman/backends/__init__.py,sha256=BQqbsGYQvfOPlXLio2XwNGsT5eLGIbrf01PZ8OceUx8,3292
94
+ mojo/apps/fileman/backends/base.py,sha256=3tvnt3GrnCWhKsLUh0sE8BQeTik7HmbVbZv5lKYw9_w,9411
95
+ mojo/apps/fileman/backends/filesystem.py,sha256=ykRCiV6aMxjjmDMOY9xfpupC1zcbPF04XBbs0ygmHWg,14949
96
+ mojo/apps/fileman/backends/s3.py,sha256=6N5ZsIsyoT7pr90241VTdNLzmBdXgcP8vJDUDHUM4XQ,26671
97
+ mojo/apps/fileman/examples/configurations.py,sha256=vDIMijAvF-iVrc8ZT1OzjDPKCJYsvxuvAuirXhB9FYU,13775
98
+ mojo/apps/fileman/examples/usage_example.py,sha256=ATkGuUUoNYb4xhEaWFul7Sj-gyKIa9XF5EmVUibSbMQ,22795
99
+ mojo/apps/fileman/management/__init__.py,sha256=HqDUzH9gSF7kUKGypm6LZ5cHxzYEc3I2_9fB3eI283s,36
100
+ mojo/apps/fileman/management/commands/__init__.py,sha256=XtylA46UPDJ5ZY48r5yyk7ZKpvfmnb8kYJjIRVFAMiM,45
101
+ mojo/apps/fileman/management/commands/cleanup_expired_uploads.py,sha256=818-r5w8sKPSOMa1iA7VjUSpYCnlKdjWtsv8cdHkfY8,8354
102
+ mojo/apps/fileman/migrations/0001_initial.py,sha256=M_JTKQK1sIHVA-jMjQzHyGVTp3GAOEUjJIHzT466KDg,7670
103
+ mojo/apps/fileman/migrations/0002_filemanager_parent_alter_filemanager_max_file_size.py,sha256=qGeGzANHIcUs_CAZBxdCrO6qxAAPSpMuh8TXiyzB6WQ,839
104
+ mojo/apps/fileman/migrations/0003_remove_file_fileman_fil_upload__c4bc35_idx_and_more.py,sha256=s6_Mk7ZgUc_sGIFlldY45KDY1O5fHo2HbMHfvd2r01c,600
105
+ mojo/apps/fileman/migrations/0004_remove_file_original_filename_and_more.py,sha256=zg7dedMO6a0a-FjtEBRVCgn5Pjrr1B5SDVBMoyw2w0c,1358
106
+ mojo/apps/fileman/migrations/0005_alter_file_upload_token.py,sha256=sDjN_Qb9CGqp-U4oDYzMClDtasWhQzTw-TQMdqHRjuU,480
107
+ mojo/apps/fileman/migrations/0006_file_download_url_filemanager_forever_urls.py,sha256=gzgtrYVKLJR71Xu8Wk83VK6dacgGdGCWvNq5eSU_vcc,703
108
+ mojo/apps/fileman/migrations/0007_remove_filemanager_forever_urls_and_more.py,sha256=dsZW-CZkgJcMp4XwF_dexzDB-JX_GNm4TDOuSFWC3e0,593
109
+ mojo/apps/fileman/migrations/0008_file_category.py,sha256=K_2hSPIxut-707_e6UxTu1yI2jA18NMtG6NE1uAd6pk,538
110
+ mojo/apps/fileman/migrations/0009_rename_file_path_file_storage_file_path.py,sha256=gs6-auHbek6OOFZ6am6SZH-BAWcSGFeISjJtNuOra7I,371
111
+ mojo/apps/fileman/migrations/0010_filerendition.py,sha256=bBXd4rN9nBOsYJ5d6uy2AasvETTU2XsHg5fay7teP-4,1939
112
+ mojo/apps/fileman/migrations/0011_alter_filerendition_original_file.py,sha256=MolIDgbswlzj6Sso2dRSgRrSxiYDF8R8V80UG0vfyZs,540
113
+ mojo/apps/fileman/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
114
+ mojo/apps/fileman/models/__init__.py,sha256=eINHGAhNCLK7Z4XeHT-iFH--0X3m23P2Py2zQgJHQbA,93
115
+ mojo/apps/fileman/models/file.py,sha256=tzeCJxEWpQ8aOgkIHecwuWSPlffm9WApCBWQMSDDGU0,15622
116
+ mojo/apps/fileman/models/manager.py,sha256=IaYvYtV9iHzZRg523X66u-iOU4fhdaAbclsFnfLb1Nw,22958
117
+ mojo/apps/fileman/models/rendition.py,sha256=j96Q-zv-dB-Shc_4AwE-ky1ZCovGjvX3KO0ACOBUlto,3198
118
+ mojo/apps/fileman/renderer/__init__.py,sha256=8LyugR_AXzq0bwScDLGWW8y7A_be0kIrs0L2AtVwgqc,3510
119
+ mojo/apps/fileman/renderer/audio.py,sha256=BUJefcyPMqqnpWD7nYATWVft4xaoKKpqbTx7GoZxI8M,15421
120
+ mojo/apps/fileman/renderer/base.py,sha256=Neh6G-v0IRey2xQvf8lFspIAAD9oK5LBvfuQqs7a0RQ,6538
121
+ mojo/apps/fileman/renderer/document.py,sha256=SScakrHT0TJJktEjpPkmX5eZfzzk2rgvD1VYJcwflLI,14836
122
+ mojo/apps/fileman/renderer/image.py,sha256=kDmtEu8UVhwUc1MsIf5Ty0OVLt3cC6tSL95xo6Vshfg,7883
123
+ mojo/apps/fileman/renderer/utils.py,sha256=dAOBih3uVMIkcGiiY2bjhGxWpgfM5_KUMG2Y4dlBTSw,8672
124
+ mojo/apps/fileman/renderer/video.py,sha256=Ml633nSDwgPx0BeKSQ5wAR4r642_BKPEA-_2dTboRDQ,10899
125
+ mojo/apps/fileman/rest/__init__.py,sha256=u4ZyCGVFOpp5OnXnHvl46rvsFUlHeXWNYNc0BBhKMK8,108
126
+ mojo/apps/fileman/rest/fileman.py,sha256=cQYKVm9Nzu5-Hf2tWbq8Gg_zad3RtIy2bE88NLgKlrs,346
127
+ mojo/apps/fileman/rest/upload.py,sha256=NZZnPytjQvG2OWVdNDN4t1a8mltZZNM51aiA0Yr51Ww,2579
128
+ mojo/apps/fileman/signals.py,sha256=Kj_vhUdOhAFNrl4VxD7RoAipbx9i8DiZJw_2L_g9Gfw,2849
129
+ mojo/apps/fileman/tasks.py,sha256=59RBxKGOTwMNYbfMIRbF3QSVqj9jWnMZi2arD9dc3DA,8059
130
+ mojo/apps/fileman/utils/__init__.py,sha256=KbDUNeCSW4d6Rg6h_Bh2H_5ol70oE6twLp3ErNnnPBE,1237
131
+ mojo/apps/fileman/utils/upload.py,sha256=hcH0pUf_dZ3tlkZQw1_YBBeAqxwMEDedsBG-n310uS8,18792
132
+ mojo/apps/incident/__init__.py,sha256=G75zqcH8fatIpQ0Jfp67xg48JtpQR_A6MkN2ykxrjRU,35
133
+ mojo/apps/incident/handlers/__init__.py,sha256=gl8imRiKYCnwB2SBoAavpUfJ9ifkS7WF_DOJKMHJg9Q,128
134
+ mojo/apps/incident/handlers/event_handlers.py,sha256=UkGDYIQq73OdTWFUJlLlsCOhOYZB0cbhKwuGippdnOE,4696
135
+ mojo/apps/incident/migrations/0001_initial.py,sha256=F1qZFxGRjD9qyk_zHkn3FmdyMh94Z0bcnHIvmIEZcJI,4506
136
+ mojo/apps/incident/migrations/0002_rename_bundle_ruleset_bundle_minutes_event_hostname_and_more.py,sha256=9_C_mLwbdr1RcyrtD-pm4EuwuFKInluk5IBuW4_1UJU,1441
137
+ mojo/apps/incident/migrations/0003_alter_event_model_id.py,sha256=pFN_W8Ok46rmQOqKDFrAXYEY0iXphFE4Rh7MSJu0VGY,459
138
+ mojo/apps/incident/migrations/0004_alter_incident_model_id.py,sha256=Cv2mqjYXeHgYBi7BUb_mYw-PuPQKRXj6_uy9bqECNRI,422
139
+ mojo/apps/incident/migrations/0005_incidenthistory.py,sha256=pGv1HkLudn2n7st5RlbAkutLnQ640dxHP4mGf7eMmho,2060
140
+ mojo/apps/incident/migrations/0006_alter_incident_state.py,sha256=fZkbMh-hoArprkwx6J6WI8NsMwbm9zMGg-QdABz63wE,412
141
+ mojo/apps/incident/migrations/0007_event_uid.py,sha256=r_K4nN0iPM-tvQTiYBHwjKO5TgYbTrqpQH6qM8qVLFc,412
142
+ mojo/apps/incident/migrations/0008_ticket_ticketnote.py,sha256=stUfNbwzDZw4yNhkYYdQOyU1NOcVjL1xBRjCH5lpo7k,3064
143
+ mojo/apps/incident/migrations/0009_incident_status.py,sha256=AUnogetohTump7vX_dO2pDUvLykkZxTiJ01k36__-pE,418
144
+ mojo/apps/incident/migrations/0010_event_country_code.py,sha256=pX2K0p2b5qDlNsmG3_HlGkquEFvrmHl2pMt4GcWlFPQ,427
145
+ mojo/apps/incident/migrations/0011_incident_country_code.py,sha256=Lx4Ob0BwDSAoXp4KJwOFvAjv45B2t2ku5_4JHm5L5GQ,433
146
+ mojo/apps/incident/migrations/0012_alter_incident_status.py,sha256=OfVHgjn9YrWG58TbwRp2Fz8xuphnsTQdQO0PU1-2miY,423
147
+ mojo/apps/incident/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
148
+ mojo/apps/incident/models/__init__.py,sha256=M20VFoPle5dNVsXZL65azmGyN6OvInYU8KCReY4lJec,164
149
+ mojo/apps/incident/models/event.py,sha256=5GPwK4c7P6kTKGHbzKGYiVmKH_L_7czO_OqxcHLpcaY,6866
150
+ mojo/apps/incident/models/history.py,sha256=67Lnp_4T8dwFCZMnkFwwTI52gtOFdsKAqfNs5yZ7og0,1492
151
+ mojo/apps/incident/models/incident.py,sha256=EIgPWnmAjWRatZyx5KRKuHDhVlzdvSQ7Vky1AQDSbWo,1387
152
+ mojo/apps/incident/models/rule.py,sha256=74tP-h5KqNRRvbmjksCj4SrKJeWi5Fu3vy18t7k6Jys,10110
153
+ mojo/apps/incident/models/ticket.py,sha256=UPd6Ag3UuKgGJNvQ8m0rp0x0jMcCdJSX_OUwnfqpcyk,2311
154
+ mojo/apps/incident/parsers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
155
+ mojo/apps/incident/parsers/ossec/__init__.py,sha256=2e96VUlQj_WgmSKLaUVxKijdv-tY5juquEUebWRCrdQ,48
156
+ mojo/apps/incident/parsers/ossec/core.py,sha256=lC3DuJolsJtHOdgVCG2qYcVwi_ryM8WNpWk9tfx-Kwg,2429
157
+ mojo/apps/incident/parsers/ossec/parsed.py,sha256=1Fcw7F01lAK70aSf7ga5ka2izB_IUGeIfomEcqUY_Qk,786
158
+ mojo/apps/incident/parsers/ossec/rules.py,sha256=635TmK6uUOQZsgMKDbU5HJIGjYlXUo4I6AIBFCuY0V8,4252
159
+ mojo/apps/incident/parsers/ossec/utils.py,sha256=OkD5unXJAuqQo2_mGCO8bokY0tTOzwAAo28hz7Ux8vg,5061
160
+ mojo/apps/incident/reporter.py,sha256=WoWXKhzFLbjLpSDp0__-UTaXevpAyjcovOeGB05Eizc,2224
161
+ mojo/apps/incident/rest/__init__.py,sha256=aiM-cxQNSNKntTqWitv6vmnSIWpGaScZb4HfeR10m1A,64
162
+ mojo/apps/incident/rest/event.py,sha256=ZlOi88Q8HcvtwCOW65X9RSaTddyXweOCOW3vWgVNOcs,851
163
+ mojo/apps/incident/rest/ossec.py,sha256=Rw7o1LRCZdeHL3wOry6zgT9r1MGVxUzJiwvmyT5GfbI,730
164
+ mojo/apps/incident/rest/ticket.py,sha256=W3OJAccl9bRYC-Q1zyGw2uJ2kmT-nviyK8vdUntUH3Y,1522
165
+ mojo/apps/jobs/__init__.py,sha256=GnUaKtFCOPcOQKHwbSgmbPfml6UcgojU2B5agcQ4BFE,16393
166
+ mojo/apps/jobs/adapters.py,sha256=cJ70QMXTmehDRUn5HsfYj5vjBswTSPiB2CtT19VIM8s,691
167
+ mojo/apps/jobs/cli.py,sha256=oau5s0TAx6fPnXnH_SEzwUXpxtS03Brl3NwqLJ0xlDw,18872
168
+ mojo/apps/jobs/daemon.py,sha256=jkxYYmKKuSyo1af-Z4GDyBe7S31zlTCyC9LsvIYEIS0,11123
169
+ mojo/apps/jobs/examples/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
170
+ mojo/apps/jobs/examples/sample_jobs.py,sha256=GuMwNv9cZQR6Bud0oYlj-Uq0pJZp0nNh8cyfypKADFY,11726
171
+ mojo/apps/jobs/examples/webhook_examples.py,sha256=y5MaD8vXgVTu19bMzsfygycvWroQMFsbvbrPJbc0ets,6500
172
+ mojo/apps/jobs/handlers/__init__.py,sha256=W57uZ7bHfyXU8lFmrpClAV_rLqWO33ornkxXFuy7TOs,122
173
+ mojo/apps/jobs/handlers/webhook.py,sha256=PaSDkMnira10CpzHQImkdeVFvoGHPnmHFCS4W7FqCSU,11013
174
+ mojo/apps/jobs/job_engine.py,sha256=ZpJlrKJN2iLMj5dPMN31D-BAaFOr8quN14JAFfg3CFA,28635
175
+ mojo/apps/jobs/keys.py,sha256=sRssn2-Imwamwk4hRNLvY2KqWqjvo2q2NjrVtmlSwkk,5408
176
+ mojo/apps/jobs/local_queue.py,sha256=uJ1rrv3iihTLqFfVKQQ3Q-qbYln7Cz0Cft2ouHTarDQ,10582
177
+ mojo/apps/jobs/management/__init__.py,sha256=J-ADrNPq_Q2K6GVV1G8MapQEn979E1Bogx6lwbCfBdc,56
178
+ mojo/apps/jobs/management/commands/__init__.py,sha256=J-ADrNPq_Q2K6GVV1G8MapQEn979E1Bogx6lwbCfBdc,56
179
+ mojo/apps/jobs/manager.py,sha256=dxROG7FiTFOytZdvl0YHL82thnQfWjIfvc40TgDd7VY,49206
180
+ mojo/apps/jobs/migrations/0001_initial.py,sha256=pQrryKe83ewo64wpBZirqsnOnB-ESkHheSmSRREfTb4,6210
181
+ mojo/apps/jobs/migrations/0002_alter_job_max_retries_joblog.py,sha256=k2kGZrmd3py06GkL_yGBtE_gYb4Crh6uhmjNZ4YYz3Y,1908
182
+ mojo/apps/jobs/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
183
+ mojo/apps/jobs/models/__init__.py,sha256=WibSDLNAYn25VPDXm7CC_VtIK4BA9VMYyr745DTTeCU,101
184
+ mojo/apps/jobs/models/job.py,sha256=lSF5orWJcsDkU8-ZJTw-ATA04PWZ8tpyiBUiRqDqCyQ,15764
185
+ mojo/apps/jobs/rest/__init__.py,sha256=LBsu8DKEKqn_a7V4D_IID0AU7Kw-NAN9bcKK4DUd7hw,43
186
+ mojo/apps/jobs/rest/control.py,sha256=Xvmff6jr48WX69zzjqmSTiMaDIYBqIMzGwcatR4jkuw,14529
187
+ mojo/apps/jobs/rest/jobs.py,sha256=tefqcizxwPY3ogk1qt9TrSPLd3qitUk8ifAD_uhi0MA,11427
188
+ mojo/apps/jobs/scheduler.py,sha256=LzqL3W1BsXfOeYuPACEuMF7aotqCpPGJ-rbCiubLUak,19942
189
+ mojo/apps/jobs/services/__init__.py,sha256=sCNHfrih3neFm9ZRThKns7inG7oCXJxZtylnZRMK5tU,118
190
+ mojo/apps/jobs/services/job_actions.py,sha256=JUFpPSdi2t7SdjJFw1Hm2E2melNylQ8R7mxtalNsXCA,15843
191
+ mojo/apps/jobs/settings.py,sha256=2P3HJ_iqAn0MKwvhuQHPfooCjHzdZ5wGpA_IIvQZcdQ,6780
192
+ mojo/apps/logit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
193
+ mojo/apps/logit/admin.py,sha256=XLvz6CtwfW3rryp5xfvtylL_CWZ5-CbChK4DB2Hl3qM,1552
194
+ mojo/apps/logit/migrations/0001_initial.py,sha256=7vrTetfEFrUzc3cOoboyktfK_KlsfrGAoCDf4T2sJzk,1348
195
+ mojo/apps/logit/migrations/0002_log_duid_log_payload_log_username.py,sha256=s97JeIMjNmKah2b7YcGauaVg_1liTeUJfq-GCi0wP6U,696
196
+ mojo/apps/logit/migrations/0003_log_level.py,sha256=HzLwBYitzRsHxGkM9gKrgc4A8dzLt4ewl14nCnWLSnc,424
197
+ mojo/apps/logit/migrations/0004_alter_log_level.py,sha256=QFPma7kIEUd2wPzc-OExWJt64ZekSXHtuyCgo7ImDVs,403
198
+ mojo/apps/logit/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
199
+ mojo/apps/logit/models/__init__.py,sha256=cOGwOYzMoshEbZiiasBGkj6wF0SBu3Jdpl-AuakDesw,19
200
+ mojo/apps/logit/models/log.py,sha256=dy0BSqErF09_O92-hnUhXgOSgFFNp5E2T6JgfHzZSlc,2567
201
+ mojo/apps/logit/rest.py,sha256=bPoq9Blqzr1YU43LTLf9DiSLe6DgjcH1ctDnfvidpbs,205
202
+ mojo/apps/metrics/README.md,sha256=i4dHNqTKgBLMSIxyLddD7wifxZRDTn2JqQGPmW3EWIw,2984
203
+ mojo/apps/metrics/__init__.py,sha256=l9-nvs7_Kkp6OzNgcJ091p5VFTvHjDidUHkQ14N5T2k,362
204
+ mojo/apps/metrics/redis_metrics.py,sha256=6M0MolNYzHFH8CvXK0jXJYfh_E_bp3F1WgzRPY1Hj5E,19511
205
+ mojo/apps/metrics/rest/__init__.py,sha256=UBR8Yzh73AMvy66BTsWEoSsOT2w9Nj6aDm45hWJkOzc,95
206
+ mojo/apps/metrics/rest/base.py,sha256=1uEqxlvEQpXNOJqFpQe-HxETiYF_6bxmJ9X5eYclabg,5895
207
+ mojo/apps/metrics/rest/categories.py,sha256=sETaAP7lzXf2qw0chPaKfjer3ilptyxUIDjGZaY0y3g,8296
208
+ mojo/apps/metrics/rest/helpers.py,sha256=5w3DO8joiOMN-QzouzQen1MtxepUvfs6UvpQS10GZkc,1781
209
+ mojo/apps/metrics/rest/permissions.py,sha256=cEihJa7F1yjwU3dT-r24T1IlGCVRUqtbqLlzCLQze9A,2765
210
+ mojo/apps/metrics/rest/values.py,sha256=RMtonBARjLby2CRSJqH4n6MOQNz3BKOKjUghJx0qHGY,8969
211
+ mojo/apps/metrics/utils.py,sha256=qkIS09ZxtCkEYFBodxRB_JfzZPJ3CXPJIpEbkXcD1pw,7774
212
+ mojo/decorators/__init__.py,sha256=XzKewkbEeLd0M1ciA6Qf1kbawOd2VV-FbAT1nMLBoQ0,64
213
+ mojo/decorators/auth.py,sha256=spUgzYYBGrVCdyZJ23QxU3wNbLZ5IHkWet195R4cbW0,1019
214
+ mojo/decorators/cron.py,sha256=8Qc4XJU9wUSxfepRALZbeFmgOOVWikhGMnrcOk5wbIw,1199
215
+ mojo/decorators/http.py,sha256=n4wdnMSYBGfbVsAOg5FECVpGJNvllJ0gcucnePj9s5M,7398
216
+ mojo/decorators/validate.py,sha256=MEaIR8yvsM2nloOVbqjvvnrrA0wZn6OLkov2tJ1qdIw,550
217
+ mojo/errors.py,sha256=MPJ5_B-RQNK69-fQ-Hs1oddjupjfwWNakieVPee9hU4,3281
218
+ mojo/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
219
+ mojo/helpers/aws/__init__.py,sha256=scAJG1zCCKTsm8kfDLYn52S5zcjBgbTuJB9fpFuW6iQ,776
220
+ mojo/helpers/aws/client.py,sha256=JoHStXSar6myZuObgteh06ZvFrKGp5Tv7lme0BFcAPw,203
221
+ mojo/helpers/aws/ec2.py,sha256=HrRxggGxjsG2MbGjWzKsC-bCk7VdyXtzFsbeQdcJEqg,27840
222
+ mojo/helpers/aws/iam.py,sha256=Kn24kEy8cacNWhYdagvEfXR8pG8un9DAYg-uHmptraY,23737
223
+ mojo/helpers/aws/inbound_email.py,sha256=dgYKIX5NWngymO1JVsPc38maXpk2Pf46IQW2YcYfP98,11270
224
+ mojo/helpers/aws/kms.py,sha256=RwlgfCo9s2Rs3y5fgcWnGoR7yK6Ntktoqln5sRQ6wDU,15619
225
+ mojo/helpers/aws/s3.py,sha256=SnLOX7X6gqu3fpi1BlGyTTI9FkEDTBFuhXNxMkwNz3o,22106
226
+ mojo/helpers/aws/ses.py,sha256=BIRZW-co4_VSm73kGN6wPhthlv_3-wKEHvkGsQsIeG0,16051
227
+ mojo/helpers/aws/ses_domain.py,sha256=3_XPgdtSNpVg1oMFZEe36Hb_1Hgw4cWmjLM1E-5Hj_g,34933
228
+ mojo/helpers/aws/sns.py,sha256=-qkJwRBEPWQxkBr18lS4t6I_oW2wLm2LGfOWTyKnXDs,15119
229
+ mojo/helpers/cron.py,sha256=_hoKgYYc7m4oU_eU4uUOIXOhJA0A9Lw0f9GPm5TCcs4,2411
230
+ mojo/helpers/crypto/__init__.py,sha256=_-uy2lQ30OFXEbTclFj6b2TJeYhF94dwRM_qwqgOkS8,201
231
+ mojo/helpers/crypto/aes.py,sha256=8VTAsykOxiSBbdKVK0DxJ_1Y2wGkY0CDRjhXSiMvF8o,1830
232
+ mojo/helpers/crypto/hash.py,sha256=HVgfzmpMO5K5stiiateB1y16SAHS7qOP0nGRGyVW0FU,2078
233
+ mojo/helpers/crypto/privpub/__init__.py,sha256=Om2Iw0r1tV4_W3OwWazLveQFTs4bwnYc35JxRBf9nm4,44
234
+ mojo/helpers/crypto/privpub/hybrid.py,sha256=APkqjHLPg4oGRBrji9e1YYKzr_v10yn5IV18ar04GIk,3422
235
+ mojo/helpers/crypto/privpub/rsa.py,sha256=ZrvHMsPv52t1ctuaAX2I7qwqnR1Yh5wLLCaveekMDsI,3420
236
+ mojo/helpers/crypto/sign.py,sha256=jC_QKm7WcxQix0DuxSk5SGD8L-6mBSl1ZHobPnpsR48,1204
237
+ mojo/helpers/crypto/too.l.py,sha256=6ypxFDOkHylcVfdGRlTtS-Jtig8JHkfVHi5N2w0i-_s,821
238
+ mojo/helpers/crypto/utils.py,sha256=_KWl0t61fw4f101aY-lWs86DjRZethhQQ4JktimzdME,1119
239
+ mojo/helpers/daemon.py,sha256=6cC2XWIUZH59YdrV2dglPqNtJ8UUPbsKSatGsDp44m8,3276
240
+ mojo/helpers/dates.py,sha256=geNPvF4kvb1WAM3aCNnIxQWmoxkEqzN-S6VKWEk5Ca8,2534
241
+ mojo/helpers/dns/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
242
+ mojo/helpers/dns/godaddy.py,sha256=l8AboiEeGQ34p2t-i5Z6XDkf3siUgRsqIg1mVciPZnU,2334
243
+ mojo/helpers/filetypes.py,sha256=4BJpH8jQ_bZk-86yy2ZasVgVnxHNLIi96d2umQz_dXI,4163
244
+ mojo/helpers/location/__init__.py,sha256=QKuRolBkUBfcGjeLvn1YHnH5vsGIO-iu4r7Qgpoym_U,102
245
+ mojo/helpers/location/countries.py,sha256=U4Rv6j9l1pQqVXlF7zHyrPxQzf2ExPphTq4IoQ4UbHo,6665
246
+ mojo/helpers/location/geolocation.py,sha256=ZNy8m7JK8Ag7Xsr12v8cgyqaxAOnUPqVIMvkLGq5fTc,7070
247
+ mojo/helpers/logit.py,sha256=ZlsS-FJTTfEUvwHR3LJI13y8-bvUZ1KBAhla2FGIXo8,10898
248
+ mojo/helpers/modules.py,sha256=Tq9agvdqLOMWsvyRYLwyyF-g28Y6zSCdJhfhT8iraj4,3180
249
+ mojo/helpers/paths.py,sha256=dIAGF0MOr9faE72fwne2-BEaarXCvJBsU8yJSjB15hA,2053
250
+ mojo/helpers/redis/__init__.py,sha256=GrJde-QtHSXWOg4fyaZo91isfh8QiB0OAn-9g32BNyk,97
251
+ mojo/helpers/redis/adapter.py,sha256=7dFwoiqGnEOnx2mMJQpVYnBtA6MOpz_8vTuGrilAxF4,18133
252
+ mojo/helpers/redis/client.py,sha256=VwYiCMyJgXNMZcGaoRe_dDCluZZpobsAbmLy3zYe484,1438
253
+ mojo/helpers/redis/pool.py,sha256=nXXrdMMr2RGTbjS_qeOGalLpL0gYqhSISHx4DSs5e84,7800
254
+ mojo/helpers/request.py,sha256=Y5cXOpiGU_qsHLnOeWLrcWeEtEAYm_2D-VHvvAQSePE,2600
255
+ mojo/helpers/request_parser.py,sha256=OHsoBaZJ07OEWMDxVTnwElTEpd-zMtwpNdAKL_4KFzc,8862
256
+ mojo/helpers/response.py,sha256=yjsbSg2_bHsXdFkhd3PvkEgkiefxtb4u_-bV2Zz0Ces,940
257
+ mojo/helpers/settings/__init__.py,sha256=hoBkefiF-jluJeIQ6mHBfMedVs7cFJGRmPZMTiNmHCo,93
258
+ mojo/helpers/settings/helper.py,sha256=TRF9MfUMz3vxr6i-u_OV1bhSm0JRQOreIbHSCUOc0Rc,3646
259
+ mojo/helpers/settings/parser.py,sha256=DmVfQdTd_wClxyhqd2T8AgrgRecAoi5ZdIAVJEm4alE,4709
260
+ mojo/helpers/sysinfo.py,sha256=CHflsP26GZYTWU3LZpUtZ98l66x5QFXllfQJlv3MvRw,4517
261
+ mojo/helpers/ua.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
262
+ mojo/middleware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
263
+ mojo/middleware/auth.py,sha256=oMk8BCHzn49nzxWJLhAd2Albs0bgZF6rI6_pAfd-GGg,948
264
+ mojo/middleware/cors.py,sha256=yrTHZW6txDiMKYMD3fWCyBp35P5eu5T-yWv5lB87iN8,1452
265
+ mojo/middleware/logging.py,sha256=wBNlQGb3qeietV_SsWmpOyUVAgxS-NCsfk7Hke1Dl8M,6549
266
+ mojo/middleware/mojo.py,sha256=bbrigUIMpalpZFmF7OysXhbg_02-9ifHsgrHBA5GO3I,1012
267
+ mojo/migrations/0001_initial.py,sha256=ir1h2kZZ6WnAChhcCejCVd5C0kWhGsXKozNhZeWvUTs,1337
268
+ mojo/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
269
+ mojo/models/__init__.py,sha256=1A4nsKq1ZDt85pFrqLUTVqi-DTKojulrSa6rTJK65-Q,61
270
+ mojo/models/rest.py,sha256=uGthNT8filc3mgkdZQI_iiUZ_bH8pXlh7zCSgzp_iBk,37611
271
+ mojo/models/secrets.py,sha256=nfoLNfvztu7lvv2ssrP2xwRJShnJu-iSE-HNhgEutFs,5471
272
+ mojo/rest/__init__.py,sha256=KjRXymi2g5qLVJ-KOOCFwqDocB2RxeGY6-T5HQU7np4,20
273
+ mojo/rest/info.py,sha256=ftL5NZjswWzIfRsxistZrPN8jbIAyHhygYzcb2M7UMQ,699
274
+ mojo/rest/openapi.py,sha256=sRc9GQh6tbNIV-MnJN7Fn_4NeT0QF37tro8G88MMbck,6448
275
+ mojo/serializers/__init__.py,sha256=8tbn92uhvCvxhqZ_HTcAoorJQs4MXqWXVnWh4SOvCH0,2777
276
+ mojo/serializers/core/__init__.py,sha256=cwpHCNHTx3Eft2lgfG_5c0KpudZtxsemNCsMDKIRhxk,2040
277
+ mojo/serializers/core/cache/__init__.py,sha256=yrsQglmJiwgqrgRz_0AMWG3oFViNufShFUj6xjzege0,3039
278
+ mojo/serializers/core/cache/backends.py,sha256=GFrA2NDCxb8LWR0Jn7-5Ic4aHsqMiEJrHXArCYwBTMA,17600
279
+ mojo/serializers/core/cache/base.py,sha256=at1WYOJzuK83MDufizUsJzIFdHcnUXk8Pwa-J8JTsD0,3143
280
+ mojo/serializers/core/cache/disabled.py,sha256=EJNETI3fYqamix7NbkdHsz8Tr_KN7cOrgY2cWzKkOXs,5636
281
+ mojo/serializers/core/cache/memory.py,sha256=Ks-KTD6NB509_HOqt3ygCTVzwvP5BkBREB0JrhIfY_w,9966
282
+ mojo/serializers/core/cache/redis.py,sha256=OrdNLDfPd75XZMZsZrvkcb4aS47ooN4nFoYMWk2Yae8,18763
283
+ mojo/serializers/core/cache/utils.py,sha256=E1ev4EVk_HEyDstB8NEuKLWocH0TD077_dNr_3jCo3E,14636
284
+ mojo/serializers/core/manager.py,sha256=mjgOPSyrJ1bIVrNVdP6OzCrwEhJcKn_0UxszLqM0sP0,20691
285
+ mojo/serializers/core/serializer.py,sha256=9b73uA19TfYaMkP0B640zDqoIICCm5c6nN24u42F3FA,18190
286
+ mojo/serializers/examples/settings.py,sha256=eKIKLPZIvJ2VHfr6VuOZCoy-0j9w6DZVfXgHUTjqnsc,11543
287
+ mojo/serializers/formats/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
288
+ mojo/serializers/formats/csv.py,sha256=duIhSpGjGaumRYaFEe7qL0W-H4jU-LkIheE3m5awLl8,15029
289
+ mojo/serializers/formats/localizers.py,sha256=vziGn1vI8cx_U7xc5qblXPO-e86qYwyq5e4loEPQjPk,13031
290
+ mojo/serializers/simple.py,sha256=sDQfiBsw2oTK1ZDiVj0-Y0w5G6SoeXsVFblITr2ClPw,8339
291
+ mojo/serializers/suggested_improvements.md,sha256=4YD1vzcVmLNpKFGfuQrL4kE1vVAcQicI1liDXFUvd6Y,15183
292
+ mojo/urls.py,sha256=lkB5Dxz7zaSQI2YC5nHvLgt32rcPeaj-YfknlUw_xzQ,1201
293
+ testit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
294
+ testit/client.py,sha256=QkswF2ubCgIwCoMQgxrnlleD_a72gBOkv4dtaLCo6kQ,5400
295
+ testit/faker.py,sha256=fdrgVkgdgypiGZGigBb9uyWHopflulaHrLOmzBdfCFA,393
296
+ testit/helpers.py,sha256=JUT_Mhd0Pb_fhmyP9zThO8hctIraPBEEnuj0thTsycA,6407
297
+ testit/runner.py,sha256=cxdvtMd_4l4-PoKCO35sP96DKOIw30ozGhNVa4BEI0I,11148
298
+ django_nativemojo-0.1.17.dist-info/LICENSE,sha256=K2Ly2mJoqzHPrWcXQFXWbvDtphQ51huB2RbfGW7WmUM,774
299
+ django_nativemojo-0.1.17.dist-info/METADATA,sha256=PXNi7L87gayUDVAsMPdr98mi2Z4DHZ9Hvg7CFsgUFNo,4803
300
+ django_nativemojo-0.1.17.dist-info/NOTICE,sha256=FqvhpeIbbnXn4wqLHA6Ap2VhQfU2e7QVFFyRW8L_6ys,256
301
+ django_nativemojo-0.1.17.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
302
+ django_nativemojo-0.1.17.dist-info/RECORD,,
mojo/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
- __version__ = "0.1.15"
1
+ __version__ = "0.1.17"
2
2
 
3
3
  from mojo.helpers.response import JsonResponse
@@ -37,9 +37,24 @@ from mojo.serializers import (
37
37
  clear_serializer_caches,
38
38
  benchmark_serializers,
39
39
  list_serializers,
40
- set_default_serializer
40
+ set_default_serializer,
41
+ HAS_UJSON,
42
+ UJSON_VERSION
41
43
  )
42
44
 
45
+ # Import cache system for enhanced functionality
46
+ try:
47
+ from mojo.serializers.core.cache import (
48
+ get_cache_backend,
49
+ get_cache_stats,
50
+ get_available_backends,
51
+ test_backend_connectivity,
52
+ get_cache_health
53
+ )
54
+ HAS_CACHE_SYSTEM = True
55
+ except ImportError:
56
+ HAS_CACHE_SYSTEM = False
57
+
43
58
 
44
59
  class Command(BaseCommand):
45
60
  help = 'Manage MOJO serializers: benchmark, configure, and monitor performance'
@@ -146,6 +161,14 @@ class Command(BaseCommand):
146
161
  help='Graph configuration to test'
147
162
  )
148
163
 
164
+ # Cache information
165
+ cache_parser = subparsers.add_parser('cache-info', help='Show detailed cache information')
166
+ cache_parser.add_argument(
167
+ '--test-connectivity',
168
+ action='store_true',
169
+ help='Test cache backend connectivity'
170
+ )
171
+
149
172
  def handle(self, *args, **options):
150
173
  """Handle command execution."""
151
174
  action = options.get('action')
@@ -163,6 +186,7 @@ class Command(BaseCommand):
163
186
  'clear-cache': self.handle_clear_cache,
164
187
  'health': self.handle_health,
165
188
  'test': self.handle_test,
189
+ 'cache-info': self.handle_cache_info,
166
190
  }
167
191
 
168
192
  handler = handler_map.get(action)
@@ -196,6 +220,24 @@ class Command(BaseCommand):
196
220
  self.stdout.write(f" Class: {info['class_name']}")
197
221
  self.stdout.write(f" Description: {info['description']}")
198
222
 
223
+ # Show ujson information
224
+ self.stdout.write(f"\nPerformance Information:")
225
+ if HAS_UJSON:
226
+ self.stdout.write(f" ✓ ujson {UJSON_VERSION} available - optimal JSON performance")
227
+ else:
228
+ self.stdout.write(f" ⚠ ujson not available - using standard json (slower)")
229
+ self.stdout.write(f" Install with: pip install ujson")
230
+
231
+ # Show cache backend information
232
+ if HAS_CACHE_SYSTEM:
233
+ try:
234
+ cache_backend = get_cache_backend()
235
+ cache_stats = cache_backend.stats()
236
+ backend_type = cache_stats.get('backend', 'unknown')
237
+ self.stdout.write(f" ✓ Cache backend: {backend_type}")
238
+ except Exception as e:
239
+ self.stdout.write(f" ⚠ Cache backend error: {e}")
240
+
199
241
  def handle_benchmark(self, options):
200
242
  """Benchmark serializer performance."""
201
243
  model_class = self.get_model_class(options['model'])
@@ -279,6 +321,68 @@ class Command(BaseCommand):
279
321
  self.style.SUCCESS("Performance statistics cleared")
280
322
  )
281
323
 
324
+ def handle_cache_info(self, options):
325
+ """Show detailed cache information."""
326
+ if not HAS_CACHE_SYSTEM:
327
+ self.stdout.write(
328
+ self.style.ERROR("Cache system not available")
329
+ )
330
+ return
331
+
332
+ self.stdout.write(self.style.SUCCESS("Cache System Information:"))
333
+
334
+ try:
335
+ # Show available backends
336
+ backends = get_available_backends()
337
+ self.stdout.write(f"\nAvailable Backends:")
338
+ for name, info in backends.items():
339
+ status = "✓" if info['available'] else "✗"
340
+ self.stdout.write(f" {status} {name}: {info['description']}")
341
+ if info.get('ujson_available'):
342
+ self.stdout.write(f" ujson: {info.get('ujson_version', 'available')}")
343
+ if info.get('error'):
344
+ self.stdout.write(f" Error: {info['error']}")
345
+
346
+ # Show current backend health
347
+ health = get_cache_health()
348
+ self.stdout.write(f"\nCache Health: {health['status'].upper()}")
349
+ if health.get('issues'):
350
+ for issue in health['issues']:
351
+ self.stdout.write(f" ⚠ {issue}")
352
+
353
+ # Show recommendations
354
+ if health.get('recommendations'):
355
+ self.stdout.write(f"\nRecommendations:")
356
+ for rec in health['recommendations']:
357
+ self.stdout.write(f" • {rec}")
358
+
359
+ # Test connectivity if requested
360
+ if options.get('test_connectivity'):
361
+ self.stdout.write(f"\nTesting Cache Connectivity:")
362
+ backend_type = health.get('backend_type', 'unknown')
363
+ test_result = test_backend_connectivity(backend_type)
364
+
365
+ if test_result['connectivity']:
366
+ self.stdout.write(f" ✓ {backend_type} backend connectivity OK")
367
+ if test_result['functionality']:
368
+ perf = test_result.get('performance', {})
369
+ self.stdout.write(f" ✓ Functionality test passed")
370
+ if perf:
371
+ self.stdout.write(f" Set time: {perf.get('set_time_ms', 0)}ms")
372
+ self.stdout.write(f" Get time: {perf.get('get_time_ms', 0)}ms")
373
+ else:
374
+ self.stdout.write(f" ✗ Functionality test failed")
375
+ else:
376
+ self.stdout.write(f" ✗ {backend_type} backend connectivity failed")
377
+
378
+ for error in test_result.get('errors', []):
379
+ self.stdout.write(f" Error: {error}")
380
+
381
+ except Exception as e:
382
+ self.stdout.write(
383
+ self.style.ERROR(f"Error getting cache information: {e}")
384
+ )
385
+
282
386
  def handle_clear_cache(self, options):
283
387
  """Clear serializer caches."""
284
388
  serializer_name = options.get('serializer')
@@ -434,6 +538,21 @@ class Command(BaseCommand):
434
538
  f"{data['total_objects']} objects serialized"
435
539
  )
436
540
 
541
+ # Cache statistics
542
+ if HAS_CACHE_SYSTEM:
543
+ try:
544
+ cache_stats = get_cache_stats()
545
+ self.stdout.write(f"\nCache Statistics:")
546
+ self.stdout.write(f" Backend: {cache_stats.get('backend', 'unknown')}")
547
+ self.stdout.write(f" Hit Rate: {cache_stats.get('hit_rate', 0):.1%}")
548
+ self.stdout.write(f" Total Requests: {cache_stats.get('total_requests', 0)}")
549
+ self.stdout.write(f" Cache Size: {cache_stats.get('current_size', 0)}")
550
+ if cache_stats.get('max_size'):
551
+ utilization = cache_stats.get('current_size', 0) / cache_stats.get('max_size', 1)
552
+ self.stdout.write(f" Utilization: {utilization:.1%}")
553
+ except Exception as e:
554
+ self.stdout.write(f"\nCache Stats Error: {e}")
555
+
437
556
  # Individual serializer stats
438
557
  for key, value in stats.items():
439
558
  if key.endswith('_stats') and isinstance(value, dict):
@@ -528,4 +647,5 @@ class Command(BaseCommand):
528
647
  self.stdout.write(" clear-cache - Clear serializer caches")
529
648
  self.stdout.write(" health - Run health checks")
530
649
  self.stdout.write(" test - Test serializer functionality")
650
+ self.stdout.write(" cache-info - Show detailed cache information")
531
651
  self.stdout.write("\nUse 'python manage.py serializer_admin <action> --help' for more details")
@@ -0,0 +1,72 @@
1
+ # Generated by Django 4.2.21 on 2025-08-28
2
+
3
+ from django.conf import settings
4
+ from django.db import migrations, models
5
+ import django.db.models.deletion
6
+
7
+
8
+ class Migration(migrations.Migration):
9
+
10
+ dependencies = [
11
+ ('account', '0005_group_last_activity'),
12
+ ]
13
+
14
+ operations = [
15
+ migrations.CreateModel(
16
+ name='GeoLocatedIP',
17
+ fields=[
18
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
19
+ ('created', models.DateTimeField(auto_now_add=True)),
20
+ ('modified', models.DateTimeField(auto_now=True, db_index=True)),
21
+ ('ip_address', models.GenericIPAddressField(db_index=True, unique=True)),
22
+ ('country_code', models.CharField(blank=True, db_index=True, max_length=3, null=True)),
23
+ ('country_name', models.CharField(blank=True, max_length=100, null=True)),
24
+ ('region', models.CharField(blank=True, db_index=True, max_length=100, null=True)),
25
+ ('city', models.CharField(blank=True, max_length=100, null=True)),
26
+ ('postal_code', models.CharField(blank=True, max_length=20, null=True)),
27
+ ('latitude', models.FloatField(blank=True, null=True)),
28
+ ('longitude', models.FloatField(blank=True, null=True)),
29
+ ('timezone', models.CharField(blank=True, max_length=50, null=True)),
30
+ ('provider', models.CharField(blank=True, max_length=50, null=True)),
31
+ ('data', models.JSONField(blank=True, default=dict)),
32
+ ('expires_at', models.DateTimeField(blank=True, default=None, null=True)),
33
+ ],
34
+ options={
35
+ 'verbose_name': 'Geolocated IP',
36
+ 'verbose_name_plural': 'Geolocated IPs',
37
+ },
38
+ ),
39
+ migrations.CreateModel(
40
+ name='UserDevice',
41
+ fields=[
42
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
43
+ ('duid', models.CharField(db_index=True, max_length=255)),
44
+ ('device_info', models.JSONField(blank=True, default=dict)),
45
+ ('user_agent_hash', models.CharField(blank=True, db_index=True, max_length=64, null=True)),
46
+ ('last_ip', models.GenericIPAddressField(blank=True, null=True)),
47
+ ('first_seen', models.DateTimeField(auto_now_add=True)),
48
+ ('last_seen', models.DateTimeField(auto_now=True)),
49
+ ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='devices', to=settings.AUTH_USER_MODEL)),
50
+ ],
51
+ options={
52
+ 'ordering': ['-last_seen'],
53
+ 'unique_together': {('user', 'duid')},
54
+ },
55
+ ),
56
+ migrations.CreateModel(
57
+ name='UserDeviceLocation',
58
+ fields=[
59
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
60
+ ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='device_locations_direct', to=settings.AUTH_USER_MODEL)),
61
+ ('ip_address', models.GenericIPAddressField(db_index=True)),
62
+ ('first_seen', models.DateTimeField(auto_now_add=True)),
63
+ ('last_seen', models.DateTimeField(auto_now=True)),
64
+ ('geolocation', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='device_locations', to='account.geolocatedip')),
65
+ ('user_device', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='locations', to='account.userdevice')),
66
+ ],
67
+ options={
68
+ 'ordering': ['-last_seen'],
69
+ 'unique_together': {('user', 'user_device', 'ip_address')},
70
+ },
71
+ ),
72
+ ]
@@ -0,0 +1,16 @@
1
+ # Generated by Django 4.2.21 on 2025-08-28 16:24
2
+
3
+ from django.db import migrations
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('account', '0006_add_device_tracking_models'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.DeleteModel(
14
+ name='UserDeviceLocation',
15
+ ),
16
+ ]
@@ -0,0 +1,33 @@
1
+ # Generated by Django 4.2.21 on 2025-08-28 22:30
2
+
3
+ from django.conf import settings
4
+ from django.db import migrations, models
5
+ import django.db.models.deletion
6
+ import mojo.models.rest
7
+
8
+
9
+ class Migration(migrations.Migration):
10
+
11
+ dependencies = [
12
+ ('account', '0007_delete_userdevicelocation'),
13
+ ]
14
+
15
+ operations = [
16
+ migrations.CreateModel(
17
+ name='UserDeviceLocation',
18
+ fields=[
19
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20
+ ('ip_address', models.GenericIPAddressField(db_index=True)),
21
+ ('first_seen', models.DateTimeField(auto_now_add=True)),
22
+ ('last_seen', models.DateTimeField(auto_now=True)),
23
+ ('geolocation', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='device_locations', to='account.geolocatedip')),
24
+ ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='device_locations_direct', to=settings.AUTH_USER_MODEL)),
25
+ ('user_device', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='locations', to='account.userdevice')),
26
+ ],
27
+ options={
28
+ 'ordering': ['-last_seen'],
29
+ 'unique_together': {('user', 'user_device', 'ip_address')},
30
+ },
31
+ bases=(models.Model, mojo.models.rest.MojoModel),
32
+ ),
33
+ ]