django-cfg 1.3.13__py3-none-any.whl → 1.4.0__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.
- django_cfg/__init__.py +1 -1
- django_cfg/apps/accounts/admin/user_admin.py +39 -16
- django_cfg/apps/accounts/serializers/profile.py +1 -1
- django_cfg/apps/accounts/services/otp_service.py +18 -11
- django_cfg/apps/accounts/signals.py +15 -24
- django_cfg/apps/accounts/utils/notifications.py +217 -358
- django_cfg/apps/accounts/views/otp.py +2 -2
- django_cfg/apps/accounts/views/webhook.py +1 -1
- django_cfg/apps/agents/core/django_agent.py +1 -1
- django_cfg/apps/api/commands/views.py +66 -83
- django_cfg/apps/api/health/drf_views.py +269 -0
- django_cfg/apps/api/health/serializers.py +45 -0
- django_cfg/apps/api/health/urls.py +6 -1
- django_cfg/apps/knowbase/admin/actions/__init__.py +13 -0
- django_cfg/apps/knowbase/admin/actions/visibility_actions.py +56 -0
- django_cfg/apps/knowbase/admin/document_admin.py +136 -270
- django_cfg/apps/knowbase/admin/helpers/__init__.py +17 -0
- django_cfg/apps/knowbase/admin/helpers/configs.py +72 -0
- django_cfg/apps/knowbase/admin/helpers/display_helpers.py +156 -0
- django_cfg/apps/knowbase/admin/helpers/statistics.py +108 -0
- django_cfg/apps/knowbase/config/constance_fields.py +1 -1
- django_cfg/apps/knowbase/config/settings.py +2 -2
- django_cfg/apps/knowbase/mixins/__init__.py +19 -2
- django_cfg/apps/knowbase/mixins/config/__init__.py +14 -0
- django_cfg/apps/knowbase/mixins/config/defaults.py +75 -0
- django_cfg/apps/knowbase/mixins/config/meta_config.py +120 -0
- django_cfg/apps/knowbase/mixins/creator.py +10 -10
- django_cfg/apps/knowbase/mixins/external_data_mixin.py +105 -403
- django_cfg/apps/knowbase/mixins/generators/__init__.py +16 -0
- django_cfg/apps/knowbase/mixins/generators/content_generator.py +218 -0
- django_cfg/apps/knowbase/mixins/generators/field_analyzer.py +76 -0
- django_cfg/apps/knowbase/mixins/generators/metadata_generator.py +124 -0
- django_cfg/apps/knowbase/mixins/service.py +2 -2
- django_cfg/apps/knowbase/services/archive/__init__.py +1 -0
- django_cfg/apps/knowbase/services/archive/analyzers/__init__.py +17 -0
- django_cfg/apps/knowbase/services/archive/analyzers/complexity_analyzer.py +33 -0
- django_cfg/apps/knowbase/services/archive/analyzers/purpose_detector.py +36 -0
- django_cfg/apps/knowbase/services/archive/analyzers/quality_analyzer.py +39 -0
- django_cfg/apps/knowbase/services/archive/analyzers/tag_generator.py +103 -0
- django_cfg/apps/knowbase/services/archive/chunking/__init__.py +19 -0
- django_cfg/apps/knowbase/services/archive/chunking/base.py +81 -0
- django_cfg/apps/knowbase/services/archive/chunking/json_chunker.py +62 -0
- django_cfg/apps/knowbase/services/archive/chunking/markdown_chunker.py +107 -0
- django_cfg/apps/knowbase/services/archive/chunking/python_chunker.py +248 -0
- django_cfg/apps/knowbase/services/archive/chunking/text_chunker.py +70 -0
- django_cfg/apps/knowbase/services/archive/chunking_service.py +110 -729
- django_cfg/apps/knowbase/services/archive/context/__init__.py +14 -0
- django_cfg/apps/knowbase/services/archive/context/builders.py +220 -0
- django_cfg/apps/knowbase/services/archive/context/models.py +38 -0
- django_cfg/apps/knowbase/services/embedding/models.py +18 -14
- django_cfg/apps/knowbase/services/embedding/processors.py +6 -3
- django_cfg/apps/knowbase/tasks/document_processing.py +11 -3
- django_cfg/apps/leads/tests.py +1 -1
- django_cfg/apps/payments/admin/api_keys_admin.py +1 -1
- django_cfg/apps/payments/admin/balance_admin.py +1 -1
- django_cfg/apps/payments/admin/currencies_admin.py +1 -1
- django_cfg/apps/payments/admin/payments_admin.py +1 -1
- django_cfg/apps/payments/admin/subscriptions_admin.py +1 -1
- django_cfg/apps/payments/admin_interface/templates/payments/base.html +59 -126
- django_cfg/apps/payments/admin_interface/views/api/payments.py +1 -1
- django_cfg/apps/payments/admin_interface/views/api/stats.py +1 -1
- django_cfg/apps/payments/admin_interface/views/api/users.py +1 -1
- django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +1 -1
- django_cfg/apps/payments/admin_interface/views/api/webhook_public.py +1 -1
- django_cfg/apps/payments/admin_interface/views/base.py +29 -2
- django_cfg/apps/payments/apps.py +1 -1
- django_cfg/apps/payments/config/django_cfg_integration.py +2 -2
- django_cfg/apps/payments/config/helpers.py +3 -2
- django_cfg/apps/payments/management/commands/cleanup_expired_data.py +1 -1
- django_cfg/apps/payments/management/commands/currency_stats.py +1 -1
- django_cfg/apps/payments/management/commands/manage_currencies.py +1 -1
- django_cfg/apps/payments/management/commands/manage_providers.py +1 -1
- django_cfg/apps/payments/management/commands/process_pending_payments.py +1 -1
- django_cfg/apps/payments/management/commands/test_providers.py +1 -1
- django_cfg/apps/payments/middleware/api_access.py +1 -1
- django_cfg/apps/payments/middleware/rate_limiting.py +1 -1
- django_cfg/apps/payments/middleware/usage_tracking.py +1 -1
- django_cfg/apps/payments/models/balance.py +2 -2
- django_cfg/apps/payments/models/managers/api_key_managers.py +1 -1
- django_cfg/apps/payments/models/managers/balance_managers.py +1 -1
- django_cfg/apps/payments/models/managers/currency_managers.py +1 -1
- django_cfg/apps/payments/models/managers/payment_managers.py +1 -1
- django_cfg/apps/payments/models/managers/subscription_managers.py +1 -1
- django_cfg/apps/payments/models/payments.py +2 -2
- django_cfg/apps/payments/services/cache_service/__init__.py +1 -1
- django_cfg/apps/payments/services/cache_service/simple_cache.py +10 -5
- django_cfg/apps/payments/services/core/base.py +1 -1
- django_cfg/apps/payments/services/core/currency/__init__.py +13 -0
- django_cfg/apps/payments/services/core/currency/currency_converter.py +57 -0
- django_cfg/apps/payments/services/core/currency/currency_validator.py +61 -0
- django_cfg/apps/payments/services/core/operations/__init__.py +15 -0
- django_cfg/apps/payments/services/core/operations/payment_canceller.py +100 -0
- django_cfg/apps/payments/services/core/operations/payment_creator.py +196 -0
- django_cfg/apps/payments/services/core/operations/status_checker.py +100 -0
- django_cfg/apps/payments/services/core/payment_service.py +124 -612
- django_cfg/apps/payments/services/core/providers/__init__.py +13 -0
- django_cfg/apps/payments/services/core/providers/provider_client.py +132 -0
- django_cfg/apps/payments/services/core/providers/status_mapper.py +89 -0
- django_cfg/apps/payments/services/core/utils/__init__.py +13 -0
- django_cfg/apps/payments/services/core/utils/data_converter.py +48 -0
- django_cfg/apps/payments/services/core/utils/statistics_calculator.py +69 -0
- django_cfg/apps/payments/services/providers/base.py +1 -1
- django_cfg/apps/payments/services/providers/nowpayments/__init__.py +3 -3
- django_cfg/apps/payments/services/providers/nowpayments/parsers/__init__.py +9 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/__init__.py +23 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/constants.py +23 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/currency_names.py +244 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/patterns.py +511 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/parser.py +168 -0
- django_cfg/apps/payments/services/providers/nowpayments/provider.py +1 -1
- django_cfg/apps/payments/services/providers/nowpayments/sync.py +1 -1
- django_cfg/apps/payments/services/providers/registry.py +1 -1
- django_cfg/apps/payments/services/providers/sync_service.py +1 -1
- django_cfg/apps/payments/signals/__init__.py +1 -1
- django_cfg/apps/payments/signals/api_key_signals.py +1 -1
- django_cfg/apps/payments/signals/balance_signals.py +1 -1
- django_cfg/apps/payments/signals/payment_signals.py +1 -1
- django_cfg/apps/payments/signals/subscription_signals.py +1 -1
- django_cfg/apps/payments/views/api/api_keys.py +1 -1
- django_cfg/apps/payments/views/api/balances.py +1 -1
- django_cfg/apps/payments/views/api/base.py +1 -1
- django_cfg/apps/payments/views/api/currencies.py +1 -1
- django_cfg/apps/payments/views/api/payments.py +1 -1
- django_cfg/apps/payments/views/api/subscriptions.py +1 -1
- django_cfg/apps/payments/views/api/webhooks.py +1 -1
- django_cfg/apps/payments/views/serializers/api_keys.py +1 -1
- django_cfg/apps/payments/views/serializers/balances.py +1 -1
- django_cfg/apps/payments/views/serializers/currencies.py +1 -1
- django_cfg/apps/payments/views/serializers/payments.py +1 -1
- django_cfg/apps/payments/views/serializers/subscriptions.py +1 -1
- django_cfg/apps/payments/views/serializers/webhooks.py +1 -1
- django_cfg/apps/support/admin/support_admin.py +21 -13
- django_cfg/apps/support/templates/support/chat/access_denied.html +21 -27
- django_cfg/apps/support/templates/support/chat/ticket_chat.html +183 -254
- django_cfg/apps/support/utils/support_email_service.py +1 -1
- django_cfg/apps/tasks/templates/tasks/layout/base.html +20 -115
- django_cfg/apps/tasks/utils/simulator.py +1 -1
- django_cfg/apps/tasks/views/dashboard.py +33 -3
- django_cfg/apps/urls.py +5 -1
- django_cfg/cli/README.md +57 -471
- django_cfg/cli/commands/create_project.py +140 -529
- django_cfg/cli/main.py +13 -10
- django_cfg/core/__init__.py +63 -6
- django_cfg/core/base/__init__.py +5 -0
- django_cfg/core/base/config_model.py +652 -0
- django_cfg/core/builders/__init__.py +11 -0
- django_cfg/core/builders/apps_builder.py +258 -0
- django_cfg/core/builders/middleware_builder.py +115 -0
- django_cfg/core/builders/security_builder.py +96 -0
- django_cfg/core/config.py +20 -892
- django_cfg/core/constants.py +69 -0
- django_cfg/core/environment/__init__.py +9 -0
- django_cfg/core/exceptions.py +45 -298
- django_cfg/core/generation/__init__.py +51 -0
- django_cfg/core/generation/core_generators/__init__.py +0 -0
- django_cfg/core/generation/core_generators/settings.py +90 -0
- django_cfg/core/generation/core_generators/static.py +82 -0
- django_cfg/core/generation/core_generators/templates.py +141 -0
- django_cfg/core/generation/data_generators/__init__.py +15 -0
- django_cfg/core/generation/data_generators/cache.py +132 -0
- django_cfg/core/generation/data_generators/database.py +117 -0
- django_cfg/core/generation/generation.py +92 -0
- django_cfg/core/generation/integration_generators/__init__.py +21 -0
- django_cfg/core/generation/integration_generators/api.py +237 -0
- django_cfg/core/generation/integration_generators/sessions.py +65 -0
- django_cfg/core/generation/integration_generators/tailwind.py +54 -0
- django_cfg/core/generation/integration_generators/tasks.py +92 -0
- django_cfg/core/generation/integration_generators/third_party.py +144 -0
- django_cfg/core/generation/orchestrator.py +285 -0
- django_cfg/core/generation/protocols.py +30 -0
- django_cfg/core/generation/security_generators/__init__.py +0 -0
- django_cfg/core/generation/utility_generators/__init__.py +24 -0
- django_cfg/core/generation/utility_generators/email.py +58 -0
- django_cfg/core/generation/utility_generators/i18n.py +66 -0
- django_cfg/core/generation/utility_generators/limits.py +58 -0
- django_cfg/core/generation/utility_generators/logging.py +66 -0
- django_cfg/core/generation/utility_generators/security.py +101 -0
- django_cfg/core/generation/utils/__init__.py +0 -0
- django_cfg/core/generation/utils/helpers.py +32 -0
- django_cfg/core/integration/__init__.py +18 -25
- django_cfg/core/integration/display/startup.py +146 -133
- django_cfg/core/integration/url_integration.py +13 -2
- django_cfg/core/services/__init__.py +5 -0
- django_cfg/core/services/config_service.py +121 -0
- django_cfg/core/state/__init__.py +9 -0
- django_cfg/core/state/registry.py +84 -0
- django_cfg/core/types/__init__.py +15 -0
- django_cfg/core/types/aliases.py +15 -0
- django_cfg/core/types/enums.py +49 -0
- django_cfg/dashboard/DEBUG_README.md +105 -0
- django_cfg/dashboard/REFACTORING_SUMMARY.md +237 -0
- django_cfg/dashboard/__init__.py +24 -0
- django_cfg/dashboard/components.py +308 -0
- django_cfg/dashboard/debug.py +176 -0
- django_cfg/dashboard/management/__init__.py +0 -0
- django_cfg/dashboard/management/commands/__init__.py +0 -0
- django_cfg/dashboard/management/commands/debug_dashboard.py +109 -0
- django_cfg/dashboard/sections/__init__.py +1 -0
- django_cfg/dashboard/sections/base.py +128 -0
- django_cfg/dashboard/sections/commands.py +32 -0
- django_cfg/dashboard/sections/overview.py +394 -0
- django_cfg/dashboard/sections/stats.py +48 -0
- django_cfg/dashboard/sections/system.py +73 -0
- django_cfg/management/commands/check_settings.py +6 -2
- django_cfg/management/commands/clear_constance.py +6 -1
- django_cfg/management/commands/create_token.py +5 -4
- django_cfg/management/commands/generate.py +5 -0
- django_cfg/management/commands/list_urls.py +7 -2
- django_cfg/management/commands/migrate_all.py +6 -2
- django_cfg/management/commands/migrator.py +6 -1
- django_cfg/management/commands/rundramatiq.py +6 -1
- django_cfg/management/commands/rundramatiq_simulator.py +11 -4
- django_cfg/management/commands/runserver_ngrok.py +9 -7
- django_cfg/management/commands/script.py +25 -21
- django_cfg/management/commands/show_config.py +6 -1
- django_cfg/management/commands/show_urls.py +8 -3
- django_cfg/management/commands/superuser.py +5 -4
- django_cfg/management/commands/task_clear.py +8 -3
- django_cfg/management/commands/task_status.py +8 -3
- django_cfg/management/commands/test_email.py +6 -1
- django_cfg/management/commands/test_telegram.py +6 -1
- django_cfg/management/commands/test_twilio.py +6 -1
- django_cfg/management/commands/tree.py +7 -4
- django_cfg/models/__init__.py +88 -3
- django_cfg/models/api/__init__.py +27 -0
- django_cfg/models/{api.py → api/config.py} +1 -1
- django_cfg/models/api/drf/__init__.py +21 -0
- django_cfg/models/api/drf/config.py +101 -0
- django_cfg/models/api/drf/redoc.py +31 -0
- django_cfg/models/api/drf/spectacular.py +129 -0
- django_cfg/models/api/drf/swagger.py +59 -0
- django_cfg/models/{api_keys.py → api/keys.py} +16 -6
- django_cfg/models/{limits.py → api/limits.py} +0 -1
- django_cfg/models/base/__init__.py +14 -0
- django_cfg/models/django/__init__.py +16 -0
- django_cfg/models/{constance.py → django/constance.py} +1 -1
- django_cfg/models/{environment.py → django/environment.py} +1 -1
- django_cfg/models/infrastructure/__init__.py +17 -0
- django_cfg/models/{cache.py → infrastructure/cache.py} +3 -2
- django_cfg/models/infrastructure/database/__init__.py +22 -0
- django_cfg/models/infrastructure/database/config.py +265 -0
- django_cfg/models/infrastructure/database/converters.py +91 -0
- django_cfg/models/infrastructure/database/parsers.py +96 -0
- django_cfg/models/infrastructure/database/routing.py +85 -0
- django_cfg/models/infrastructure/database/validators.py +170 -0
- django_cfg/models/{logging.py → infrastructure/logging.py} +1 -1
- django_cfg/models/{security.py → infrastructure/security.py} +2 -2
- django_cfg/models/ngrok/__init__.py +11 -0
- django_cfg/models/ngrok/auth.py +37 -0
- django_cfg/models/ngrok/config.py +77 -0
- django_cfg/models/ngrok/tunnel.py +35 -0
- django_cfg/models/payments/__init__.py +20 -0
- django_cfg/models/payments/api_keys.py +57 -0
- django_cfg/models/{payments.py → payments/config.py} +56 -154
- django_cfg/models/payments/providers/__init__.py +15 -0
- django_cfg/models/payments/providers/base.py +25 -0
- django_cfg/models/payments/providers/nowpayments.py +48 -0
- django_cfg/models/services/__init__.py +18 -0
- django_cfg/models/services/base.py +65 -0
- django_cfg/models/{email.py → services/email.py} +1 -1
- django_cfg/models/services/telegram.py +172 -0
- django_cfg/models/tasks/__init__.py +51 -0
- django_cfg/models/tasks/backends.py +250 -0
- django_cfg/models/tasks/config.py +314 -0
- django_cfg/models/tasks/utils.py +174 -0
- django_cfg/modules/base.py +18 -3
- django_cfg/modules/django_admin/decorators/actions.py +1 -1
- django_cfg/modules/django_admin/decorators/display.py +1 -1
- django_cfg/modules/django_admin/mixins/standalone_actions_mixin.py +1 -1
- django_cfg/modules/django_cfg_rpc_client/README.md +346 -0
- django_cfg/modules/django_cfg_rpc_client/__init__.py +51 -0
- django_cfg/modules/django_cfg_rpc_client/client.py +540 -0
- django_cfg/modules/django_cfg_rpc_client/config.py +207 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/README.md +517 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/UNFOLD_INTEGRATION.md +439 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/__init__.py +11 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/apps.py +22 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/monitor.py +435 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/static/django_cfg_rpc_dashboard/js/dashboard.js +373 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/templates/django_cfg_rpc_dashboard/base.html +76 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/templates/django_cfg_rpc_dashboard/dashboard.html +200 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/urls.py +22 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/urls_admin.py +9 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/views.py +251 -0
- django_cfg/modules/django_cfg_rpc_client/exceptions.py +201 -0
- django_cfg/modules/django_drf_theme/CHANGELOG.md +210 -0
- django_cfg/modules/django_drf_theme/EXAMPLE.md +465 -0
- django_cfg/modules/django_drf_theme/IMPLEMENTATION.md +232 -0
- django_cfg/modules/django_drf_theme/README.md +207 -0
- django_cfg/modules/django_drf_theme/TAILWIND_CDN_GUIDE.md +274 -0
- django_cfg/modules/django_drf_theme/__init__.py +23 -0
- django_cfg/modules/django_drf_theme/apps.py +15 -0
- django_cfg/modules/django_drf_theme/renderers.py +58 -0
- django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/api.html +375 -0
- django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/base.html +938 -0
- django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/forms/filter_form.html +132 -0
- django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/forms/raw_data_form.html +123 -0
- django_cfg/modules/django_drf_theme/templatetags/__init__.py +1 -0
- django_cfg/modules/django_drf_theme/templatetags/tailwind_tags.py +57 -0
- django_cfg/modules/django_email/__init__.py +14 -0
- django_cfg/modules/{django_email.py → django_email/service.py} +78 -113
- django_cfg/modules/django_email/utils.py +40 -0
- django_cfg/modules/django_health/__init__.py +9 -0
- django_cfg/modules/{django_health.py → django_health/service.py} +23 -21
- django_cfg/modules/django_llm/llm/client.py +155 -550
- django_cfg/modules/django_llm/llm/embeddings/__init__.py +13 -0
- django_cfg/modules/django_llm/llm/embeddings/mock_embedder.py +106 -0
- django_cfg/modules/django_llm/llm/embeddings/openai_embedder.py +79 -0
- django_cfg/modules/django_llm/llm/models_api/__init__.py +9 -0
- django_cfg/modules/django_llm/llm/models_api/models_query.py +163 -0
- django_cfg/modules/django_llm/llm/providers/__init__.py +15 -0
- django_cfg/modules/django_llm/llm/providers/config_builder.py +103 -0
- django_cfg/modules/django_llm/llm/providers/provider_manager.py +148 -0
- django_cfg/modules/django_llm/llm/providers/provider_selector.py +60 -0
- django_cfg/modules/django_llm/llm/requests/__init__.py +15 -0
- django_cfg/modules/django_llm/llm/requests/cache_manager.py +170 -0
- django_cfg/modules/django_llm/llm/requests/chat_handler.py +199 -0
- django_cfg/modules/django_llm/llm/requests/embedding_handler.py +113 -0
- django_cfg/modules/django_llm/llm/responses/__init__.py +9 -0
- django_cfg/modules/django_llm/llm/responses/response_builder.py +131 -0
- django_cfg/modules/django_llm/llm/stats/__init__.py +9 -0
- django_cfg/modules/django_llm/llm/stats/stats_manager.py +107 -0
- django_cfg/modules/django_llm/translator/detectors/__init__.py +13 -0
- django_cfg/modules/django_llm/translator/detectors/language_detector.py +90 -0
- django_cfg/modules/django_llm/translator/detectors/script_detector.py +153 -0
- django_cfg/modules/django_llm/translator/stats/__init__.py +11 -0
- django_cfg/modules/django_llm/translator/stats/stats_tracker.py +85 -0
- django_cfg/modules/django_llm/translator/translator.py +150 -603
- django_cfg/modules/django_llm/translator/translators/__init__.py +15 -0
- django_cfg/modules/django_llm/translator/translators/json_translator.py +316 -0
- django_cfg/modules/django_llm/translator/translators/text_translator.py +139 -0
- django_cfg/modules/django_llm/translator/utils/__init__.py +13 -0
- django_cfg/modules/django_llm/translator/utils/prompt_builder.py +110 -0
- django_cfg/modules/django_llm/translator/utils/text_utils.py +114 -0
- django_cfg/modules/django_logging/FIXES_SUMMARY.md +276 -0
- django_cfg/modules/django_logging/LOGGING_GUIDE.md +504 -0
- django_cfg/modules/django_logging/__init__.py +14 -0
- django_cfg/modules/{django_logger.py → django_logging/django_logger.py} +13 -13
- django_cfg/modules/{logger.py → django_logging/logger.py} +14 -4
- django_cfg/modules/django_ngrok/__init__.py +39 -0
- django_cfg/modules/{django_ngrok.py → django_ngrok/service.py} +14 -42
- django_cfg/modules/django_rpc_old/POETRY.md +344 -0
- django_cfg/modules/django_rpc_old/README.md +397 -0
- django_cfg/modules/django_rpc_old/TESTING.md +358 -0
- django_cfg/modules/django_rpc_old/__init__.py +39 -0
- django_cfg/modules/django_rpc_old/client.py +531 -0
- django_cfg/modules/django_rpc_old/config.py +279 -0
- django_cfg/modules/django_rpc_old/exceptions.py +172 -0
- django_cfg/modules/django_tailwind/README.md +478 -0
- django_cfg/modules/django_tailwind/__init__.py +7 -0
- django_cfg/modules/django_tailwind/apps.py +10 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/app.html +5 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/base.html +117 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/components/navbar.html +124 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/components/theme_toggle.html +54 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/components/user_menu.html +116 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/simple.html +46 -0
- django_cfg/modules/django_tailwind/templatetags/__init__.py +1 -0
- django_cfg/modules/django_tailwind/templatetags/tailwind_info.py +185 -0
- django_cfg/modules/django_tasks/__init__.py +29 -0
- django_cfg/modules/django_tasks/factory.py +127 -0
- django_cfg/modules/{django_tasks.py → django_tasks/service.py} +45 -274
- django_cfg/modules/django_tasks/settings.py +107 -0
- django_cfg/modules/django_telegram/__init__.py +29 -0
- django_cfg/modules/{django_telegram.py → django_telegram/service.py} +45 -113
- django_cfg/modules/django_telegram/utils.py +62 -0
- django_cfg/modules/django_twilio/__init__.py +54 -107
- django_cfg/modules/django_twilio/_imports.py +30 -0
- django_cfg/modules/django_twilio/base.py +192 -0
- django_cfg/modules/django_twilio/email_otp.py +227 -0
- django_cfg/modules/django_twilio/sendgrid_service.py +1 -1
- django_cfg/modules/django_twilio/simple_service.py +1 -2
- django_cfg/modules/django_twilio/sms.py +94 -0
- django_cfg/modules/django_twilio/twilio_service.py +2 -3
- django_cfg/modules/django_twilio/unified.py +310 -0
- django_cfg/modules/django_twilio/utils.py +190 -0
- django_cfg/modules/django_twilio/whatsapp.py +137 -0
- django_cfg/modules/django_unfold/callbacks/base.py +198 -7
- django_cfg/modules/django_unfold/callbacks/main.py +102 -10
- django_cfg/modules/django_unfold/dashboard.py +65 -43
- django_cfg/modules/django_unfold/models/config.py +13 -12
- django_cfg/modules/django_unfold/models/navigation.py +8 -3
- django_cfg/modules/django_unfold/models/tabs.py +2 -2
- django_cfg/modules/django_unfold/templates/unfold/helpers/app_list.html +102 -0
- django_cfg/registry/core.py +24 -26
- django_cfg/registry/modules.py +5 -2
- django_cfg/registry/services.py +20 -3
- django_cfg/registry/third_party.py +8 -8
- django_cfg/static/admin/css/dashboard.css +260 -0
- django_cfg/static/admin/js/commands.js +171 -0
- django_cfg/static/admin/js/dashboard.js +126 -0
- django_cfg/templates/admin/components/management_commands.js +375 -0
- django_cfg/templates/admin/components/progress_bar.html +18 -23
- django_cfg/templates/admin/index.html +48 -20
- django_cfg/templates/admin/index_new.html +106 -0
- django_cfg/templates/admin/layouts/base_dashboard.html +60 -0
- django_cfg/templates/admin/layouts/dashboard_with_tabs.html +1 -20
- django_cfg/templates/admin/sections/commands_section.html +626 -0
- django_cfg/templates/admin/sections/overview_section.html +112 -0
- django_cfg/templates/admin/sections/stats_section.html +35 -0
- django_cfg/templates/admin/sections/system_section.html +99 -0
- django_cfg/templates/admin/snippets/components/CHARTS_GUIDE.md +322 -0
- django_cfg/templates/admin/snippets/components/activity_tracker.html +85 -47
- django_cfg/templates/admin/snippets/components/charts_section.html +154 -64
- django_cfg/templates/admin/snippets/components/django_commands.html +3 -3
- django_cfg/templates/admin/snippets/components/recent_activity_improved.html +25 -0
- django_cfg/templates/admin/snippets/components/recent_users_table.html +1 -1
- django_cfg/templates/admin/snippets/components/system_metrics.html +179 -93
- django_cfg/templates/admin/snippets/zones/zones_table.html +2 -2
- django_cfg/templatetags/django_cfg.py +7 -1
- django_cfg/utils/smart_defaults.py +4 -4
- django_cfg-1.4.0.dist-info/METADATA +920 -0
- {django_cfg-1.3.13.dist-info → django_cfg-1.4.0.dist-info}/RECORD +424 -195
- django_cfg/apps/accounts/utils/auth_email_service.py +0 -84
- django_cfg/apps/payments/services/providers/nowpayments/parsers.py +0 -879
- django_cfg/core/generation.py +0 -621
- django_cfg/management/commands/validate_config.py +0 -189
- django_cfg/models/database.py +0 -480
- django_cfg/models/drf.py +0 -272
- django_cfg/models/ngrok.py +0 -122
- django_cfg/models/services.py +0 -440
- django_cfg/models/tasks.py +0 -550
- django_cfg/modules/django_twilio/service.py +0 -942
- django_cfg/template_archive/django_sample.zip +0 -0
- django_cfg/templates/rest_framework/api.html +0 -12
- django_cfg/utils/toolkit.py +0 -703
- django_cfg-1.3.13.dist-info/METADATA +0 -1029
- /django_cfg/apps/accounts/management/commands/{test_otp.py → otp_test.py} +0 -0
- /django_cfg/core/{environment.py → environment/detector.py} +0 -0
- /django_cfg/models/{cors.py → api/cors.py} +0 -0
- /django_cfg/models/{jwt.py → api/jwt.py} +0 -0
- /django_cfg/models/{base.py → base/config.py} +0 -0
- /django_cfg/models/{cfg.py → base/module.py} +0 -0
- /django_cfg/models/{revolution.py → django/revolution.py} +0 -0
- /django_cfg/modules/{dramatiq_setup.py → django_tasks/dramatiq_setup.py} +0 -0
- {django_cfg-1.3.13.dist-info → django_cfg-1.4.0.dist-info}/WHEEL +0 -0
- {django_cfg-1.3.13.dist-info → django_cfg-1.4.0.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.3.13.dist-info → django_cfg-1.4.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,127 @@
|
|
1
|
+
"""
|
2
|
+
Task service factory and utilities.
|
3
|
+
|
4
|
+
Provides singleton instance and utility functions.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from typing import Optional, Dict, Any
|
8
|
+
import logging
|
9
|
+
|
10
|
+
logger = logging.getLogger(__name__)
|
11
|
+
|
12
|
+
# Lazy import to avoid circular dependency
|
13
|
+
_task_service_instance = None
|
14
|
+
|
15
|
+
|
16
|
+
def get_task_service():
|
17
|
+
"""Get the global task service instance."""
|
18
|
+
global _task_service_instance
|
19
|
+
|
20
|
+
if _task_service_instance is None:
|
21
|
+
from .service import DjangoTasks
|
22
|
+
_task_service_instance = DjangoTasks()
|
23
|
+
|
24
|
+
return _task_service_instance
|
25
|
+
|
26
|
+
|
27
|
+
def reset_task_service():
|
28
|
+
"""Reset the global task service instance (useful for testing)."""
|
29
|
+
global _task_service_instance
|
30
|
+
_task_service_instance = None
|
31
|
+
|
32
|
+
|
33
|
+
def is_task_system_available() -> bool:
|
34
|
+
"""Check if task system is available and properly configured."""
|
35
|
+
try:
|
36
|
+
service = get_task_service()
|
37
|
+
return service.is_enabled()
|
38
|
+
except Exception:
|
39
|
+
return False
|
40
|
+
|
41
|
+
|
42
|
+
def get_task_health() -> Dict[str, Any]:
|
43
|
+
"""Get task system health status."""
|
44
|
+
try:
|
45
|
+
service = get_task_service()
|
46
|
+
return service.get_health_status()
|
47
|
+
except Exception as e:
|
48
|
+
return {
|
49
|
+
"enabled": False,
|
50
|
+
"error": str(e),
|
51
|
+
"redis_connection": False,
|
52
|
+
"configuration_valid": False,
|
53
|
+
}
|
54
|
+
|
55
|
+
|
56
|
+
def initialize_task_system():
|
57
|
+
"""
|
58
|
+
Initialize the task system during Django app startup.
|
59
|
+
This function is called from Django AppConfig.ready() method.
|
60
|
+
"""
|
61
|
+
try:
|
62
|
+
service = get_task_service()
|
63
|
+
|
64
|
+
# Force config reload to ensure we have fresh config
|
65
|
+
service._config = None
|
66
|
+
config = service.config
|
67
|
+
|
68
|
+
if config and config.enabled:
|
69
|
+
logger.info("🔧 Initializing Django-CFG task system...")
|
70
|
+
|
71
|
+
# Set up Dramatiq broker from Django settings
|
72
|
+
try:
|
73
|
+
import dramatiq
|
74
|
+
from django.conf import settings
|
75
|
+
|
76
|
+
# Django-dramatiq automatically configures the broker from DRAMATIQ_BROKER setting
|
77
|
+
if hasattr(settings, 'DRAMATIQ_BROKER'):
|
78
|
+
# Configure broker with middleware
|
79
|
+
broker_config = settings.DRAMATIQ_BROKER
|
80
|
+
middleware_list = getattr(settings, 'DRAMATIQ_MIDDLEWARE', [])
|
81
|
+
|
82
|
+
# Import and instantiate middleware
|
83
|
+
middleware_instances = []
|
84
|
+
for middleware_path in middleware_list:
|
85
|
+
try:
|
86
|
+
module_path, class_name = middleware_path.rsplit('.', 1)
|
87
|
+
module = __import__(module_path, fromlist=[class_name])
|
88
|
+
middleware_class = getattr(module, class_name)
|
89
|
+
middleware_instances.append(middleware_class())
|
90
|
+
except Exception as e:
|
91
|
+
logger.warning(f"Failed to load middleware {middleware_path}: {e}")
|
92
|
+
|
93
|
+
# Create broker with middleware
|
94
|
+
broker_class_path = broker_config['BROKER']
|
95
|
+
module_path, class_name = broker_class_path.rsplit('.', 1)
|
96
|
+
module = __import__(module_path, fromlist=[class_name])
|
97
|
+
broker_class = getattr(module, class_name)
|
98
|
+
|
99
|
+
broker_options = broker_config.get('OPTIONS', {})
|
100
|
+
broker = broker_class(middleware=middleware_instances, **broker_options)
|
101
|
+
|
102
|
+
# Set as default broker
|
103
|
+
dramatiq.set_broker(broker)
|
104
|
+
|
105
|
+
logger.debug(f"✅ Dramatiq broker configured with {len(middleware_instances)} middleware")
|
106
|
+
else:
|
107
|
+
logger.warning("DRAMATIQ_BROKER not found in Django settings")
|
108
|
+
|
109
|
+
except Exception as e:
|
110
|
+
logger.warning(f"Failed to configure Dramatiq: {e}")
|
111
|
+
|
112
|
+
logger.info("✅ Task system initialized successfully")
|
113
|
+
logger.info("💡 To start workers, run: python manage.py rundramatiq")
|
114
|
+
else:
|
115
|
+
logger.debug(f"Task system not enabled (config: {config}), skipping initialization")
|
116
|
+
|
117
|
+
except Exception as e:
|
118
|
+
logger.error(f"Failed to initialize task system: {e}")
|
119
|
+
|
120
|
+
|
121
|
+
__all__ = [
|
122
|
+
"get_task_service",
|
123
|
+
"reset_task_service",
|
124
|
+
"is_task_system_available",
|
125
|
+
"get_task_health",
|
126
|
+
"initialize_task_system",
|
127
|
+
]
|
@@ -1,19 +1,18 @@
|
|
1
1
|
"""
|
2
|
-
Django-CFG Task Service
|
2
|
+
Django-CFG Task Service.
|
3
3
|
|
4
|
-
|
5
|
-
Provides essential functionality without unnecessary complexity.
|
4
|
+
Main DjangoTasks class for Dramatiq integration.
|
6
5
|
"""
|
7
6
|
|
8
7
|
from typing import Optional, Dict, Any, List
|
9
8
|
import logging
|
10
9
|
from urllib.parse import urlparse
|
11
10
|
|
12
|
-
from
|
11
|
+
from ..base import BaseCfgModule
|
13
12
|
from django_cfg.models.tasks import TaskConfig, validate_task_config
|
14
|
-
from django_cfg.models.constance import ConstanceField
|
13
|
+
from django_cfg.models.django.constance import ConstanceField
|
15
14
|
|
16
|
-
# Django imports
|
15
|
+
# Django imports
|
17
16
|
try:
|
18
17
|
from django.apps import apps
|
19
18
|
except ImportError:
|
@@ -36,25 +35,24 @@ logger = logging.getLogger(__name__)
|
|
36
35
|
class DjangoTasks(BaseCfgModule):
|
37
36
|
"""
|
38
37
|
Simplified Django-CFG task service.
|
39
|
-
|
38
|
+
|
40
39
|
Focuses on essential functionality:
|
41
40
|
- Configuration management
|
42
41
|
- Task discovery
|
43
42
|
- Health checks
|
44
43
|
- Constance integration
|
45
44
|
"""
|
46
|
-
|
45
|
+
|
47
46
|
def __init__(self):
|
48
47
|
super().__init__()
|
49
48
|
self._config: Optional[TaskConfig] = None
|
50
49
|
self._redis_url: Optional[str] = None
|
51
|
-
|
50
|
+
|
52
51
|
@property
|
53
52
|
def config(self) -> Optional[TaskConfig]:
|
54
53
|
"""Get task configuration (lazy-loaded)."""
|
55
54
|
if self._config is None:
|
56
55
|
try:
|
57
|
-
# Get config from django-cfg
|
58
56
|
django_config = self.get_config()
|
59
57
|
if django_config and hasattr(django_config, 'tasks'):
|
60
58
|
self._config = django_config.tasks
|
@@ -70,38 +68,36 @@ class DjangoTasks(BaseCfgModule):
|
|
70
68
|
logger.debug("Could not import api.config")
|
71
69
|
except Exception as e:
|
72
70
|
logger.warning(f"Failed to get task config: {e}")
|
73
|
-
|
71
|
+
|
74
72
|
return self._config
|
75
|
-
|
73
|
+
|
76
74
|
def is_enabled(self) -> bool:
|
77
75
|
"""Check if task system is enabled and properly configured."""
|
78
76
|
if not self.config or not self.config.enabled:
|
79
77
|
return False
|
80
|
-
|
81
|
-
# Check if required dependencies are available
|
78
|
+
|
82
79
|
if dramatiq is None:
|
83
80
|
logger.warning("Dramatiq not available")
|
84
81
|
return False
|
85
|
-
|
82
|
+
|
86
83
|
return True
|
87
|
-
|
84
|
+
|
88
85
|
def get_redis_url(self) -> Optional[str]:
|
89
86
|
"""Get Redis URL using the same logic as Dramatiq settings generation."""
|
90
87
|
if self._redis_url is None:
|
91
|
-
# Use BaseCfgModule to get config (same as generate_dramatiq_settings_from_config)
|
92
88
|
config = self.get_config()
|
93
|
-
|
89
|
+
|
94
90
|
if not config:
|
95
91
|
raise RuntimeError("No Django-CFG configuration available")
|
96
|
-
|
97
|
-
# Get Redis URL from cache config
|
92
|
+
|
93
|
+
# Get Redis URL from cache config
|
98
94
|
if hasattr(config, 'cache_default') and config.cache_default:
|
99
95
|
self._redis_url = getattr(config.cache_default, 'redis_url', None)
|
100
96
|
if self._redis_url:
|
101
97
|
logger.debug(f"Got Redis URL from cache config: {self._redis_url}")
|
102
98
|
return self._redis_url
|
103
|
-
|
104
|
-
# If no cache_default, try
|
99
|
+
|
100
|
+
# If no cache_default, try Django cache settings
|
105
101
|
try:
|
106
102
|
from django.conf import settings
|
107
103
|
if hasattr(settings, 'CACHES') and 'default' in settings.CACHES:
|
@@ -113,8 +109,8 @@ class DjangoTasks(BaseCfgModule):
|
|
113
109
|
return self._redis_url
|
114
110
|
except Exception as e:
|
115
111
|
logger.debug(f"Could not get Redis URL from Django settings: {e}")
|
116
|
-
|
117
|
-
# Try
|
112
|
+
|
113
|
+
# Try DRAMATIQ_BROKER settings
|
118
114
|
try:
|
119
115
|
from django.conf import settings
|
120
116
|
if hasattr(settings, 'DRAMATIQ_BROKER'):
|
@@ -126,22 +122,21 @@ class DjangoTasks(BaseCfgModule):
|
|
126
122
|
return self._redis_url
|
127
123
|
except Exception as e:
|
128
124
|
logger.debug(f"Could not get Redis URL from DRAMATIQ_BROKER settings: {e}")
|
129
|
-
|
130
|
-
# If still no Redis URL found, raise error (no fallbacks)
|
125
|
+
|
131
126
|
raise RuntimeError("No Redis URL found in cache configuration, Django settings, or DRAMATIQ_BROKER")
|
132
|
-
|
127
|
+
|
133
128
|
return self._redis_url
|
134
|
-
|
129
|
+
|
135
130
|
def get_redis_client(self):
|
136
131
|
"""Get Redis client instance."""
|
137
132
|
redis_url = self.get_redis_url()
|
138
133
|
if not redis_url or redis is None:
|
139
134
|
return None
|
140
|
-
|
135
|
+
|
141
136
|
try:
|
142
137
|
parsed = urlparse(redis_url)
|
143
|
-
|
144
|
-
# Extract database from URL path
|
138
|
+
|
139
|
+
# Extract database from URL path
|
145
140
|
db = 1 # Default
|
146
141
|
if parsed.path and parsed.path != "/":
|
147
142
|
try:
|
@@ -150,9 +145,9 @@ class DjangoTasks(BaseCfgModule):
|
|
150
145
|
pass
|
151
146
|
elif self.config and self.config.dramatiq:
|
152
147
|
db = self.config.dramatiq.redis_db
|
153
|
-
|
148
|
+
|
154
149
|
logger.debug(f"Using Redis DB: {db} from URL: {redis_url}")
|
155
|
-
|
150
|
+
|
156
151
|
return redis.Redis(
|
157
152
|
host=parsed.hostname or 'localhost',
|
158
153
|
port=parsed.port or 6379,
|
@@ -163,49 +158,44 @@ class DjangoTasks(BaseCfgModule):
|
|
163
158
|
except Exception as e:
|
164
159
|
logger.error(f"Failed to create Redis client: {e}")
|
165
160
|
return None
|
166
|
-
|
167
|
-
def _get_current_timestamp(self) -> str:
|
168
|
-
"""Get current timestamp in ISO format."""
|
169
|
-
from datetime import datetime
|
170
|
-
return datetime.now().isoformat()
|
171
|
-
|
161
|
+
|
172
162
|
def check_redis_connection(self) -> bool:
|
173
163
|
"""Check if Redis connection is available."""
|
174
164
|
redis_client = self.get_redis_client()
|
175
165
|
if not redis_client:
|
176
166
|
return False
|
177
|
-
|
167
|
+
|
178
168
|
try:
|
179
169
|
redis_client.ping()
|
180
170
|
return True
|
181
171
|
except Exception as e:
|
182
172
|
logger.error(f"Redis connection failed: {e}")
|
183
173
|
return False
|
184
|
-
|
174
|
+
|
185
175
|
def validate_configuration(self) -> bool:
|
186
176
|
"""Validate complete task system configuration."""
|
187
177
|
if not self.config:
|
188
178
|
logger.error("Task configuration not available")
|
189
179
|
return False
|
190
|
-
|
180
|
+
|
191
181
|
redis_url = self.get_redis_url()
|
192
182
|
if not redis_url:
|
193
183
|
logger.error("Redis URL not configured")
|
194
184
|
return False
|
195
|
-
|
185
|
+
|
196
186
|
return validate_task_config(self.config, redis_url)
|
197
|
-
|
187
|
+
|
198
188
|
def discover_tasks(self) -> List[str]:
|
199
189
|
"""Discover task modules in Django apps."""
|
200
190
|
if not self.config or not self.config.auto_discover_tasks:
|
201
191
|
return []
|
202
|
-
|
192
|
+
|
203
193
|
discovered = []
|
204
|
-
|
194
|
+
|
205
195
|
if apps is None:
|
206
196
|
logger.warning("Django apps not available")
|
207
197
|
return []
|
208
|
-
|
198
|
+
|
209
199
|
try:
|
210
200
|
for app_config in apps.get_app_configs():
|
211
201
|
for module_name in self.config.task_modules:
|
@@ -215,20 +205,19 @@ class DjangoTasks(BaseCfgModule):
|
|
215
205
|
discovered.append(module_path)
|
216
206
|
logger.debug(f"Discovered task module: {module_path}")
|
217
207
|
except ImportError:
|
218
|
-
# Module doesn't exist, which is fine
|
219
208
|
pass
|
220
209
|
except Exception as e:
|
221
210
|
logger.warning(f"Error importing task module {module_path}: {e}")
|
222
211
|
except Exception as e:
|
223
212
|
logger.error(f"Task discovery failed: {e}")
|
224
|
-
|
213
|
+
|
225
214
|
return discovered
|
226
|
-
|
215
|
+
|
227
216
|
def get_constance_fields(self) -> List[ConstanceField]:
|
228
217
|
"""Get Constance fields for Dramatiq configuration."""
|
229
218
|
if not self.is_enabled():
|
230
219
|
return []
|
231
|
-
|
220
|
+
|
232
221
|
fields = [
|
233
222
|
ConstanceField(
|
234
223
|
name="DRAMATIQ_WORKER_PROCESSES",
|
@@ -267,10 +256,10 @@ class DjangoTasks(BaseCfgModule):
|
|
267
256
|
required=False,
|
268
257
|
),
|
269
258
|
]
|
270
|
-
|
259
|
+
|
271
260
|
logger.debug(f"Generated {len(fields)} Constance fields for Dramatiq")
|
272
261
|
return fields
|
273
|
-
|
262
|
+
|
274
263
|
def get_health_status(self) -> Dict[str, Any]:
|
275
264
|
"""Get comprehensive health status of task system."""
|
276
265
|
status = {
|
@@ -279,231 +268,13 @@ class DjangoTasks(BaseCfgModule):
|
|
279
268
|
"configuration_valid": False,
|
280
269
|
"discovered_modules": [],
|
281
270
|
}
|
282
|
-
|
271
|
+
|
283
272
|
if self.is_enabled():
|
284
273
|
status["redis_connection"] = self.check_redis_connection()
|
285
274
|
status["configuration_valid"] = self.validate_configuration()
|
286
275
|
status["discovered_modules"] = self.discover_tasks()
|
287
|
-
|
288
|
-
return status
|
289
|
-
|
290
|
-
|
291
|
-
# === Service Factory ===
|
292
|
-
|
293
|
-
_task_service_instance: Optional[DjangoTasks] = None
|
294
|
-
|
295
|
-
|
296
|
-
def get_task_service() -> DjangoTasks:
|
297
|
-
"""Get the global task service instance."""
|
298
|
-
global _task_service_instance
|
299
|
-
|
300
|
-
if _task_service_instance is None:
|
301
|
-
_task_service_instance = DjangoTasks()
|
302
|
-
|
303
|
-
return _task_service_instance
|
304
|
-
|
305
|
-
|
306
|
-
def reset_task_service():
|
307
|
-
"""Reset the global task service instance (useful for testing)."""
|
308
|
-
global _task_service_instance
|
309
|
-
_task_service_instance = None
|
310
|
-
|
311
|
-
|
312
|
-
# === Utility Functions ===
|
313
|
-
|
314
|
-
def is_task_system_available() -> bool:
|
315
|
-
"""Check if task system is available and properly configured."""
|
316
|
-
try:
|
317
|
-
service = get_task_service()
|
318
|
-
return service.is_enabled()
|
319
|
-
except Exception:
|
320
|
-
return False
|
321
|
-
|
322
|
-
|
323
|
-
def get_task_health() -> Dict[str, Any]:
|
324
|
-
"""Get task system health status."""
|
325
|
-
try:
|
326
|
-
service = get_task_service()
|
327
|
-
return service.get_health_status()
|
328
|
-
except Exception as e:
|
329
|
-
return {
|
330
|
-
"enabled": False,
|
331
|
-
"error": str(e),
|
332
|
-
"redis_connection": False,
|
333
|
-
"configuration_valid": False,
|
334
|
-
}
|
335
|
-
|
336
|
-
|
337
|
-
def initialize_task_system():
|
338
|
-
"""
|
339
|
-
Initialize the task system during Django app startup.
|
340
|
-
This function is called from Django AppConfig.ready() method.
|
341
|
-
"""
|
342
|
-
try:
|
343
|
-
service = get_task_service()
|
344
|
-
|
345
|
-
# Force config reload to ensure we have fresh config
|
346
|
-
service._config = None
|
347
|
-
config = service.config
|
348
|
-
|
349
|
-
if config and config.enabled:
|
350
|
-
logger.info("🔧 Initializing Django-CFG task system...")
|
351
|
-
|
352
|
-
# Set up Dramatiq broker from Django settings
|
353
|
-
try:
|
354
|
-
import dramatiq
|
355
|
-
from django.conf import settings
|
356
|
-
|
357
|
-
# Django-dramatiq automatically configures the broker from DRAMATIQ_BROKER setting
|
358
|
-
if hasattr(settings, 'DRAMATIQ_BROKER'):
|
359
|
-
# Configure broker with middleware
|
360
|
-
broker_config = settings.DRAMATIQ_BROKER
|
361
|
-
middleware_list = getattr(settings, 'DRAMATIQ_MIDDLEWARE', [])
|
362
|
-
|
363
|
-
# Import and instantiate middleware
|
364
|
-
middleware_instances = []
|
365
|
-
for middleware_path in middleware_list:
|
366
|
-
try:
|
367
|
-
module_path, class_name = middleware_path.rsplit('.', 1)
|
368
|
-
module = __import__(module_path, fromlist=[class_name])
|
369
|
-
middleware_class = getattr(module, class_name)
|
370
|
-
middleware_instances.append(middleware_class())
|
371
|
-
except Exception as e:
|
372
|
-
logger.warning(f"Failed to load middleware {middleware_path}: {e}")
|
373
|
-
|
374
|
-
# Create broker with middleware
|
375
|
-
broker_class_path = broker_config['BROKER']
|
376
|
-
module_path, class_name = broker_class_path.rsplit('.', 1)
|
377
|
-
module = __import__(module_path, fromlist=[class_name])
|
378
|
-
broker_class = getattr(module, class_name)
|
379
|
-
|
380
|
-
broker_options = broker_config.get('OPTIONS', {})
|
381
|
-
broker = broker_class(middleware=middleware_instances, **broker_options)
|
382
|
-
|
383
|
-
# Set as default broker
|
384
|
-
dramatiq.set_broker(broker)
|
385
|
-
|
386
|
-
logger.debug(f"✅ Dramatiq broker configured with {len(middleware_instances)} middleware")
|
387
|
-
else:
|
388
|
-
logger.warning("DRAMATIQ_BROKER not found in Django settings")
|
389
|
-
|
390
|
-
except Exception as e:
|
391
|
-
logger.warning(f"Failed to configure Dramatiq: {e}")
|
392
|
-
|
393
|
-
logger.info("✅ Task system initialized successfully")
|
394
|
-
logger.info("💡 To start workers, run: python manage.py rundramatiq")
|
395
|
-
else:
|
396
|
-
logger.debug(f"Task system not enabled (config: {config}), skipping initialization")
|
397
|
-
|
398
|
-
except Exception as e:
|
399
|
-
logger.error(f"Failed to initialize task system: {e}")
|
400
|
-
|
401
|
-
|
402
|
-
def generate_dramatiq_settings_from_config(config):
|
403
|
-
"""
|
404
|
-
Generate Dramatiq settings from DjangoConfig instance.
|
405
|
-
|
406
|
-
Args:
|
407
|
-
config: DjangoConfig instance with tasks configuration
|
408
|
-
|
409
|
-
Returns:
|
410
|
-
Dict[str, Any]: Dramatiq settings dictionary or empty dict if not enabled
|
411
|
-
"""
|
412
|
-
try:
|
413
|
-
if not hasattr(config, "tasks") or not config.tasks or not config.tasks.enabled:
|
414
|
-
return {}
|
415
|
-
|
416
|
-
# Get Redis URL from cache configuration
|
417
|
-
redis_url = None
|
418
|
-
if config.cache_default and hasattr(config.cache_default, 'redis_url'):
|
419
|
-
redis_url = config.cache_default.redis_url
|
420
|
-
elif config.cache_default and hasattr(config.cache_default, 'location'):
|
421
|
-
redis_url = config.cache_default.location
|
422
|
-
else:
|
423
|
-
# Fallback to default Redis URL
|
424
|
-
redis_url = "redis://localhost:6379"
|
425
|
-
|
426
|
-
if redis_url:
|
427
|
-
dramatiq_settings = config.tasks.get_dramatiq_settings(redis_url)
|
428
|
-
logger.debug(f"Generated Dramatiq settings with Redis URL: {redis_url}")
|
429
|
-
return dramatiq_settings
|
430
|
-
else:
|
431
|
-
logger.warning("Tasks enabled but no Redis URL available for Dramatiq")
|
432
|
-
return {}
|
433
|
-
|
434
|
-
except Exception as e:
|
435
|
-
logger.error(f"Failed to generate Dramatiq settings: {e}")
|
436
|
-
return {}
|
437
|
-
|
438
|
-
|
439
|
-
def extend_constance_config_with_tasks():
|
440
|
-
"""
|
441
|
-
Extend Constance configuration with Dramatiq task fields if tasks are enabled.
|
442
|
-
"""
|
443
|
-
try:
|
444
|
-
service = get_task_service()
|
445
|
-
if not service.is_enabled():
|
446
|
-
logger.debug("Task system not enabled, skipping Constance extension")
|
447
|
-
return []
|
448
|
-
|
449
|
-
fields = service.get_constance_fields()
|
450
|
-
logger.info(f"🔧 Extended Constance with {len(fields)} task configuration fields")
|
451
|
-
return fields
|
452
|
-
|
453
|
-
except Exception as e:
|
454
|
-
logger.error(f"Failed to extend Constance config with tasks: {e}")
|
455
|
-
return []
|
456
276
|
|
277
|
+
return status
|
457
278
|
|
458
|
-
# === Exports ===
|
459
279
|
|
460
|
-
|
461
|
-
"""
|
462
|
-
Generate Dramatiq settings from auto-discovered DjangoConfig.
|
463
|
-
|
464
|
-
Returns:
|
465
|
-
Dictionary of Dramatiq settings or None if tasks disabled
|
466
|
-
"""
|
467
|
-
try:
|
468
|
-
# Get config through BaseCfgModule
|
469
|
-
base_module = BaseCfgModule()
|
470
|
-
config = base_module.get_config()
|
471
|
-
|
472
|
-
if not config or not hasattr(config, 'tasks') or not config.tasks or not config.tasks.enabled:
|
473
|
-
return None
|
474
|
-
|
475
|
-
# Get Redis URL from cache config or environment
|
476
|
-
redis_url = None
|
477
|
-
if hasattr(config, 'cache_default') and config.cache_default:
|
478
|
-
redis_url = getattr(config.cache_default, 'redis_url', None)
|
479
|
-
|
480
|
-
if not redis_url:
|
481
|
-
# Fallback to environment or default
|
482
|
-
import os
|
483
|
-
redis_url = os.getenv('REDIS_URL', 'redis://localhost:6379/1')
|
484
|
-
|
485
|
-
# Generate Dramatiq settings
|
486
|
-
dramatiq_settings = config.tasks.get_dramatiq_settings(redis_url)
|
487
|
-
|
488
|
-
# Ensure we only use Redis broker (no RabbitMQ)
|
489
|
-
if 'DRAMATIQ_BROKER' in dramatiq_settings:
|
490
|
-
dramatiq_settings['DRAMATIQ_BROKER']['BROKER'] = 'dramatiq.brokers.redis.RedisBroker'
|
491
|
-
|
492
|
-
logger.info(f"✅ Generated Dramatiq settings with Redis broker and {len(config.tasks.dramatiq.queues)} queues")
|
493
|
-
return dramatiq_settings
|
494
|
-
|
495
|
-
except Exception as e:
|
496
|
-
logger.error(f"Failed to generate Dramatiq settings: {e}")
|
497
|
-
return None
|
498
|
-
|
499
|
-
|
500
|
-
__all__ = [
|
501
|
-
"DjangoTasks",
|
502
|
-
"get_task_service",
|
503
|
-
"reset_task_service",
|
504
|
-
"is_task_system_available",
|
505
|
-
"get_task_health",
|
506
|
-
"generate_dramatiq_settings_from_config",
|
507
|
-
"extend_constance_config_with_tasks",
|
508
|
-
"initialize_task_system",
|
509
|
-
]
|
280
|
+
__all__ = ["DjangoTasks"]
|