arthexis 0.1.21__tar.gz → 0.1.22__tar.gz

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.

Potentially problematic release.


This version of arthexis might be problematic. Click here for more details.

Files changed (244) hide show
  1. {arthexis-0.1.21 → arthexis-0.1.22}/PKG-INFO +8 -8
  2. {arthexis-0.1.21 → arthexis-0.1.22}/arthexis.egg-info/PKG-INFO +8 -8
  3. {arthexis-0.1.21 → arthexis-0.1.22}/arthexis.egg-info/SOURCES.txt +1 -1
  4. {arthexis-0.1.21 → arthexis-0.1.22}/arthexis.egg-info/requires.txt +7 -7
  5. {arthexis-0.1.21 → arthexis-0.1.22}/config/settings.py +4 -0
  6. {arthexis-0.1.21 → arthexis-0.1.22}/config/urls.py +5 -0
  7. {arthexis-0.1.21 → arthexis-0.1.22}/core/admin.py +139 -19
  8. arthexis-0.1.22/core/environment.py +60 -0
  9. {arthexis-0.1.21 → arthexis-0.1.22}/core/models.py +419 -2
  10. {arthexis-0.1.21 → arthexis-0.1.22}/core/system.py +76 -0
  11. {arthexis-0.1.21 → arthexis-0.1.22}/core/tests.py +152 -8
  12. {arthexis-0.1.21 → arthexis-0.1.22}/core/views.py +35 -1
  13. {arthexis-0.1.21 → arthexis-0.1.22}/nodes/admin.py +148 -38
  14. {arthexis-0.1.21 → arthexis-0.1.22}/nodes/apps.py +11 -0
  15. {arthexis-0.1.21 → arthexis-0.1.22}/nodes/models.py +26 -6
  16. {arthexis-0.1.21 → arthexis-0.1.22}/nodes/tests.py +214 -1
  17. {arthexis-0.1.21 → arthexis-0.1.22}/nodes/views.py +1 -0
  18. {arthexis-0.1.21 → arthexis-0.1.22}/ocpp/admin.py +20 -1
  19. {arthexis-0.1.21 → arthexis-0.1.22}/ocpp/consumers.py +1 -0
  20. {arthexis-0.1.21 → arthexis-0.1.22}/ocpp/models.py +23 -1
  21. {arthexis-0.1.21 → arthexis-0.1.22}/ocpp/tasks.py +99 -1
  22. {arthexis-0.1.21 → arthexis-0.1.22}/ocpp/tests.py +227 -2
  23. {arthexis-0.1.21 → arthexis-0.1.22}/ocpp/views.py +281 -3
  24. {arthexis-0.1.21 → arthexis-0.1.22}/pages/admin.py +112 -15
  25. arthexis-0.1.22/pages/apps.py +45 -0
  26. {arthexis-0.1.21 → arthexis-0.1.22}/pages/forms.py +31 -8
  27. {arthexis-0.1.21 → arthexis-0.1.22}/pages/models.py +42 -2
  28. {arthexis-0.1.21 → arthexis-0.1.22}/pages/tests.py +361 -22
  29. {arthexis-0.1.21 → arthexis-0.1.22}/pages/urls.py +5 -0
  30. {arthexis-0.1.21 → arthexis-0.1.22}/pages/views.py +264 -11
  31. {arthexis-0.1.21 → arthexis-0.1.22}/pyproject.toml +2 -2
  32. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_admin_system_stop.py +18 -3
  33. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_odoo_product.py +36 -0
  34. arthexis-0.1.22/tests/test_readme_assets.py +87 -0
  35. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_shell_scripts.py +5 -0
  36. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_version_endpoint.py +15 -0
  37. arthexis-0.1.21/core/environment.py +0 -297
  38. arthexis-0.1.21/pages/apps.py +0 -13
  39. arthexis-0.1.21/tests/test_environment_network_setup_form.py +0 -39
  40. {arthexis-0.1.21 → arthexis-0.1.22}/LICENSE +0 -0
  41. {arthexis-0.1.21 → arthexis-0.1.22}/README.md +0 -0
  42. {arthexis-0.1.21 → arthexis-0.1.22}/arthexis.egg-info/dependency_links.txt +0 -0
  43. {arthexis-0.1.21 → arthexis-0.1.22}/arthexis.egg-info/top_level.txt +0 -0
  44. {arthexis-0.1.21 → arthexis-0.1.22}/config/__init__.py +0 -0
  45. {arthexis-0.1.21 → arthexis-0.1.22}/config/active_app.py +0 -0
  46. {arthexis-0.1.21 → arthexis-0.1.22}/config/asgi.py +0 -0
  47. {arthexis-0.1.21 → arthexis-0.1.22}/config/auth_app.py +0 -0
  48. {arthexis-0.1.21 → arthexis-0.1.22}/config/celery.py +0 -0
  49. {arthexis-0.1.21 → arthexis-0.1.22}/config/context_processors.py +0 -0
  50. {arthexis-0.1.21 → arthexis-0.1.22}/config/horologia_app.py +0 -0
  51. {arthexis-0.1.21 → arthexis-0.1.22}/config/loadenv.py +0 -0
  52. {arthexis-0.1.21 → arthexis-0.1.22}/config/logging.py +0 -0
  53. {arthexis-0.1.21 → arthexis-0.1.22}/config/middleware.py +0 -0
  54. {arthexis-0.1.21 → arthexis-0.1.22}/config/offline.py +0 -0
  55. {arthexis-0.1.21 → arthexis-0.1.22}/config/settings_helpers.py +0 -0
  56. {arthexis-0.1.21 → arthexis-0.1.22}/config/wsgi.py +0 -0
  57. {arthexis-0.1.21 → arthexis-0.1.22}/core/__init__.py +0 -0
  58. {arthexis-0.1.21 → arthexis-0.1.22}/core/admin_history.py +0 -0
  59. {arthexis-0.1.21 → arthexis-0.1.22}/core/admindocs.py +0 -0
  60. {arthexis-0.1.21 → arthexis-0.1.22}/core/apps.py +0 -0
  61. {arthexis-0.1.21 → arthexis-0.1.22}/core/auto_upgrade.py +0 -0
  62. {arthexis-0.1.21 → arthexis-0.1.22}/core/backends.py +0 -0
  63. {arthexis-0.1.21 → arthexis-0.1.22}/core/changelog.py +0 -0
  64. {arthexis-0.1.21 → arthexis-0.1.22}/core/entity.py +0 -0
  65. {arthexis-0.1.21 → arthexis-0.1.22}/core/fields.py +0 -0
  66. {arthexis-0.1.21 → arthexis-0.1.22}/core/form_fields.py +0 -0
  67. {arthexis-0.1.21 → arthexis-0.1.22}/core/github_helper.py +0 -0
  68. {arthexis-0.1.21 → arthexis-0.1.22}/core/github_issues.py +0 -0
  69. {arthexis-0.1.21 → arthexis-0.1.22}/core/github_repos.py +0 -0
  70. {arthexis-0.1.21 → arthexis-0.1.22}/core/lcd_screen.py +0 -0
  71. {arthexis-0.1.21 → arthexis-0.1.22}/core/liveupdate.py +0 -0
  72. {arthexis-0.1.21 → arthexis-0.1.22}/core/log_paths.py +0 -0
  73. {arthexis-0.1.21 → arthexis-0.1.22}/core/mailer.py +0 -0
  74. {arthexis-0.1.21 → arthexis-0.1.22}/core/middleware.py +0 -0
  75. {arthexis-0.1.21 → arthexis-0.1.22}/core/notifications.py +0 -0
  76. {arthexis-0.1.21 → arthexis-0.1.22}/core/public_wifi.py +0 -0
  77. {arthexis-0.1.21 → arthexis-0.1.22}/core/reference_utils.py +0 -0
  78. {arthexis-0.1.21 → arthexis-0.1.22}/core/release.py +0 -0
  79. {arthexis-0.1.21 → arthexis-0.1.22}/core/rfid_import_export.py +0 -0
  80. {arthexis-0.1.21 → arthexis-0.1.22}/core/sigil_builder.py +0 -0
  81. {arthexis-0.1.21 → arthexis-0.1.22}/core/sigil_context.py +0 -0
  82. {arthexis-0.1.21 → arthexis-0.1.22}/core/sigil_resolver.py +0 -0
  83. {arthexis-0.1.21 → arthexis-0.1.22}/core/tasks.py +0 -0
  84. {arthexis-0.1.21 → arthexis-0.1.22}/core/temp_passwords.py +0 -0
  85. {arthexis-0.1.21 → arthexis-0.1.22}/core/test_system_info.py +0 -0
  86. {arthexis-0.1.21 → arthexis-0.1.22}/core/tests_liveupdate.py +0 -0
  87. {arthexis-0.1.21 → arthexis-0.1.22}/core/urls.py +0 -0
  88. {arthexis-0.1.21 → arthexis-0.1.22}/core/user_data.py +0 -0
  89. {arthexis-0.1.21 → arthexis-0.1.22}/core/widgets.py +0 -0
  90. {arthexis-0.1.21 → arthexis-0.1.22}/nodes/__init__.py +0 -0
  91. {arthexis-0.1.21 → arthexis-0.1.22}/nodes/backends.py +0 -0
  92. {arthexis-0.1.21 → arthexis-0.1.22}/nodes/dns.py +0 -0
  93. {arthexis-0.1.21 → arthexis-0.1.22}/nodes/feature_checks.py +0 -0
  94. {arthexis-0.1.21 → arthexis-0.1.22}/nodes/lcd.py +0 -0
  95. {arthexis-0.1.21 → arthexis-0.1.22}/nodes/reports.py +0 -0
  96. {arthexis-0.1.21 → arthexis-0.1.22}/nodes/rfid_sync.py +0 -0
  97. {arthexis-0.1.21 → arthexis-0.1.22}/nodes/signals.py +0 -0
  98. {arthexis-0.1.21 → arthexis-0.1.22}/nodes/tasks.py +0 -0
  99. {arthexis-0.1.21 → arthexis-0.1.22}/nodes/urls.py +0 -0
  100. {arthexis-0.1.21 → arthexis-0.1.22}/nodes/utils.py +0 -0
  101. {arthexis-0.1.21 → arthexis-0.1.22}/ocpp/__init__.py +0 -0
  102. {arthexis-0.1.21 → arthexis-0.1.22}/ocpp/apps.py +0 -0
  103. {arthexis-0.1.21 → arthexis-0.1.22}/ocpp/evcs.py +0 -0
  104. {arthexis-0.1.21 → arthexis-0.1.22}/ocpp/evcs_discovery.py +0 -0
  105. {arthexis-0.1.21 → arthexis-0.1.22}/ocpp/reference_utils.py +0 -0
  106. {arthexis-0.1.21 → arthexis-0.1.22}/ocpp/routing.py +0 -0
  107. {arthexis-0.1.21 → arthexis-0.1.22}/ocpp/simulator.py +0 -0
  108. {arthexis-0.1.21 → arthexis-0.1.22}/ocpp/status_display.py +0 -0
  109. {arthexis-0.1.21 → arthexis-0.1.22}/ocpp/store.py +0 -0
  110. {arthexis-0.1.21 → arthexis-0.1.22}/ocpp/test_export_import.py +0 -0
  111. {arthexis-0.1.21 → arthexis-0.1.22}/ocpp/test_rfid.py +0 -0
  112. {arthexis-0.1.21 → arthexis-0.1.22}/ocpp/transactions_io.py +0 -0
  113. {arthexis-0.1.21 → arthexis-0.1.22}/ocpp/urls.py +0 -0
  114. {arthexis-0.1.21 → arthexis-0.1.22}/pages/__init__.py +0 -0
  115. {arthexis-0.1.21 → arthexis-0.1.22}/pages/checks.py +0 -0
  116. {arthexis-0.1.21 → arthexis-0.1.22}/pages/context_processors.py +0 -0
  117. {arthexis-0.1.21 → arthexis-0.1.22}/pages/defaults.py +0 -0
  118. {arthexis-0.1.21 → arthexis-0.1.22}/pages/middleware.py +0 -0
  119. {arthexis-0.1.21 → arthexis-0.1.22}/pages/module_defaults.py +0 -0
  120. {arthexis-0.1.21 → arthexis-0.1.22}/pages/site_config.py +0 -0
  121. {arthexis-0.1.21 → arthexis-0.1.22}/pages/tasks.py +0 -0
  122. {arthexis-0.1.21 → arthexis-0.1.22}/pages/utils.py +0 -0
  123. {arthexis-0.1.21 → arthexis-0.1.22}/setup.cfg +0 -0
  124. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_acronym_capitalization.py +0 -0
  125. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_admin_client_report.py +0 -0
  126. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_admin_doc_commands.py +0 -0
  127. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_admin_doc_model_groups.py +0 -0
  128. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_admin_history.py +0 -0
  129. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_admin_index_actions.py +0 -0
  130. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_admin_model_graph.py +0 -0
  131. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_admin_object_history.py +0 -0
  132. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_admin_profile_link.py +0 -0
  133. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_allowed_hosts_hostname.py +0 -0
  134. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_api_login_required.py +0 -0
  135. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_auto_upgrade_scheduler.py +0 -0
  136. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_awg_admin.py +0 -0
  137. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_benchmark_command.py +0 -0
  138. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_build_pypi_command.py +0 -0
  139. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_celery_no_debug.py +0 -0
  140. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_changelog_builder.py +0 -0
  141. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_check_admin_command.py +0 -0
  142. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_check_migrations_script.py +0 -0
  143. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_check_pypi_command.py +0 -0
  144. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_clean_release_logs_command.py +0 -0
  145. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_client_report_form.py +0 -0
  146. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_client_report_generation.py +0 -0
  147. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_client_report_schedule.py +0 -0
  148. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_csrf_failure.py +0 -0
  149. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_csrf_origin_subnet.py +0 -0
  150. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_dist_cleanup.py +0 -0
  151. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_email_collector.py +0 -0
  152. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_email_inbox.py +0 -0
  153. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_email_inbox_admin.py +0 -0
  154. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_email_inbox_search_action.py +0 -0
  155. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_email_outbox_admin.py +0 -0
  156. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_email_profiles.py +0 -0
  157. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_email_transaction.py +0 -0
  158. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_env_refresh_clean.py +0 -0
  159. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_env_refresh_pip.py +0 -0
  160. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_env_refresh_unlink.py +0 -0
  161. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_experience_admin_group.py +0 -0
  162. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_fixture_presence.py +0 -0
  163. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_footer_no_references.py +0 -0
  164. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_footer_presence.py +0 -0
  165. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_footer_render.py +0 -0
  166. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_git_checks.py +0 -0
  167. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_github_issue_reporting.py +0 -0
  168. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_install_script.py +0 -0
  169. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_invitation_login_view.py +0 -0
  170. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_language_switch.py +0 -0
  171. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_lcd_check_command.py +0 -0
  172. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_lcd_smbus2.py +0 -0
  173. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_localhost_admin_backend.py +0 -0
  174. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_log_paths.py +0 -0
  175. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_login_view_no_site.py +0 -0
  176. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_manage_debug_flag.py +0 -0
  177. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_manuals.py +0 -0
  178. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_message_command.py +0 -0
  179. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_migrations.py +0 -0
  180. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_model_verbose_name_capitalization.py +0 -0
  181. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_network_setup_interactive.py +0 -0
  182. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_node_info_view.py +0 -0
  183. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_notifications_fallback.py +0 -0
  184. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_notify_command.py +0 -0
  185. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_ocpp_session_lock.py +0 -0
  186. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_odoo_profile.py +0 -0
  187. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_odoo_profile_admin.py +0 -0
  188. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_odoo_quote_report.py +0 -0
  189. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_offline.py +0 -0
  190. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_package_admin_next_release.py +0 -0
  191. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_power_admin_group.py +0 -0
  192. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_profile_inline_deletion.py +0 -0
  193. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_pypi_check.py +0 -0
  194. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_pypi_token.py +0 -0
  195. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_readme_editor.py +0 -0
  196. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_readme_language.py +0 -0
  197. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_reference_qr_code.py +0 -0
  198. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_reference_transaction_uuid.py +0 -0
  199. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_register_site_apps_command.py +0 -0
  200. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_release_build.py +0 -0
  201. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_release_build_flow.py +0 -0
  202. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_release_checklist.py +0 -0
  203. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_release_logs.py +0 -0
  204. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_release_manager_admin.py +0 -0
  205. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_release_packages.py +0 -0
  206. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_release_progress.py +0 -0
  207. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_release_progress_pre_release_integration.py +0 -0
  208. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_release_push.py +0 -0
  209. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_release_tasks.py +0 -0
  210. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_render_nginx_sites.py +0 -0
  211. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_request_invite.py +0 -0
  212. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_rfid_admin_print_labels.py +0 -0
  213. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_rfid_admin_reference_clear.py +0 -0
  214. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_rfid_admin_scan_csrf.py +0 -0
  215. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_rfid_always_on.py +0 -0
  216. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_rfid_backend.py +0 -0
  217. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_rfid_background_reader.py +0 -0
  218. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_rfid_client_report.py +0 -0
  219. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_rfid_watch_command.py +0 -0
  220. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_role_marker_filtering.py +0 -0
  221. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_seed_data.py +0 -0
  222. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_send_invite_command.py +0 -0
  223. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_settings_helpers.py +0 -0
  224. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_settings_mcp_port.py +0 -0
  225. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_show_leads_command.py +0 -0
  226. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_sigil_builder.py +0 -0
  227. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_sigil_resolution.py +0 -0
  228. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_sites_utils.py +0 -0
  229. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_social_profile.py +0 -0
  230. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_staff_login_net_message.py +0 -0
  231. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_staff_required_decorator.py +0 -0
  232. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_suite_gateway.py +0 -0
  233. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_switch_role_script.py +0 -0
  234. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_system_changelog_report.py +0 -0
  235. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_temp_passwords.py +0 -0
  236. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_totp_admin.py +0 -0
  237. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_totp_backend.py +0 -0
  238. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_uninstall_script.py +0 -0
  239. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_update_fixtures_command.py +0 -0
  240. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_upgrade_report.py +0 -0
  241. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_urls_autodiscover.py +0 -0
  242. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_user_data_admin.py +0 -0
  243. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_version_file.py +0 -0
  244. {arthexis-0.1.21 → arthexis-0.1.22}/tests/test_vscode_manage.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arthexis
