django-spire 0.23.6__py3-none-any.whl → 0.23.8__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 (541) hide show
  1. django_spire/ai/admin.py +11 -11
  2. django_spire/ai/chat/apps.py +1 -0
  3. django_spire/ai/chat/templates/django_spire/ai/chat/widget/dialog_widget.html +1 -1
  4. django_spire/ai/chat/tests/factories.py +15 -0
  5. django_spire/ai/chat/tests/test_controller.py +45 -0
  6. django_spire/ai/chat/tests/test_models.py +301 -0
  7. django_spire/ai/chat/tests/test_prompts.py +48 -0
  8. django_spire/ai/chat/tests/test_responses.py +208 -0
  9. django_spire/ai/chat/tests/test_router/test_base_chat_router.py +66 -6
  10. django_spire/ai/chat/tests/test_router/test_chat_workflow.py +73 -3
  11. django_spire/ai/chat/tests/test_router/test_integration.py +86 -6
  12. django_spire/ai/chat/tests/test_router/test_intent_decoder.py +93 -1
  13. django_spire/ai/chat/tests/test_router/test_message_intel.py +60 -1
  14. django_spire/ai/chat/tests/test_router/test_spire_chat_router.py +110 -0
  15. django_spire/ai/chat/tests/test_urls/test_json_urls.py +202 -1
  16. django_spire/ai/context/tests/__init__.py +0 -0
  17. django_spire/ai/context/tests/test_context.py +188 -0
  18. django_spire/ai/decorators.py +7 -6
  19. django_spire/ai/prompt/tests/test_bots.py +100 -10
  20. django_spire/ai/prompt/tests/test_prompt_intel.py +83 -0
  21. django_spire/ai/prompt/tests/test_prompt_tuning.py +126 -0
  22. django_spire/ai/sms/decorators.py +8 -2
  23. django_spire/ai/sms/tests/test_sms.py +240 -16
  24. django_spire/ai/sms/tests/test_sms_intel.py +42 -0
  25. django_spire/ai/sms/tests/test_webhook.py +155 -7
  26. django_spire/ai/sms/views.py +23 -24
  27. django_spire/ai/tests/test_ai.py +131 -7
  28. django_spire/auth/apps.py +4 -2
  29. django_spire/auth/controller/controller.py +36 -23
  30. django_spire/auth/controller/exceptions.py +9 -0
  31. django_spire/auth/group/admin.py +1 -0
  32. django_spire/auth/group/apps.py +2 -0
  33. django_spire/auth/group/factories.py +17 -8
  34. django_spire/auth/group/forms.py +7 -0
  35. django_spire/auth/group/tests/test_factories.py +146 -0
  36. django_spire/auth/group/tests/test_forms.py +282 -0
  37. django_spire/auth/group/tests/test_models.py +192 -0
  38. django_spire/auth/group/tests/test_querysets.py +98 -0
  39. django_spire/auth/group/tests/test_utils.py +341 -0
  40. django_spire/auth/group/tests/test_views.py +377 -0
  41. django_spire/auth/group/urls/__init__.py +3 -1
  42. django_spire/auth/group/urls/form_urls.py +2 -0
  43. django_spire/auth/group/urls/json_urls.py +3 -0
  44. django_spire/auth/group/urls/page_urls.py +2 -0
  45. django_spire/auth/group/utils.py +6 -2
  46. django_spire/auth/group/views/form_views.py +6 -3
  47. django_spire/auth/group/views/json_views.py +6 -2
  48. django_spire/auth/mfa/admin.py +2 -0
  49. django_spire/auth/mfa/apps.py +2 -0
  50. django_spire/auth/mfa/forms.py +1 -0
  51. django_spire/auth/mfa/querysets.py +9 -2
  52. django_spire/auth/mfa/tests/test_models.py +233 -0
  53. django_spire/auth/mfa/tests/test_utils.py +106 -0
  54. django_spire/auth/mfa/urls/__init__.py +2 -0
  55. django_spire/auth/mfa/urls/page_urls.py +2 -0
  56. django_spire/auth/mfa/urls/redirect_urls.py +2 -0
  57. django_spire/auth/mfa/views/page_views.py +2 -1
  58. django_spire/auth/permissions/consts.py +2 -2
  59. django_spire/auth/permissions/decorators.py +8 -8
  60. django_spire/auth/permissions/permissions.py +28 -35
  61. django_spire/auth/permissions/tests/test_decorators.py +333 -0
  62. django_spire/auth/permissions/tests/test_permissions.py +337 -0
  63. django_spire/auth/permissions/tests/test_tools.py +305 -0
  64. django_spire/auth/permissions/tools.py +21 -15
  65. django_spire/auth/seeding/seed.py +3 -0
  66. django_spire/auth/seeding/seeder.py +2 -0
  67. django_spire/auth/tests/test_controller.py +323 -0
  68. django_spire/auth/tests/test_url_endpoints.py +9 -9
  69. django_spire/auth/tests/test_views.py +406 -0
  70. django_spire/auth/urls/admin_urls.py +2 -0
  71. django_spire/auth/urls/redirect_urls.py +2 -0
  72. django_spire/auth/user/apps.py +2 -0
  73. django_spire/auth/user/forms.py +9 -0
  74. django_spire/auth/user/models.py +1 -1
  75. django_spire/auth/user/services/services.py +1 -0
  76. django_spire/auth/user/tests/factories.py +14 -13
  77. django_spire/auth/user/tests/test_factories.py +166 -2
  78. django_spire/auth/user/tests/test_forms.py +573 -0
  79. django_spire/auth/user/tests/test_models.py +257 -0
  80. django_spire/auth/user/tests/test_services.py +200 -0
  81. django_spire/auth/user/tests/test_tools.py +153 -0
  82. django_spire/auth/user/tests/test_user_factories.py +139 -0
  83. django_spire/auth/user/tests/test_views.py +363 -0
  84. django_spire/auth/user/tools.py +7 -1
  85. django_spire/auth/user/urls/form_urls.py +3 -0
  86. django_spire/auth/user/urls/page_urls.py +3 -0
  87. django_spire/auth/user/views/form_views.py +19 -10
  88. django_spire/auth/user/views/page_views.py +8 -2
  89. django_spire/auth/views/redirect_views.py +14 -9
  90. django_spire/comment/admin.py +2 -0
  91. django_spire/comment/apps.py +2 -0
  92. django_spire/comment/templatetags/comment_tags.py +1 -0
  93. django_spire/comment/tests/test_forms.py +27 -0
  94. django_spire/comment/tests/test_models.py +215 -0
  95. django_spire/comment/tests/test_querysets.py +101 -0
  96. django_spire/comment/tests/test_utils.py +90 -0
  97. django_spire/comment/urls.py +2 -0
  98. django_spire/comment/utils.py +22 -13
  99. django_spire/comment/views.py +1 -1
  100. django_spire/conf.py +8 -6
  101. django_spire/consts.py +1 -1
  102. django_spire/contrib/breadcrumb/apps.py +2 -0
  103. django_spire/contrib/breadcrumb/breadcrumbs.py +18 -18
  104. django_spire/contrib/breadcrumb/tests/test_breadcrumbs.py +198 -0
  105. django_spire/contrib/constructor/__init__.py +3 -3
  106. django_spire/contrib/constructor/constructor.py +15 -15
  107. django_spire/contrib/constructor/django_model_constructor.py +5 -4
  108. django_spire/contrib/constructor/exceptions.py +5 -3
  109. django_spire/contrib/constructor/tests/__init__.py +0 -0
  110. django_spire/contrib/constructor/tests/test_constructor.py +193 -0
  111. django_spire/contrib/form/tests/__init__.py +0 -0
  112. django_spire/contrib/form/tests/test_forms.py +203 -0
  113. django_spire/contrib/generic_views/modal_views.py +2 -1
  114. django_spire/contrib/generic_views/portal_views.py +20 -19
  115. django_spire/contrib/generic_views/tests/__init__.py +0 -0
  116. django_spire/contrib/generic_views/tests/test_views.py +459 -0
  117. django_spire/contrib/help/apps.py +2 -0
  118. django_spire/contrib/help/templatetags/help.py +1 -0
  119. django_spire/contrib/help/tests/__init__.py +0 -0
  120. django_spire/contrib/help/tests/test_templatetags.py +100 -0
  121. django_spire/contrib/options/mixins.py +6 -5
  122. django_spire/contrib/options/tests/factories.py +5 -1
  123. django_spire/contrib/options/tests/test_options.py +234 -0
  124. django_spire/contrib/ordering/exceptions.py +7 -3
  125. django_spire/contrib/ordering/mixins.py +2 -0
  126. django_spire/contrib/ordering/querysets.py +3 -1
  127. django_spire/contrib/ordering/services/processor_service.py +8 -4
  128. django_spire/contrib/ordering/services/service.py +1 -2
  129. django_spire/contrib/ordering/tests/__init__.py +0 -0
  130. django_spire/contrib/ordering/tests/test_ordering.py +165 -0
  131. django_spire/contrib/ordering/validators.py +6 -6
  132. django_spire/contrib/pagination/templatetags/pagination_tags.py +12 -5
  133. django_spire/contrib/pagination/tests/__init__.py +0 -0
  134. django_spire/contrib/pagination/tests/test_pagination.py +179 -0
  135. django_spire/contrib/performance/decorators.py +16 -6
  136. django_spire/contrib/performance/tests/__init__.py +0 -0
  137. django_spire/contrib/performance/tests/test_performance.py +107 -0
  138. django_spire/contrib/progress/__init__.py +1 -3
  139. django_spire/contrib/progress/static/django_spire/js/contrib/progress/progress.js +38 -82
  140. django_spire/contrib/queryset/enums.py +3 -1
  141. django_spire/contrib/queryset/filter_tools.py +10 -5
  142. django_spire/contrib/queryset/mixins.py +16 -16
  143. django_spire/contrib/queryset/tests/__init__.py +0 -0
  144. django_spire/contrib/queryset/tests/test_queryset.py +137 -0
  145. django_spire/contrib/seeding/field/base.py +13 -7
  146. django_spire/contrib/seeding/field/callable.py +8 -1
  147. django_spire/contrib/seeding/field/cleaners.py +5 -5
  148. django_spire/contrib/seeding/field/custom.py +20 -10
  149. django_spire/contrib/seeding/field/django/seeder.py +8 -6
  150. django_spire/contrib/seeding/field/enums.py +7 -5
  151. django_spire/contrib/seeding/field/override.py +16 -6
  152. django_spire/contrib/seeding/field/static.py +9 -2
  153. django_spire/contrib/seeding/field/tests/test_base.py +18 -14
  154. django_spire/contrib/seeding/field/tests/test_callable.py +13 -9
  155. django_spire/contrib/seeding/field/tests/test_cleaners.py +51 -38
  156. django_spire/contrib/seeding/field/tests/test_static.py +13 -9
  157. django_spire/contrib/seeding/intelligence/bots/seeder_generator_bot.py +2 -0
  158. django_spire/contrib/seeding/intelligence/intel.py +5 -1
  159. django_spire/contrib/seeding/intelligence/prompts/factory.py +6 -1
  160. django_spire/contrib/seeding/intelligence/prompts/foreign_key_selection_prompt.py +6 -1
  161. django_spire/contrib/seeding/intelligence/prompts/generate_django_model_seeder_prompts.py +2 -0
  162. django_spire/contrib/seeding/intelligence/prompts/generic_relationship_selection_prompt.py +7 -1
  163. django_spire/contrib/seeding/intelligence/prompts/hierarchical_selection_prompt.py +6 -2
  164. django_spire/contrib/seeding/intelligence/prompts/model_field_choices_prompt.py +8 -2
  165. django_spire/contrib/seeding/intelligence/prompts/negation_prompt.py +2 -0
  166. django_spire/contrib/seeding/intelligence/prompts/objective_prompt.py +6 -1
  167. django_spire/contrib/seeding/management/commands/seeding.py +9 -3
  168. django_spire/contrib/seeding/management/example.py +2 -0
  169. django_spire/contrib/seeding/model/base.py +16 -7
  170. django_spire/contrib/seeding/model/config.py +31 -15
  171. django_spire/contrib/seeding/model/django/config.py +13 -13
  172. django_spire/contrib/seeding/model/django/seeder.py +4 -4
  173. django_spire/contrib/seeding/model/django/tests/test_seeder.py +34 -23
  174. django_spire/contrib/seeding/model/enums.py +2 -0
  175. django_spire/contrib/seeding/tests/test_config.py +71 -0
  176. django_spire/contrib/seeding/tests/test_custom.py +35 -0
  177. django_spire/contrib/seeding/tests/test_enums.py +40 -0
  178. django_spire/contrib/seeding/tests/test_intel.py +32 -0
  179. django_spire/contrib/seeding/tests/test_override.py +63 -0
  180. django_spire/contrib/service/__init__.py +2 -2
  181. django_spire/contrib/service/django_model_service.py +16 -15
  182. django_spire/contrib/service/exceptions.py +5 -3
  183. django_spire/contrib/service/tests/__init__.py +0 -0
  184. django_spire/contrib/service/tests/test_service.py +153 -0
  185. django_spire/contrib/session/apps.py +2 -0
  186. django_spire/contrib/session/controller.py +48 -42
  187. django_spire/contrib/session/templatetags/session_tags.py +11 -2
  188. django_spire/contrib/session/tests/test_session_controller.py +117 -53
  189. django_spire/contrib/tests/__init__.py +0 -0
  190. django_spire/contrib/tests/test_utils.py +37 -0
  191. django_spire/contrib/utils.py +4 -1
  192. django_spire/core/apps.py +2 -0
  193. django_spire/core/converters/tests/test_to_data.py +353 -0
  194. django_spire/core/converters/tests/test_to_enums.py +61 -41
  195. django_spire/core/converters/tests/test_to_pydantic.py +138 -109
  196. django_spire/core/converters/to_data.py +29 -10
  197. django_spire/core/converters/to_enums.py +4 -2
  198. django_spire/core/converters/to_pydantic.py +22 -22
  199. django_spire/core/decorators.py +19 -6
  200. django_spire/core/forms/widgets.py +4 -0
  201. django_spire/core/maps.py +3 -1
  202. django_spire/core/middleware/maintenance.py +3 -3
  203. django_spire/core/middleware.py +8 -6
  204. django_spire/core/redirect/__init__.py +5 -0
  205. django_spire/core/redirect/generic_redirect.py +1 -2
  206. django_spire/core/redirect/tests/__init__.py +0 -0
  207. django_spire/core/redirect/tests/test_generic_redirect.py +34 -0
  208. django_spire/core/{tests/tests_redirect.py → redirect/tests/test_safe_redirect.py} +55 -81
  209. django_spire/core/shortcuts.py +3 -3
  210. django_spire/core/static/django_spire/css/app-layout.css +1 -1
  211. django_spire/core/static/django_spire/css/app-navigation.css +3 -3
  212. django_spire/core/static/django_spire/css/bootstrap-override.css +4 -0
  213. django_spire/core/tag/admin.py +12 -0
  214. django_spire/core/tag/intelligence/tag_set_bot.py +2 -0
  215. django_spire/core/tag/mixins.py +2 -0
  216. django_spire/core/tag/models.py +2 -0
  217. django_spire/core/tag/querysets.py +2 -0
  218. django_spire/core/tag/service/tag_service.py +6 -3
  219. django_spire/core/tag/tests/test_intelligence.py +9 -9
  220. django_spire/core/tag/tests/test_tags.py +44 -54
  221. django_spire/core/tag/tests/test_tools.py +191 -0
  222. django_spire/core/tag/tools.py +3 -0
  223. django_spire/core/templates/django_spire/card/card.html +5 -2
  224. django_spire/core/templates/django_spire/card/title_card.html +9 -4
  225. django_spire/core/templates/django_spire/infinite_scroll/base.html +1 -0
  226. django_spire/core/templates/django_spire/navigation/side_navigation.html +19 -24
  227. django_spire/core/templates/django_spire/page/full_page.html +46 -16
  228. django_spire/core/templates/django_spire/table/base.html +4 -2
  229. django_spire/core/templatetags/json.py +6 -2
  230. django_spire/core/templatetags/message.py +13 -8
  231. django_spire/core/templatetags/string_formating.py +8 -5
  232. django_spire/core/templatetags/tests/__init__.py +0 -0
  233. django_spire/core/templatetags/tests/test_templatetags.py +427 -0
  234. django_spire/core/templatetags/variable_types.py +17 -9
  235. django_spire/core/tests/test_cases.py +1 -1
  236. django_spire/core/tests/test_conf.py +43 -0
  237. django_spire/core/tests/test_consts.py +28 -0
  238. django_spire/core/tests/test_context_processors.py +93 -0
  239. django_spire/core/tests/test_decorators.py +95 -0
  240. django_spire/core/tests/test_django_spire_utils.py +56 -0
  241. django_spire/core/tests/test_exceptions.py +37 -0
  242. django_spire/core/tests/test_models.py +54 -0
  243. django_spire/core/tests/test_settings.py +45 -0
  244. django_spire/core/tests/test_shortcuts.py +74 -0
  245. django_spire/core/tests/test_urls.py +16 -0
  246. django_spire/core/tests/test_utils.py +58 -0
  247. django_spire/core/urls.py +4 -1
  248. django_spire/core/utils.py +12 -8
  249. django_spire/exceptions.py +16 -1
  250. django_spire/file/admin.py +4 -2
  251. django_spire/file/apps.py +8 -10
  252. django_spire/file/fields.py +7 -7
  253. django_spire/file/forms.py +1 -1
  254. django_spire/file/interfaces.py +15 -15
  255. django_spire/file/mixins.py +1 -4
  256. django_spire/file/models.py +3 -5
  257. django_spire/file/tests/factories.py +59 -0
  258. django_spire/file/tests/test_admin.py +69 -0
  259. django_spire/file/tests/test_apps.py +24 -0
  260. django_spire/file/tests/test_fields.py +114 -0
  261. django_spire/file/tests/test_forms.py +20 -0
  262. django_spire/file/tests/test_interfaces.py +183 -0
  263. django_spire/file/tests/test_models.py +82 -0
  264. django_spire/file/tests/test_querysets.py +102 -0
  265. django_spire/file/tests/test_utils.py +32 -0
  266. django_spire/file/tests/test_views.py +145 -0
  267. django_spire/file/tests/test_widgets.py +82 -0
  268. django_spire/file/tools.py +8 -2
  269. django_spire/file/views.py +7 -3
  270. django_spire/file/widgets.py +12 -12
  271. django_spire/help_desk/admin.py +15 -0
  272. django_spire/help_desk/apps.py +2 -0
  273. django_spire/help_desk/auth/controller.py +2 -0
  274. django_spire/help_desk/choices.py +2 -0
  275. django_spire/help_desk/enums.py +2 -0
  276. django_spire/help_desk/exceptions.py +31 -3
  277. django_spire/help_desk/forms.py +2 -0
  278. django_spire/help_desk/models.py +2 -0
  279. django_spire/help_desk/querysets.py +4 -1
  280. django_spire/help_desk/services/notification_service.py +26 -27
  281. django_spire/help_desk/services/service.py +2 -3
  282. django_spire/help_desk/tests/factories.py +8 -3
  283. django_spire/help_desk/tests/test_admin.py +41 -0
  284. django_spire/help_desk/tests/test_apps.py +41 -0
  285. django_spire/help_desk/tests/test_choices.py +50 -0
  286. django_spire/help_desk/tests/test_controller.py +87 -0
  287. django_spire/help_desk/tests/test_enums.py +18 -0
  288. django_spire/help_desk/tests/test_exceptions.py +37 -0
  289. django_spire/help_desk/tests/test_forms.py +89 -0
  290. django_spire/help_desk/tests/test_models.py +59 -0
  291. django_spire/help_desk/tests/test_querysets.py +38 -0
  292. django_spire/help_desk/tests/test_services/test_notification_service.py +15 -8
  293. django_spire/help_desk/tests/test_services/test_service.py +92 -0
  294. django_spire/help_desk/tests/test_urls/test_form_urls.py +6 -6
  295. django_spire/help_desk/tests/test_urls/test_page_urls.py +8 -9
  296. django_spire/help_desk/tests/test_views/test_form_views.py +46 -19
  297. django_spire/help_desk/tests/test_views/test_page_views.py +32 -9
  298. django_spire/help_desk/urls/__init__.py +4 -1
  299. django_spire/help_desk/urls/form_urls.py +3 -0
  300. django_spire/help_desk/urls/page_urls.py +3 -0
  301. django_spire/help_desk/views/form_views.py +13 -5
  302. django_spire/help_desk/views/page_views.py +11 -3
  303. django_spire/history/activity/admin.py +2 -0
  304. django_spire/history/activity/apps.py +3 -1
  305. django_spire/history/activity/mixins.py +13 -7
  306. django_spire/history/activity/models.py +6 -5
  307. django_spire/history/activity/querysets.py +2 -0
  308. django_spire/history/activity/tests/__init__.py +0 -0
  309. django_spire/history/activity/tests/test_activity.py +176 -0
  310. django_spire/history/admin.py +9 -2
  311. django_spire/history/choices.py +3 -0
  312. django_spire/history/models.py +5 -5
  313. django_spire/history/tests/test_admin.py +93 -0
  314. django_spire/history/tests/test_history.py +101 -0
  315. django_spire/history/tests/test_mixins.py +84 -0
  316. django_spire/history/viewed/admin.py +3 -1
  317. django_spire/history/viewed/apps.py +3 -1
  318. django_spire/history/viewed/models.py +2 -0
  319. django_spire/history/viewed/tests/__init__.py +0 -0
  320. django_spire/history/viewed/tests/test_viewed.py +46 -0
  321. django_spire/knowledge/auth/tests/__init__.py +0 -0
  322. django_spire/knowledge/auth/tests/test_controller.py +116 -0
  323. django_spire/knowledge/collection/admin.py +5 -1
  324. django_spire/knowledge/collection/models.py +3 -1
  325. django_spire/knowledge/collection/seeding/seed.py +1 -0
  326. django_spire/knowledge/collection/services/factory_service.py +10 -11
  327. django_spire/knowledge/collection/services/ordering_service.py +1 -2
  328. django_spire/knowledge/collection/services/service.py +5 -10
  329. django_spire/knowledge/collection/services/tag_service.py +5 -2
  330. django_spire/knowledge/collection/tests/factories.py +28 -1
  331. django_spire/knowledge/collection/tests/test_models.py +48 -0
  332. django_spire/knowledge/collection/tests/test_querysets.py +93 -0
  333. django_spire/knowledge/collection/tests/test_services/test_factory_service.py +100 -0
  334. django_spire/knowledge/collection/tests/test_services/test_services.py +160 -0
  335. django_spire/knowledge/collection/tests/test_urls/test_form_urls.py +21 -3
  336. django_spire/knowledge/collection/tests/test_urls/test_json_urls.py +39 -1
  337. django_spire/knowledge/collection/tests/test_urls/test_page_urls.py +12 -4
  338. django_spire/knowledge/collection/urls/__init__.py +3 -0
  339. django_spire/knowledge/collection/urls/form_urls.py +2 -0
  340. django_spire/knowledge/collection/urls/json_urls.py +2 -0
  341. django_spire/knowledge/collection/urls/page_urls.py +2 -0
  342. django_spire/knowledge/collection/views/form_views.py +4 -4
  343. django_spire/knowledge/collection/views/json_views.py +5 -1
  344. django_spire/knowledge/collection/views/page_views.py +5 -2
  345. django_spire/knowledge/entry/admin.py +7 -1
  346. django_spire/knowledge/entry/forms.py +2 -0
  347. django_spire/knowledge/entry/models.py +2 -0
  348. django_spire/knowledge/entry/seeding/seed.py +3 -0
  349. django_spire/knowledge/entry/services/automation_service.py +5 -4
  350. django_spire/knowledge/entry/services/factory_service.py +7 -5
  351. django_spire/knowledge/entry/services/service.py +4 -7
  352. django_spire/knowledge/entry/services/tag_service.py +0 -1
  353. django_spire/knowledge/entry/services/tool_service.py +1 -0
  354. django_spire/knowledge/entry/services/transformation_services.py +1 -5
  355. django_spire/knowledge/entry/tests/factories.py +1 -2
  356. django_spire/knowledge/entry/tests/test_factory_service.py +20 -0
  357. django_spire/knowledge/entry/tests/test_models.py +41 -0
  358. django_spire/knowledge/entry/tests/test_querysets.py +71 -0
  359. django_spire/knowledge/entry/tests/test_services.py +94 -0
  360. django_spire/knowledge/entry/tests/test_urls/test_form_urls.py +9 -14
  361. django_spire/knowledge/entry/tests/test_urls/test_json_urls.py +48 -5
  362. django_spire/knowledge/entry/tests/test_urls/test_page_urls.py +6 -8
  363. django_spire/knowledge/entry/tests/test_urls/test_template_urls.py +40 -0
  364. django_spire/knowledge/entry/urls/form_urls.py +2 -0
  365. django_spire/knowledge/entry/urls/json_urls.py +2 -0
  366. django_spire/knowledge/entry/urls/page_urls.py +2 -0
  367. django_spire/knowledge/entry/urls/template_urls.py +2 -0
  368. django_spire/knowledge/entry/version/block/choices.py +2 -0
  369. django_spire/knowledge/entry/version/block/data/data.py +1 -0
  370. django_spire/knowledge/entry/version/block/data/list/data.py +8 -13
  371. django_spire/knowledge/entry/version/block/data/list/maps.py +3 -0
  372. django_spire/knowledge/entry/version/block/data/list/meta.py +1 -2
  373. django_spire/knowledge/entry/version/block/data/list/tests/__init__.py +0 -0
  374. django_spire/knowledge/entry/version/block/data/list/tests/test_maps.py +32 -0
  375. django_spire/knowledge/entry/version/block/data/list/tests/test_meta.py +58 -0
  376. django_spire/knowledge/entry/version/block/data/maps.py +3 -6
  377. django_spire/knowledge/entry/version/block/models.py +7 -5
  378. django_spire/knowledge/entry/version/block/seeding/constants.py +5 -4
  379. django_spire/knowledge/entry/version/block/services/service.py +2 -3
  380. django_spire/knowledge/entry/version/block/tests/factories.py +4 -10
  381. django_spire/knowledge/entry/version/block/tests/test_choices.py +56 -0
  382. django_spire/knowledge/entry/version/block/tests/test_data.py +90 -0
  383. django_spire/knowledge/entry/version/block/tests/test_maps.py +37 -0
  384. django_spire/knowledge/entry/version/block/tests/test_models.py +55 -0
  385. django_spire/knowledge/entry/version/block/tests/test_querysets.py +35 -0
  386. django_spire/knowledge/entry/version/block/tests/test_services.py +65 -0
  387. django_spire/knowledge/entry/version/choices.py +2 -0
  388. django_spire/knowledge/entry/version/converters/converter.py +1 -1
  389. django_spire/knowledge/entry/version/converters/docx_converter.py +4 -7
  390. django_spire/knowledge/entry/version/converters/markdown_converter.py +20 -20
  391. django_spire/knowledge/entry/version/maps.py +4 -5
  392. django_spire/knowledge/entry/version/querysets.py +1 -1
  393. django_spire/knowledge/entry/version/seeding/seeder.py +1 -2
  394. django_spire/knowledge/entry/version/services/processor_service.py +5 -4
  395. django_spire/knowledge/entry/version/services/service.py +1 -2
  396. django_spire/knowledge/entry/version/tests/factories.py +2 -2
  397. django_spire/knowledge/entry/version/tests/test_choices.py +18 -0
  398. django_spire/knowledge/entry/version/tests/test_converters/test_docx_converter.py +56 -8
  399. django_spire/knowledge/entry/version/tests/test_converters/test_markdown_converter.py +78 -0
  400. django_spire/knowledge/entry/version/tests/test_maps.py +58 -0
  401. django_spire/knowledge/entry/version/tests/test_models.py +23 -0
  402. django_spire/knowledge/entry/version/tests/test_querysets.py +26 -0
  403. django_spire/knowledge/entry/version/tests/test_services.py +62 -0
  404. django_spire/knowledge/entry/version/tests/test_urls/test_json_urls.py +27 -8
  405. django_spire/knowledge/entry/version/tests/test_urls/test_page_urls.py +15 -8
  406. django_spire/knowledge/entry/version/tests/test_urls/test_redirect_urls.py +38 -0
  407. django_spire/knowledge/entry/version/urls/__init__.py +3 -0
  408. django_spire/knowledge/entry/version/urls/json_urls.py +2 -1
  409. django_spire/knowledge/entry/version/urls/page_urls.py +2 -0
  410. django_spire/knowledge/entry/version/urls/redirect_urls.py +2 -0
  411. django_spire/knowledge/entry/version/views/json_views.py +5 -1
  412. django_spire/knowledge/entry/version/views/page_views.py +10 -3
  413. django_spire/knowledge/entry/version/views/redirect_views.py +5 -1
  414. django_spire/knowledge/entry/views/form_views.py +16 -8
  415. django_spire/knowledge/entry/views/json_views.py +3 -1
  416. django_spire/knowledge/entry/views/page_views.py +8 -2
  417. django_spire/knowledge/entry/views/template_views.py +7 -1
  418. django_spire/knowledge/exceptions.py +2 -1
  419. django_spire/knowledge/intelligence/intel/answer_intel.py +2 -1
  420. django_spire/knowledge/intelligence/intel/entry_intel.py +0 -1
  421. django_spire/knowledge/intelligence/workflows/knowledge_workflow.py +4 -5
  422. django_spire/knowledge/models.py +1 -2
  423. django_spire/knowledge/tests/__init__.py +0 -0
  424. django_spire/knowledge/tests/test_templatetags.py +40 -0
  425. django_spire/knowledge/tests/test_urls/__init__.py +0 -0
  426. django_spire/knowledge/tests/test_urls/test_page_urls.py +24 -0
  427. django_spire/knowledge/urls/__init__.py +2 -0
  428. django_spire/knowledge/urls/page_urls.py +2 -0
  429. django_spire/knowledge/views/page_views.py +8 -3
  430. django_spire/notification/admin.py +3 -1
  431. django_spire/notification/app/admin.py +2 -0
  432. django_spire/notification/app/apps.py +3 -1
  433. django_spire/notification/app/exceptions.py +9 -2
  434. django_spire/notification/app/models.py +8 -4
  435. django_spire/notification/app/processor.py +22 -26
  436. django_spire/notification/app/querysets.py +2 -0
  437. django_spire/notification/app/tests/__init__.py +0 -0
  438. django_spire/notification/app/tests/factories.py +34 -0
  439. django_spire/notification/app/tests/test_apps.py +24 -0
  440. django_spire/notification/app/tests/test_models.py +72 -0
  441. django_spire/notification/app/tests/test_processor.py +111 -0
  442. django_spire/notification/app/tests/test_querysets.py +90 -0
  443. django_spire/notification/app/tests/test_views/__init__.py +0 -0
  444. django_spire/notification/app/tests/test_views/test_json_views.py +48 -0
  445. django_spire/notification/app/tests/test_views/test_page_views.py +19 -0
  446. django_spire/notification/app/urls/__init__.py +3 -1
  447. django_spire/notification/app/urls/json_urls.py +6 -4
  448. django_spire/notification/app/urls/page_urls.py +4 -3
  449. django_spire/notification/app/urls/template_urls.py +4 -2
  450. django_spire/notification/apps.py +4 -1
  451. django_spire/notification/email/admin.py +5 -1
  452. django_spire/notification/email/apps.py +3 -1
  453. django_spire/notification/email/exceptions.py +4 -2
  454. django_spire/notification/email/helper.py +5 -3
  455. django_spire/notification/email/models.py +4 -0
  456. django_spire/notification/email/processor.py +19 -15
  457. django_spire/notification/email/querysets.py +3 -0
  458. django_spire/notification/email/tests/__init__.py +0 -0
  459. django_spire/notification/email/tests/factories.py +35 -0
  460. django_spire/notification/email/tests/test_apps.py +24 -0
  461. django_spire/notification/email/tests/test_models.py +52 -0
  462. django_spire/notification/email/tests/test_processor.py +92 -0
  463. django_spire/notification/email/tests/test_querysets.py +43 -0
  464. django_spire/notification/exceptions.py +17 -2
  465. django_spire/notification/managers.py +7 -1
  466. django_spire/notification/maps.py +4 -1
  467. django_spire/notification/mixins.py +2 -0
  468. django_spire/notification/models.py +3 -1
  469. django_spire/notification/processors/notification.py +12 -5
  470. django_spire/notification/processors/processor.py +2 -0
  471. django_spire/notification/processors/tests/__init__.py +0 -0
  472. django_spire/notification/processors/tests/test_notification.py +106 -0
  473. django_spire/notification/push/admin.py +10 -1
  474. django_spire/notification/push/apps.py +3 -1
  475. django_spire/notification/push/models.py +2 -3
  476. django_spire/notification/push/tests/__init__.py +0 -0
  477. django_spire/notification/push/tests/test_apps.py +24 -0
  478. django_spire/notification/push/tests/test_models.py +28 -0
  479. django_spire/notification/querysets.py +7 -1
  480. django_spire/notification/sms/admin.py +2 -0
  481. django_spire/notification/sms/apps.py +4 -1
  482. django_spire/notification/sms/automations.py +2 -0
  483. django_spire/notification/sms/choices.py +2 -0
  484. django_spire/notification/sms/exceptions.py +19 -5
  485. django_spire/notification/sms/helper.py +33 -23
  486. django_spire/notification/sms/models.py +5 -1
  487. django_spire/notification/sms/processor.py +20 -20
  488. django_spire/notification/sms/querysets.py +2 -0
  489. django_spire/notification/sms/tests/factories.py +33 -0
  490. django_spire/notification/sms/tests/test_apps.py +24 -0
  491. django_spire/notification/sms/tests/test_automation.py +38 -0
  492. django_spire/notification/sms/tests/test_choices.py +15 -0
  493. django_spire/notification/sms/tests/test_consts.py +17 -0
  494. django_spire/notification/sms/tests/test_exceptions.py +27 -0
  495. django_spire/notification/sms/tests/test_helper.py +50 -0
  496. django_spire/notification/sms/tests/test_models.py +81 -0
  497. django_spire/notification/sms/tests/test_processor.py +107 -0
  498. django_spire/notification/sms/tests/test_tools.py +25 -11
  499. django_spire/notification/sms/tools.py +16 -5
  500. django_spire/notification/sms/urls/__init__.py +3 -1
  501. django_spire/notification/sms/urls/media_urls.py +2 -0
  502. django_spire/notification/sms/views/media_views.py +14 -4
  503. django_spire/notification/tests/__init__.py +0 -0
  504. django_spire/notification/tests/factories.py +26 -0
  505. django_spire/notification/tests/test_admin.py +55 -0
  506. django_spire/notification/tests/test_apps.py +30 -0
  507. django_spire/notification/tests/test_automation.py +18 -0
  508. django_spire/notification/tests/test_choices.py +59 -0
  509. django_spire/notification/tests/test_exceptions.py +58 -0
  510. django_spire/notification/tests/test_managers.py +100 -0
  511. django_spire/notification/tests/test_maps.py +31 -0
  512. django_spire/notification/tests/test_models.py +76 -0
  513. django_spire/notification/tests/test_querysets.py +184 -0
  514. django_spire/notification/tests/test_utils.py +23 -0
  515. django_spire/notification/urls.py +3 -1
  516. django_spire/notification/utils.py +3 -1
  517. django_spire/settings.py +3 -0
  518. django_spire/theme/tests/test_context_processor.py +15 -13
  519. django_spire/theme/tests/test_enums.py +2 -2
  520. django_spire/theme/tests/test_filesystem.py +2 -5
  521. django_spire/theme/tests/test_integration.py +12 -12
  522. django_spire/theme/tests/test_model.py +40 -38
  523. django_spire/theme/tests/test_views/test_json_views.py +33 -33
  524. django_spire/theme/urls/json_urls.py +3 -0
  525. django_spire/theme/urls/page_urls.py +3 -0
  526. django_spire/urls.py +19 -15
  527. django_spire/utils.py +13 -4
  528. {django_spire-0.23.6.dist-info → django_spire-0.23.8.dist-info}/METADATA +1 -1
  529. {django_spire-0.23.6.dist-info → django_spire-0.23.8.dist-info}/RECORD +532 -361
  530. django_spire/contrib/options/tests/test_unit.py +0 -148
  531. django_spire/contrib/progress/views.py +0 -64
  532. django_spire/contrib/seeding/tests/test_seeding.py +0 -25
  533. django_spire/core/tests/test_templatetags.py +0 -117
  534. django_spire/core/tests/tests_shortcuts.py +0 -73
  535. django_spire/history/activity/tests.py +0 -3
  536. django_spire/history/activity/views.py +0 -3
  537. django_spire/knowledge/collection/tests/test_services/test_transformation_service.py +0 -71
  538. django_spire/notification/app/tests.py +0 -3
  539. {django_spire-0.23.6.dist-info → django_spire-0.23.8.dist-info}/WHEEL +0 -0
  540. {django_spire-0.23.6.dist-info → django_spire-0.23.8.dist-info}/licenses/LICENSE.md +0 -0
  541. {django_spire-0.23.6.dist-info → django_spire-0.23.8.dist-info}/top_level.txt +0 -0