3
- Version: 0.1.21
3
+ Version: 0.1.22
4
4
  Summary: Power & Energy Infrastructure
5
5
  Author-email: "Rafael J. Guillén-Osorio" <tecnologia@gelectriic.com>
6
6
  License-Expression: GPL-3.0-only
@@ -26,14 +26,14 @@ Requires-Dist: celery==5.5.3
26
26
  Requires-Dist: certifi==2025.7.14
27
27
  Requires-Dist: cffi==2.0.0
28
28
  Requires-Dist: channels==4.1.0
29
- Requires-Dist: charset-normalizer==3.4.2
29
+ Requires-Dist: charset-normalizer==3.4.4
30
30
  Requires-Dist: click==8.2.1
31
31
  Requires-Dist: click-didyoumean==0.3.1
32
32
  Requires-Dist: click-plugins==1.1.1.2
33
33
  Requires-Dist: click-repl==0.3.0
34
34
  Requires-Dist: colorama==0.4.6
35
35
  Requires-Dist: constantly==23.10.4
36
- Requires-Dist: cron-descriptor==1.4.5
36
+ Requires-Dist: cron-descriptor==2.0.6
37
37
  Requires-Dist: cryptography==45.0.5
38
38
  Requires-Dist: daphne==4.2.1
39
39
  Requires-Dist: diff-match-patch==20241021
@@ -56,15 +56,15 @@ Requires-Dist: hyperlink==21.0.0
56
56
  Requires-Dist: idna==3.11
57
57
  Requires-Dist: incremental==24.7.2
58
58
  Requires-Dist: kombu==5.5.4
59
- Requires-Dist: libipld==3.1.1
60
- Requires-Dist: Markdown==3.8.2
59
+ Requires-Dist: libipld==3.2.0
60
+ Requires-Dist: Markdown==3.9
61
61
  Requires-Dist: mdx_truly_sane_lists==1.3
62
62
  Requires-Dist: mfrc522==0.0.7; sys_platform == "linux"
63
63
  Requires-Dist: outcome==1.3.0.post0
64
64
  Requires-Dist: packaging==25.0
65
65
  Requires-Dist: pillow==11.3.0
66
66
  Requires-Dist: prompt_toolkit==3.0.51
67
- Requires-Dist: psutil==7.1.1
67
+ Requires-Dist: psutil==7.1.2
68
68
  Requires-Dist: psycopg==3.2.9
69
69
  Requires-Dist: psycopg-binary==3.2.12
70
70
  Requires-Dist: pyasn1==0.6.1
@@ -79,7 +79,7 @@ Requires-Dist: python-crontab==3.3.0
79
79
  Requires-Dist: python-dateutil==2.9.0.post0