@@ -1,18 +1,21 @@
1
+ from __future__ import annotations
2
+
1
3
  from datetime import datetime
4
+ from unittest.mock import MagicMock
2
5
 
3
- from django.test import TestCase, RequestFactory
4
6
  from django.contrib.sessions.middleware import SessionMiddleware
5
7
  from django.contrib.sessions.models import Session
8
+ from django.test import RequestFactory, TestCase
6
9
 
7
10
  from django_spire.contrib.session.controller import SessionController
11
+ from django_spire.contrib.session.templatetags.session_tags import session_controller_to_json
8
12
 
9
13
 
10
- class BaseSessionTestCase(TestCase):
11
- def setUp(self):
14
+ class TestSessionController(TestCase):
15
+ def setUp(self) -> None:
12
16
  self.factory = RequestFactory()
13
17
  self.request = self.factory.get('/')
14
18
 
15
- # Attach real session
16
19
  middleware = SessionMiddleware(lambda req: None)
17
20
  middleware.process_request(self.request)
18
21
 
@@ -21,85 +24,146 @@ class BaseSessionTestCase(TestCase):
21
24
  session_key='shopping_cart'
22
25
  )
23
26
 
24
- def test_base_session_add_data(self):
27
+ def test_add_data(self) -> None:
25
28
  key = 'currency'
26
29
  value = 'CAD'
27
30
 
28
31
  self.shopping_cart_session.add_data(key, value)
29
- self.assertIn(key, self.shopping_cart_session.data)
30
- self.assertEqual(self.shopping_cart_session.data[key], value)
31
32
 
32
- def test_base_session_set_item(self):
33
- key = 'currency'
34
- value = 'CAD'
33
+ assert key in self.shopping_cart_session.data
34
+ assert self.shopping_cart_session.data[key] == value
35
35
 
36
- self.shopping_cart_session[key] = value
37
- self.assertIn(key, self.shopping_cart_session.data)
38
- self.assertEqual(self.shopping_cart_session.data[key], value)
36
+ def test_data_property_returns_dict(self) -> None:
37
+ assert isinstance(self.shopping_cart_session.data, dict)
39
38
 
40
- def test_base_session_remove_data(self):
39
+ def test_getitem(self) -> None:
41
40
  self.shopping_cart_session.add_data('currency', 'CAD')
42
- self.shopping_cart_session.add_data('discount', None)
43
- self.shopping_cart_session.remove_data('currency')
44
41
 
45
- self.assertNotIn('currency', self.shopping_cart_session.data)
46
- self.assertIn('discount', self.shopping_cart_session.data)
42
+ assert self.shopping_cart_session['currency'] == 'CAD'
47
43
 