80
80
  Requires-Dist: python-dotenv==1.1.1
81
81
  Requires-Dist: qrcode==8.2
82
- Requires-Dist: redis==5.0.8
82
+ Requires-Dist: redis==7.0.1
83
83
  Requires-Dist: reportlab==4.2.2
84
84
  Requires-Dist: requests==2.32.5
85
85
  Requires-Dist: selenium==4.34.2
@@ -103,7 +103,7 @@ Requires-Dist: typing_extensions==4.14.1
103
103
  Requires-Dist: tzdata==2025.2
104
104
  Requires-Dist: urllib3==2.5.0
105
105
  Requires-Dist: vine==5.1.0
106
- Requires-Dist: wcwidth==0.2.13
106
+ Requires-Dist: wcwidth==0.2.14
107
107
  Requires-Dist: webencodings==0.5.1
108
108
  Requires-Dist: websocket-client==1.8.0
109
109
  Requires-Dist: websockets==13.1
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arthexis
3
- Version: 0.1.21
3
+ Version: 0.1.22
4
4
  Summary: Power & Energy Infrastructure
5
5
  Author-email: "Rafael J. Guillén-Osorio" <tecnologia@gelectriic.com>
6
6
  License-Expression: GPL-3.0-only
@@ -26,14 +26,14 @@ Requires-Dist: celery==5.5.3
26
26
  Requires-Dist: certifi==2025.7.14