48
- def test_set_session_modified(self):
44
+ def test_has_data_false_when_empty(self) -> None:
45
+ assert self.shopping_cart_session.has_data is False
46
+
47
+ def test_has_data_true_when_data_exists(self) -> None:
49
48
  self.shopping_cart_session.add_data('currency', 'CAD')
50
- self.assertTrue(self.request.session.modified)
51
49
 
52
- def test_session_has_data(self):
53
- self.assertFalse(self.shopping_cart_session.has_data)
50
+ assert self.shopping_cart_session.has_data is True
54
51
 
52
+ def test_has_data_false_after_remove(self) -> None:
55
53
  self.shopping_cart_session.add_data('currency', 'CAD')
56
- self.assertTrue(self.shopping_cart_session.has_data)
54
+ self.shopping_cart_session.remove_data('currency')
57
55
 
56
+ assert self.shopping_cart_session.has_data is False
58
57
 
59
- self.shopping_cart_session.remove_data('currency')
60
- self.assertFalse(self.shopping_cart_session.has_data)
58
+ def test_is_expired_false_when_not_expired(self) -> None:
59
+ self.shopping_cart_session.add_data('currency', 'CAD')
61
60
 
62
- def test_session_data_to_json(self):
61
+ assert self.shopping_cart_session.is_expired is False
62
+
63
+ def test_is_expired_true_when_expired(self) -> None:
63
64
  self.shopping_cart_session.add_data('currency', 'CAD')
64
- self.shopping_cart_session.add_data('discount', None)
65
+ self.shopping_cart_session.seconds_till_expiry = -5
66
+ self.shopping_cart_session._set_timeout_datestamp()
65
67
 
66
- self.assertTrue(isinstance(self.shopping_cart_session.to_json(), str))
68
+ assert self.shopping_cart_session.is_expired is True
67
69
 
68
- # def test_to_json_errors_when_not_json_serializable(self):
69
- # self.shopping_cart_session.json_serializable = False
70
- #
71
- # with self.assertRaises(ValueError):
72
- # self.shopping_cart_session.to_json()
70
+ def test_purge_removes_session_data(self) -> None:
71
+ self.shopping_cart_session.add_data('currency', 'CAD')
72
+ self.shopping_cart_session.purge()
73
73
 
74
- def test_set_timeout_datestamp(self):
75
- self.shopping_cart_session._set_timeout_datestamp()
76
- self.assertIn('_timeout_datestamp', self.shopping_cart_session.data)
77
- self.assertTrue(datetime.now().timestamp() < self.shopping_cart_session['_timeout_datestamp'])
74
+ assert 'shopping_cart' not in self.request.session
78
75
 
79
- def test_session_data_expiry(self):
76
+ def test_remove_data(self) -> None:
80
77
  self.shopping_cart_session.add_data('currency', 'CAD')