27
27
  Requires-Dist: cffi==2.0.0
28
28
  Requires-Dist: channels==4.1.0
29
- Requires-Dist: charset-normalizer==3.4.2
29
+ Requires-Dist: charset-normalizer==3.4.4
30
30
  Requires-Dist: click==8.2.1
31
31
  Requires-Dist: click-didyoumean==0.3.1
32
32
  Requires-Dist: click-plugins==1.1.1.2
33
33
  Requires-Dist: click-repl==0.3.0
34
34
  Requires-Dist: colorama==0.4.6
35
35
  Requires-Dist: constantly==23.10.4
36
- Requires-Dist: cron-descriptor==1.4.5
36
+ Requires-Dist: cron-descriptor==2.0.6
37
37
  Requires-Dist: cryptography==45.0.5
38
38
  Requires-Dist: daphne==4.2.1
39
39
  Requires-Dist: diff-match-patch==20241021
@@ -56,15 +56,15 @@ Requires-Dist: hyperlink==21.0.0
56
56
  Requires-Dist: idna==3.11
57
57
  Requires-Dist: incremental==24.7.2
58
58
  Requires-Dist: kombu==5.5.4
59
- Requires-Dist: libipld==3.1.1
60
- Requires-Dist: Markdown==3.8.2
59
+ Requires-Dist: libipld==3.2.0
60
+ Requires-Dist: Markdown==3.9
61
61
  Requires-Dist: mdx_truly_sane_lists==1.3
62
62
  Requires-Dist: mfrc522==0.0.7; sys_platform == "linux"
63
63
  Requires-Dist: outcome==1.3.0.post0
64
64
  Requires-Dist: packaging==25.0
65
65
  Requires-Dist: pillow==11.3.0
66
66
  Requires-Dist: prompt_toolkit==3.0.51
67
- Requires-Dist: psutil==7.1.1
67
+ Requires-Dist: psutil==7.1.2
68
68
  Requires-Dist: psycopg==3.2.9
69
69
  Requires-Dist: psycopg-binary==3.2.12
70
70
  Requires-Dist: pyasn1==0.6.1
@@ -79,7 +79,7 @@ Requires-Dist: python-crontab==3.3.0
79
79
  Requires-Dist: python-dateutil==2.9.0.post0
80
80
  Requires-Dist: python-dotenv==1.1.1
81
81
  Requires-Dist: qrcode==8.2
82
- Requires-Dist: redis==5.0.8
82
+ Requires-Dist: redis==7.0.1
83
83
  Requires-Dist: reportlab==4.2.2
84
84
  Requires-Dist: requests==2.32.5
85
85
  Requires-Dist: selenium==4.34.2
@@ -103,7 +103,7 @@ Requires-Dist: typing_extensions==4.14.1
103
103
  Requires-Dist: tzdata==2025.2
104
104
  Requires-Dist: urllib3==2.5.0
105
105
  Requires-Dist: vine==5.1.0
106
- Requires-Dist: wcwidth==0.2.13
106
+ Requires-Dist: wcwidth==0.2.14
107
107
  Requires-Dist: webencodings==0.5.1
108
108
  Requires-Dist: websocket-client==1.8.0
109
109
  Requires-Dist: websockets==13.1
@@ -149,7 +149,6 @@ tests/test_email_transaction.py
149
149
  tests/test_env_refresh_clean.py
150
150
  tests/test_env_refresh_pip.py
151
151
  tests/test_env_refresh_unlink.py
152
- tests/test_environment_network_setup_form.py
153
152
  tests/test_experience_admin_group.py
154
153
  tests/test_fixture_presence.py