81
- self.assertFalse(self.shopping_cart_session.is_expired)
78
+ self.shopping_cart_session.add_data('discount', None)
79
+ self.shopping_cart_session.remove_data('currency')
82
80
 
83
- self.shopping_cart_session.seconds_till_expiry = -5
84
- self.shopping_cart_session._set_timeout_datestamp()
85
- self.assertTrue(self.shopping_cart_session.is_expired)
81
+ assert 'currency' not in self.shopping_cart_session.data
82
+ assert 'discount' in self.shopping_cart_session.data
86
83
 
87
- def test_session_data_added_to_database(self):
88
- # Add something to the session
89
- self.shopping_cart_session.add_data('favorites', ['cool_shirt', 'fun_hat'] )
84
+ def test_session_data_added_to_database(self) -> None:
85
+ self.shopping_cart_session.add_data('favorites', ['cool_shirt', 'fun_hat'])
90
86
  self.request.session.save()
91
87
 
92
- # Get session from DB using session_key
93
88
  session_key = self.request.session.session_key
94
89
  session_in_db = Session.objects.get(session_key=session_key)
95
-
96
- # Decode the session data
97
90
  session_data = session_in_db.get_decoded()
98
91
 
99
- self.assertIn(self.shopping_cart_session.session_key, session_data)
100
- self.assertIn('favorites', session_data[self.shopping_cart_session.session_key])
101
- self.assertEqual(
102
- session_data[self.shopping_cart_session.session_key]['favorites'],
103
- ['cool_shirt', 'fun_hat']
92
+ assert self.shopping_cart_session.session_key in session_data
93
+ assert 'favorites' in session_data[self.shopping_cart_session.session_key]
94
+ assert session_data[self.shopping_cart_session.session_key]['favorites'] == ['cool_shirt', 'fun_hat']
95
+
96
+ def test_set_modified(self) -> None:
97
+ self.shopping_cart_session.add_data('currency', 'CAD')
98
+
99
+ assert self.request.session.modified is True
100
+
101
+ def test_set_timeout_datestamp(self) -> None:
102
+ self.shopping_cart_session._set_timeout_datestamp()
103
+
104
+ assert '_timeout_datestamp' in self.shopping_cart_session.data
105
+ assert datetime.now().timestamp() < self.shopping_cart_session['_timeout_datestamp']
106
+
107
+ def test_setitem(self) -> None:
108
+ key = 'currency'
109
+ value = 'CAD'
110
+
111
+ self.shopping_cart_session[key] = value
112
+
113
+ assert key in self.shopping_cart_session.data
114
+ assert self.shopping_cart_session.data[key] == value
115
+
116
+ def test_timeout_datestamp_returns_float(self) -> None:
117
+ self.shopping_cart_session._set_timeout_datestamp()
118
+
119
+ assert isinstance(self.shopping_cart_session.timeout_datestamp, float)
120
+
121
+ def test_timeout_datestamp_returns_zero_when_not_set(self) -> None:
122
+ controller = SessionController(
123
+ request=self.request,
124
+ session_key='new_session'
104
125
  )
105
126
 
127
+ assert controller.timeout_datestamp == 0
128
+
129
+ def test_to_json_returns_string(self) -> None:
130
+ self.shopping_cart_session.add_data('currency', 'CAD')
131
+ self.shopping_cart_session.add_data('discount', None)
132
+
133
+ assert isinstance(self.shopping_cart_session.to_json(), str)
134
+
135
+
136
+ class TestSessionControllerToJson(TestCase):
137
+ def setUp(self) -> None:
138
+ self.factory = RequestFactory()
139
+
140
+ def _create_context_with_session(self) -> MagicMock:
141
+ request = self.factory.get('/')
142
+ middleware = SessionMiddleware(lambda req: None)
143
+ middleware.process_request(request)
144
+
145
+ context = MagicMock()
146
+ context.get.return_value = request
147
+
148
+ return context
149
+
150
+ def test_returns_escaped_json(self) -> None:
151
+ context = self._create_context_with_session()
152
+
153
+ result = session_controller_to_json(context, 'test_key')
154
+
155
+ assert isinstance(result, str)
156
+
157
+ def test_calls_context_get_with_request(self) -> None:
158
+ context = self._create_context_with_session()
159
+
160
+ session_controller_to_json(context, 'test_key')
161
+
162
+ context.get.assert_called_once_with('request')
163
+
164
+ def test_returns_safe_string(self) -> None:
165
+ context = self._create_context_with_session()
166
+
167
+ result = session_controller_to_json(context, 'test_key')
168
+
169
+ assert hasattr(result, '__html__')
File without changes
@@ -0,0 +1,37 @@
1
+ from __future__ import annotations
2
+
3
+ from django.test import TestCase
4
+
5
+ from django_spire.contrib.utils import truncate_string
6
+
7
+
8
+ class TestTruncateString(TestCase):
9
+ def test_returns_original_when_equal_to_length(self) -> None:
10
+ result = truncate_string('hello', 5)
11
+
12
+ assert result == 'hello'
13
+
14
+ def test_returns_original_when_shorter_than_length(self) -> None:
15
+ result = truncate_string('hi', 10)
16
+
17
+ assert result == 'hi'
18
+
19
+ def test_truncates_when_longer_than_length(self) -> None:
20
+ result = truncate_string('hello world', 8)
21
+
22
+ assert result == 'hello...'
23
+
24
+ def test_truncates_with_ellipsis(self) -> None:
25
+ result = truncate_string('this is a long string', 10)
26
+
27
+ assert result.endswith('...')
28
+
29
+ def test_truncated_length_equals_specified_length(self) -> None:
30
+ result = truncate_string('this is a long string', 10)
31
+
32
+ assert len(result) == 10
33
+
34
+ def test_empty_string(self) -> None:
35
+ result = truncate_string('', 5)
36
+
37
+ assert result == ''
@@ -1,2 +1,5 @@
1
+ from __future__ import annotations
2
+
3
+
1
4
  def truncate_string(string: str, length: int) -> str:
2
- return string[:(length - 3)] + '...' if len(string) > length else string
5
+ return string[:(length - 3)] + '...' if len(string) > length else string
django_spire/core/apps.py CHANGED
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from django.apps import AppConfig
2
4
 
3
5
 
@@ -0,0 +1,353 @@
1
+ from __future__ import annotations
2
+
3
+ import datetime
4
+
5
+ from unittest import TestCase
6
+ from uuid import UUID
7
+
8
+ from django.core.validators import MaxValueValidator, MinValueValidator
9
+ from django.db import models
10
+
11
+ from django_spire.core.converters.to_data import DjangoFieldToFakerData, fake_model_field_value
12
+
13
+
14
+ class TestDjangoFieldToFakerData(TestCase):
15
+ def test_binary_field_data(self) -> None:
16
+ class BinaryModel(models.Model):
17
+ data = models.BinaryField()
18
+
19
+ class Meta:
20
+ managed = False
21
+ app_label = 'test_to_data'
22
+
23
+ def __str__(self) -> str:
24
+ return 'model'
25
+
26
+ field = BinaryModel._meta.get_field('data')
27
+ result = DjangoFieldToFakerData(field).convert()
28
+
29
+ assert isinstance(result, bytes)
30
+ assert len(result) == 16
31
+
32
+ def test_boolean_field_data(self) -> None:
33
+ class BooleanModel(models.Model):
34
+ is_active = models.BooleanField()
35
+
36
+ class Meta:
37
+ managed = False
38
+ app_label = 'test_to_data'
39
+
40
+ def __str__(self) -> str:
41
+ return 'model'
42
+
43
+ field = BooleanModel._meta.get_field('is_active')
44
+ result = DjangoFieldToFakerData(field).convert()
45
+
46
+ assert isinstance(result, bool)
47
+
48
+ def test_char_field_data(self) -> None:
49
+ class CharModel(models.Model):
50
+ name = models.CharField(max_length=50)
51
+
52
+ class Meta:
53
+ managed = False
54
+ app_label = 'test_to_data'
55
+
56
+ def __str__(self) -> str:
57
+ return 'model'
58
+
59
+ field = CharModel._meta.get_field('name')
60
+ result = DjangoFieldToFakerData(field).convert()
61
+
62
+ assert isinstance(result, str)
63
+ assert len(result) <= 50
64
+
65
+ def test_char_field_with_choices(self) -> None:
66
+ class ChoicesModel(models.Model):
67
+ status = models.CharField(
68
+ max_length=10,
69
+ choices=[('A', 'Active'), ('I', 'Inactive')]
70
+ )
71
+
72
+ class Meta:
73
+ managed = False
74
+ app_label = 'test_to_data'
75
+
76
+ def __str__(self) -> str:
77
+ return 'model'
78
+
79
+ field = ChoicesModel._meta.get_field('status')
80
+ result = DjangoFieldToFakerData(field).convert()
81
+
82
+ assert result in ['A', 'I']
83
+
84
+ def test_custom_faker_method(self) -> None:
85
+ class CustomFakerModel(models.Model):
86
+ name = models.CharField(max_length=100)
87
+
88
+ class Meta:
89
+ managed = False
90
+ app_label = 'test_to_data'
91
+
92
+ def __str__(self) -> str:
93
+ return 'model'
94
+
95
+ field = CustomFakerModel._meta.get_field('name')
96
+ result = DjangoFieldToFakerData(field, faker_method=('first_name',)).convert()
97
+
98
+ assert isinstance(result, str)
99
+
100
+ def test_custom_faker_method_with_kwargs(self) -> None:
101
+ class CustomFakerKwargsModel(models.Model):
102
+ number = models.IntegerField()
103
+
104
+ class Meta:
105
+ managed = False
106
+ app_label = 'test_to_data'
107
+
108
+ def __str__(self) -> str:
109
+ return 'model'
110
+
111
+ field = CustomFakerKwargsModel._meta.get_field('number')
112
+ result = DjangoFieldToFakerData(
113
+ field,
114
+ faker_method=('random_int', {'min': 100, 'max': 200})
115
+ ).convert()
116
+
117
+ assert isinstance(result, int)
118
+ assert 100 <= result <= 200
119
+
120
+ def test_date_field_data(self) -> None:
121
+ class DateModel(models.Model):
122
+ created = models.DateField()
123
+
124
+ class Meta:
125
+ managed = False
126
+ app_label = 'test_to_data'
127
+
128
+ def __str__(self) -> str:
129
+ return 'model'
130
+
131
+ field = DateModel._meta.get_field('created')
132
+ result = DjangoFieldToFakerData(field).convert()
133
+
134
+ assert isinstance(result, datetime.date)
135
+
136
+ def test_date_time_field_data(self) -> None:
137
+ class DateTimeModel(models.Model):
138
+ created_at = models.DateTimeField()
139
+
140
+ class Meta:
141
+ managed = False
142
+ app_label = 'test_to_data'
143
+
144
+ def __str__(self) -> str:
145
+ return 'model'
146
+
147
+ field = DateTimeModel._meta.get_field('created_at')
148
+ result = DjangoFieldToFakerData(field).convert()
149
+
150
+ assert isinstance(result, datetime.datetime)
151
+
152
+ def test_decimal_field_data(self) -> None:
153
+ class DecimalModel(models.Model):
154
+ price = models.DecimalField(max_digits=10, decimal_places=2)
155
+
156
+ class Meta:
157
+ managed = False
158
+ app_label = 'test_to_data'
159
+
160
+ def __str__(self) -> str:
161
+ return 'model'
162
+
163
+ field = DecimalModel._meta.get_field('price')
164
+ result = DjangoFieldToFakerData(field).convert()
165
+
166
+ assert isinstance(result, float)
167
+
168
+ def test_email_field_data(self) -> None:
169
+ """EmailField.get_internal_type() returns 'CharField', so it uses _char_field_data"""
170
+
171
+ class EmailModel(models.Model):
172
+ email = models.EmailField()
173
+
174
+ class Meta:
175
+ managed = False
176
+ app_label = 'test_to_data'
177
+
178
+ def __str__(self) -> str:
179
+ return 'model'
180
+
181
+ field = EmailModel._meta.get_field('email')
182
+ result = DjangoFieldToFakerData(field).convert()
183
+
184
+ assert isinstance(result, str)
185
+
186
+ def test_integer_field_data(self) -> None:
187
+ class IntegerModel(models.Model):
188
+ count = models.IntegerField()
189
+
190
+ class Meta:
191
+ managed = False
192
+ app_label = 'test_to_data'
193
+
194
+ def __str__(self) -> str:
195
+ return 'model'
196
+
197
+ field = IntegerModel._meta.get_field('count')
198
+ result = DjangoFieldToFakerData(field).convert()
199
+
200
+ assert isinstance(result, int)
201
+
202
+ def test_integer_field_with_validators(self) -> None:
203
+ class IntegerValidatorModel(models.Model):
204
+ count = models.IntegerField(
205
+ validators=[MinValueValidator(10), MaxValueValidator(20)]
206
+ )
207
+
208
+ class Meta:
209
+ managed = False
210
+ app_label = 'test_to_data'
211
+
212
+ def __str__(self) -> str:
213
+ return 'model'
214
+
215
+ field = IntegerValidatorModel._meta.get_field('count')
216
+ result = DjangoFieldToFakerData(field).convert()
217
+
218
+ assert isinstance(result, int)
219
+ assert 10 <= result <= 20
220
+
221
+ def test_positive_integer_field_data(self) -> None:
222
+ class PositiveIntegerModel(models.Model):
223
+ count = models.PositiveIntegerField()
224
+
225
+ class Meta:
226
+ managed = False
227
+ app_label = 'test_to_data'
228
+
229
+ def __str__(self) -> str:
230
+ return 'model'
231
+
232
+ field = PositiveIntegerModel._meta.get_field('count')
233
+ result = DjangoFieldToFakerData(field).convert()
234
+
235
+ assert isinstance(result, int)
236
+ assert result >= 0
237
+
238
+ def test_slug_field_data(self) -> None:
239
+ class SlugModel(models.Model):
240
+ slug = models.SlugField()
241
+
242
+ class Meta:
243
+ managed = False
244
+ app_label = 'test_to_data'
245
+
246
+ def __str__(self) -> str:
247
+ return 'model'
248
+
249
+ field = SlugModel._meta.get_field('slug')
250
+ result = DjangoFieldToFakerData(field).convert()
251
+
252
+ assert isinstance(result, str)
253
+
254
+ def test_text_field_data(self) -> None:
255
+ class TextModel(models.Model):
256
+ description = models.TextField()
257
+
258
+ class Meta:
259
+ managed = False
260
+ app_label = 'test_to_data'
261
+
262
+ def __str__(self) -> str:
263
+ return 'model'
264
+
265
+ field = TextModel._meta.get_field('description')
266
+ result = DjangoFieldToFakerData(field).convert()
267
+
268
+ assert isinstance(result, str)
269
+
270
+ def test_time_field_data(self) -> None:
271
+ class TimeModel(models.Model):
272
+ start_time = models.TimeField()
273
+
274
+ class Meta:
275
+ managed = False
276
+ app_label = 'test_to_data'
277
+
278
+ def __str__(self) -> str:
279
+ return 'model'
280
+
281
+ field = TimeModel._meta.get_field('start_time')
282
+ result = DjangoFieldToFakerData(field).convert()
283
+
284
+ assert isinstance(result, str)
285
+
286
+ def test_url_field_data(self) -> None:
287
+ """URLField.get_internal_type() returns 'CharField', so it uses _char_field_data"""
288
+
289
+ class UrlModel(models.Model):
290
+ website = models.URLField()
291
+
292
+ class Meta:
293
+ managed = False
294
+ app_label = 'test_to_data'
295
+
296
+ def __str__(self) -> str:
297
+ return 'model'
298
+
299
+ field = UrlModel._meta.get_field('website')
300
+ result = DjangoFieldToFakerData(field).convert()
301
+
302
+ assert isinstance(result, str)
303
+
304
+ def test_uuid_field_data(self) -> None:
305
+ class UuidModel(models.Model):
306
+ uuid = models.UUIDField()
307
+
308
+ class Meta:
309
+ managed = False
310
+ app_label = 'test_to_data'
311
+
312
+ def __str__(self) -> str:
313
+ return 'model'
314
+
315
+ field = UuidModel._meta.get_field('uuid')
316
+ result = DjangoFieldToFakerData(field).convert()
317
+
318
+ assert isinstance(result, str)
319
+ UUID(result)
320
+
321
+
322
+ class TestFakeModelFieldValue(TestCase):
323
+ def test_fake_model_field_value(self) -> None:
324
+ class FakeValueModel(models.Model):
325
+ name = models.CharField(max_length=50)
326
+
327
+ class Meta:
328
+ managed = False
329
+ app_label = 'test_to_data'
330
+
331
+ def __str__(self) -> str:
332
+ return 'model'
333
+
334
+ result = fake_model_field_value(FakeValueModel, 'name')
335
+
336
+ assert isinstance(result, str)
337
+ assert len(result) <= 50
338
+
339
+ def test_fake_model_field_value_with_faker_method(self) -> None:
340
+ class FakeValueFakerModel(models.Model):
341
+ email = models.EmailField()
342
+
343
+ class Meta:
344
+ managed = False
345
+ app_label = 'test_to_data'
346
+
347
+ def __str__(self) -> str:
348
+ return 'model'
349
+
350
+ result = fake_model_field_value(FakeValueFakerModel, 'email', faker_method=('email',))
351
+
352
+ assert isinstance(result, str)
353
+ assert '@' in result