155
154
  tests/test_footer_no_references.py
@@ -185,6 +184,7 @@ tests/test_power_admin_group.py
185
184
  tests/test_profile_inline_deletion.py
186
185
  tests/test_pypi_check.py
187
186
  tests/test_pypi_token.py
187
+ tests/test_readme_assets.py
188
188
  tests/test_readme_editor.py
189
189
  tests/test_readme_language.py
190
190
  tests/test_reference_qr_code.py
@@ -13,14 +13,14 @@ celery==5.5.3
13
13
  certifi==2025.7.14
14
14
  cffi==2.0.0
15
15
  channels==4.1.0
16
- charset-normalizer==3.4.2
16
+ charset-normalizer==3.4.4
17
17
  click==8.2.1
18
18
  click-didyoumean==0.3.1
19
19
  click-plugins==1.1.1.2
20
20
  click-repl==0.3.0
21
21
  colorama==0.4.6
22
22
  constantly==23.10.4
23
- cron-descriptor==1.4.5
23
+ cron-descriptor==2.0.6
24
24
  cryptography==45.0.5
25
25
  daphne==4.2.1
26
26
  diff-match-patch==20241021
@@ -42,14 +42,14 @@ hyperlink==21.0.0
42
42
  idna==3.11
43
43
  incremental==24.7.2
44
44
  kombu==5.5.4
45
- libipld==3.1.1
46
- Markdown==3.8.2
45
+ libipld==3.2.0
46
+ Markdown==3.9
47
47
  mdx_truly_sane_lists==1.3
48
48
  outcome==1.3.0.post0
49
49
  packaging==25.0
50
50
  pillow==11.3.0
51
51
  prompt_toolkit==3.0.51
52
- psutil==7.1.1
52
+ psutil==7.1.2
53
53
  psycopg==3.2.9
54
54
  psycopg-binary==3.2.12
55
55
  pyasn1==0.6.1
@@ -64,7 +64,7 @@ python-crontab==3.3.0
64
64
  python-dateutil==2.9.0.post0
65
65
  python-dotenv==1.1.1
66
66
  qrcode==8.2
67
- redis==5.0.8
67
+ redis==7.0.1
68
68
  reportlab==4.2.2
69
69
  requests==2.32.5
70
70
  selenium==4.34.2
@@ -88,7 +88,7 @@ typing_extensions==4.14.1
88
88
  tzdata==2025.2
89
89
  urllib3==2.5.0
90
90
  vine==5.1.0
91
- wcwidth==0.2.13
91
+ wcwidth==0.2.14
92
92
  webencodings==0.5.1
93
93
  websocket-client==1.8.0
94
94
  websockets==13.1
@@ -662,4 +662,8 @@ CELERY_BEAT_SCHEDULE = {
662
662
  "task": "core.tasks.heartbeat",
663
663
  "schedule": crontab(minute="*/5"),
664
664
  },
665
+ "ocpp_configuration_check": {
666
+ "task": "ocpp.tasks.schedule_daily_charge_point_configuration_checks",
667
+ "schedule": crontab(minute=0, hour=0),
668
+ },
665
669
  }
@@ -134,6 +134,11 @@ urlpatterns = [
134
134
  core_views.todo_done,
135
135
  name="todo-done",
136
136
  ),
137
+ path(
138
+ "admin/core/todos/<int:pk>/delete/",
139
+ core_views.todo_delete,
140
+ name="todo-delete",
141
+ ),
137
142
  path(
138
143
  "admin/core/todos/<int:pk>/snapshot/",
139
144
  core_views.todo_snapshot,
@@ -83,6 +83,7 @@ from .models import (
83
83
  OdooProfile,
84
84
  OpenPayProfile,
85
85
  EmailInbox,
86
+ GoogleCalendarProfile,
86
87
  SocialProfile,
87
88
  EmailCollector,
88
89
  Package,
@@ -1005,6 +1006,41 @@ class OpenPayProfileAdminForm(forms.ModelForm):
1005
1006
  )
1006
1007
 
1007
1008
 
1009
+ class GoogleCalendarProfileAdminForm(forms.ModelForm):
1010
+ """Admin form for :class:`core.models.GoogleCalendarProfile`."""
1011
+
1012
+ api_key = forms.CharField(
1013
+ widget=forms.PasswordInput(render_value=True),
1014
+ required=False,
1015
+ help_text="Leave blank to keep the current key.",
1016
+ )
1017
+
1018
+ class Meta:
1019
+ model = GoogleCalendarProfile
1020
+ fields = "__all__"
1021
+
1022
+ def __init__(self, *args, **kwargs):
1023
+ super().__init__(*args, **kwargs)
1024
+ if self.instance.pk:
1025
+ self.fields["api_key"].initial = ""
1026
+ self.initial["api_key"] = ""
1027
+ else:
1028
+ self.fields["api_key"].required = True
1029
+
1030
+ def clean_api_key(self):
1031
+ key = self.cleaned_data.get("api_key")
1032
+ if not key and self.instance.pk:
1033
+ return keep_existing("api_key")
1034
+ return key
1035
+
1036
+ def _post_clean(self):
1037
+ super()._post_clean()
1038
+ _restore_sigil_values(
1039
+ self,
1040
+ ["calendar_id", "api_key", "display_name", "timezone"],
1041
+ )
1042
+
1043
+
1008
1044
  class MaskedPasswordFormMixin:
1009
1045
  """Mixin that hides stored passwords while allowing updates."""
1010
1046
 
@@ -1222,6 +1258,15 @@ class OpenPayProfileInlineForm(ProfileFormMixin, OpenPayProfileAdminForm):
1222
1258
  return cleaned
1223
1259
 
1224
1260
 
1261
+ class GoogleCalendarProfileInlineForm(
1262
+ ProfileFormMixin, GoogleCalendarProfileAdminForm
1263
+ ):
1264
+ profile_fields = GoogleCalendarProfile.profile_fields
1265
+
1266
+ class Meta(GoogleCalendarProfileAdminForm.Meta):
1267
+ exclude = ("user", "group")
1268
+
1269
+
1225
1270
  class EmailInboxInlineForm(ProfileFormMixin, EmailInboxAdminForm):
1226
1271
  profile_fields = EmailInbox.profile_fields
1227
1272
 
@@ -1346,6 +1391,16 @@ PROFILE_INLINE_CONFIG = {
1346
1391
  ),
1347
1392
  "readonly_fields": ("verified_on", "verification_reference"),
1348
1393
  },
1394
+ GoogleCalendarProfile: {
1395
+ "form": GoogleCalendarProfileInlineForm,
1396
+ "fields": (
1397
+ "display_name",
1398
+ "calendar_id",
1399
+ "api_key",
1400
+ "max_events",
1401
+ "timezone",
1402
+ ),
1403
+ },
1349
1404
  EmailInbox: {
1350
1405
  "form": EmailInboxInlineForm,
1351
1406
  "fields": (
@@ -1817,6 +1872,44 @@ class OpenPayProfileAdmin(ProfileAdminMixin, SaveBeforeChangeAction, EntityModel
1817
1872
  verify_credentials_action.short_description = _("Test credentials")
1818
1873
 
1819
1874
 
1875
+ class GoogleCalendarProfileAdmin(
1876
+ ProfileAdminMixin, SaveBeforeChangeAction, EntityModelAdmin
1877
+ ):
1878
+ form = GoogleCalendarProfileAdminForm
1879
+ list_display = ("owner", "calendar_identifier", "max_events")
1880
+ search_fields = (
1881
+ "display_name",
1882
+ "calendar_id",
1883
+ "user__username",
1884
+ "group__name",
1885
+ )
1886
+ changelist_actions = ["my_profile"]
1887
+ change_actions = ["my_profile_action"]
1888
+ fieldsets = (
1889
+ (_("Owner"), {"fields": ("user", "group")}),
1890
+ (
1891
+ _("Calendar"),
1892
+ {
1893
+ "fields": (
1894
+ "display_name",
1895
+ "calendar_id",
1896
+ "api_key",
1897
+ "max_events",
1898
+ "timezone",
1899
+ )
1900
+ },
1901
+ ),
1902
+ )
1903
+
1904
+ @admin.display(description=_("Owner"))
1905
+ def owner(self, obj):
1906
+ return obj.owner_display()
1907
+
1908
+ @admin.display(description=_("Calendar"))
1909
+ def calendar_identifier(self, obj):
1910
+ display = obj.get_display_name()
1911
+ return display or obj.resolved_calendar_id()
1912
+
1820
1913
  class EmailSearchForm(forms.Form):
1821
1914
  subject = forms.CharField(
1822
1915
  required=False, widget=forms.TextInput(attrs={"style": "width: 40em;"})
@@ -2416,8 +2509,30 @@ class ProductAdmin(EntityModelAdmin):
2416
2509
  ],
2417
2510
  limit=0,
2418
2511
  )
2419
- except Exception:
2512
+ except Exception as exc:
2513
+ logger.exception(
2514
+ "Failed to fetch Odoo products for user %s (profile_id=%s, host=%s, database=%s)",
2515
+ getattr(getattr(request, "user", None), "pk", None),
2516
+ getattr(profile, "pk", None),
2517
+ getattr(profile, "host", None),
2518
+ getattr(profile, "database", None),
2519
+ )
2420
2520
  context["error"] = _("Unable to fetch products from Odoo.")
2521
+ if getattr(request.user, "is_superuser", False):
2522
+ fault = getattr(exc, "faultString", "")
2523
+ message = str(exc)
2524
+ details = [
2525
+ f"Host: {getattr(profile, 'host', '')}",
2526
+ f"Database: {getattr(profile, 'database', '')}",
2527
+ f"User ID: {getattr(profile, 'odoo_uid', '')}",
2528
+ ]
2529
+ if fault and fault != message:
2530
+ details.append(f"Fault: {fault}")
2531
+ if message:
2532
+ details.append(f"Exception: {type(exc).__name__}: {message}")
2533
+ else:
2534
+ details.append(f"Exception type: {type(exc).__name__}")
2535
+ context["debug_error"] = "\n".join(details)
2421
2536
  return context, []
2422
2537
 
2423
2538
  context["has_credentials"] = True
@@ -2697,7 +2812,7 @@ class RFIDAdmin(EntityModelAdmin, ImportExportModelAdmin):
2697
2812
  "user_data_flag",
2698
2813
  "color",
2699
2814
  "kind",
2700
- "endianness",
2815
+ "endianness_short",
2701
2816
  "released",
2702
2817
  "allowed",
2703
2818
  "last_seen_on",
@@ -2762,6 +2877,14 @@ class RFIDAdmin(EntityModelAdmin, ImportExportModelAdmin):
2762
2877
  def user_data_flag(self, obj):
2763
2878
  return getattr(obj, "is_user_data", False)
2764
2879
 
2880
+ @admin.display(description=_("End"), ordering="endianness")
2881
+ def endianness_short(self, obj):
2882
+ labels = {
2883
+ RFID.BIG_ENDIAN: _("Big"),
2884
+ RFID.LITTLE_ENDIAN: _("Little"),
2885
+ }
2886
+ return labels.get(obj.endianness, obj.get_endianness_display())
2887
+
2765
2888
  def scan_rfids(self, request, queryset):
2766
2889
  return redirect("admin:core_rfid_scan")
2767
2890
 
@@ -3715,9 +3838,9 @@ class PackageReleaseAdmin(SaveBeforeChangeAction, EntityModelAdmin):
3715
3838
  self.message_user(request, str(exc), messages.ERROR)
3716
3839
  return
3717
3840
  releases = resp.json().get("releases", {})
3718
- created = 0
3719
3841
  updated = 0
3720
3842
  restored = 0
3843
+ missing: list[str] = []
3721
3844
 
3722
3845
  for version, files in releases.items():
3723
3846
  release_on = self._release_on_from_files(files)
@@ -3742,23 +3865,11 @@ class PackageReleaseAdmin(SaveBeforeChangeAction, EntityModelAdmin):
3742
3865
  if update_fields:
3743
3866
  release.save(update_fields=update_fields)
3744
3867
  continue
3745
- PackageRelease.objects.create(
3746
- package=package,
3747
- release_manager=package.release_manager,
3748
- version=version,
3749
- revision="",
3750
- pypi_url=f"https://pypi.org/project/{package.name}/{version}/",
3751
- release_on=release_on,
3752
- )
3753
- created += 1
3868
+ missing.append(version)
3754
3869
 
3755
- if created or updated or restored:
3870
+ if updated or restored:
3756
3871
  PackageRelease.dump_fixture()
3757
3872
  message_parts = []
3758
- if created:
3759
- message_parts.append(
3760
- f"Created {created} release{'s' if created != 1 else ''} from PyPI"
3761
- )
3762
3873
  if updated:
3763
3874
  message_parts.append(
3764
3875
  f"Updated release date for {updated} release"
@@ -3769,8 +3880,17 @@ class PackageReleaseAdmin(SaveBeforeChangeAction, EntityModelAdmin):
3769
3880
  f"Restored {restored} release{'s' if restored != 1 else ''}"
3770
3881
  )
3771
3882
  self.message_user(request, "; ".join(message_parts), messages.SUCCESS)
3772
- else:
3773
- self.message_user(request, "No new releases found", messages.INFO)
3883
+ elif not missing:
3884
+ self.message_user(request, "No matching releases found", messages.INFO)
3885
+
3886
+ if missing:
3887
+ versions = ", ".join(sorted(missing))
3888
+ count = len(missing)
3889
+ message = (
3890
+ "Manual creation required for "
3891
+ f"{count} release{'s' if count != 1 else ''}: {versions}"
3892
+ )
3893
+ self.message_user(request, message, messages.WARNING)
3774
3894
 
3775
3895
  refresh_from_pypi.label = "Refresh from PyPI"
3776
3896
  refresh_from_pypi.short_description = "Refresh from PyPI"
@@ -0,0 +1,60 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ from django.conf import settings
5
+ from django.contrib import admin
6
+ from django.template.response import TemplateResponse
7
+ from django.urls import path
8
+ from django.utils.translation import gettext_lazy as _
9
+
10
+
11
+ def _get_django_settings():
12
+ return sorted(
13
+ [(name, getattr(settings, name)) for name in dir(settings) if name.isupper()]
14
+ )
15
+
16
+
17
+ def _environment_view(request):
18
+ env_vars = sorted(os.environ.items())
19
+ context = admin.site.each_context(request)
20
+ context.update(
21
+ {
22
+ "title": _("Environment"),
23
+ "env_vars": env_vars,
24
+ "environment_tasks": [],
25
+ }
26
+ )
27
+ return TemplateResponse(request, "admin/environment.html", context)
28
+
29
+ def _config_view(request):
30
+ context = admin.site.each_context(request)
31
+ context.update(
32
+ {
33
+ "title": _("Django Settings"),
34
+ "django_settings": _get_django_settings(),
35
+ }
36
+ )
37
+ return TemplateResponse(request, "admin/config.html", context)
38
+
39
+
40
+ def patch_admin_environment_view() -> None:
41
+ """Register the Environment and Config admin views on the main admin site."""
42
+ original_get_urls = admin.site.get_urls
43
+
44
+ def get_urls():
45
+ urls = original_get_urls()
46
+ custom = [
47
+ path(
48
+ "environment/",
49
+ admin.site.admin_view(_environment_view),
50
+ name="environment",
51
+ ),
52
+ path(
53
+ "config/",
54
+ admin.site.admin_view(_config_view),
55
+ name="config",
56
+ ),
57
+ ]
58
+ return custom + urls
59
+
60
+ admin.site.get_urls = get_urls