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,25 @@
|
|
1
|
+
"""
|
2
|
+
Base provider configuration for payment providers.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from pydantic import BaseModel, Field
|
6
|
+
from typing import Dict
|
7
|
+
|
8
|
+
|
9
|
+
class BaseProviderConfig(BaseModel):
|
10
|
+
"""Base configuration for payment providers."""
|
11
|
+
|
12
|
+
provider_name: str = Field(..., description="Provider name")
|
13
|
+
enabled: bool = Field(default=True, description="Whether provider is enabled")
|
14
|
+
|
15
|
+
def get_provider_config(self) -> Dict[str, any]:
|
16
|
+
"""Get provider-specific configuration."""
|
17
|
+
return {
|
18
|
+
'provider_name': self.provider_name,
|
19
|
+
'enabled': self.enabled,
|
20
|
+
}
|
21
|
+
|
22
|
+
|
23
|
+
__all__ = [
|
24
|
+
"BaseProviderConfig",
|
25
|
+
]
|
@@ -0,0 +1,48 @@
|
|
1
|
+
"""
|
2
|
+
NowPayments provider configuration.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from pydantic import Field
|
6
|
+
from typing import Dict
|
7
|
+
from .base import BaseProviderConfig
|
8
|
+
|
9
|
+
|
10
|
+
class NowPaymentsProviderConfig(BaseProviderConfig):
|
11
|
+
"""NowPayments provider configuration."""
|
12
|
+
|
13
|
+
provider_name: str = Field(default="nowpayments", description="Provider name")
|
14
|
+
api_key: str = Field(default="", description="NowPayments API key")
|
15
|
+
ipn_secret: str = Field(default="", description="NowPayments IPN secret for webhook validation")
|
16
|
+
sandbox_mode: bool = Field(default=True, description="NowPayments sandbox mode")
|
17
|
+
|
18
|
+
def get_provider_config(self) -> Dict[str, any]:
|
19
|
+
"""Get NowPayments-specific configuration."""
|
20
|
+
return {
|
21
|
+
'provider_name': self.provider_name,
|
22
|
+
'enabled': self.enabled and bool(self.api_key.strip()),
|
23
|
+
'api_key': self.api_key,
|
24
|
+
'ipn_secret': self.ipn_secret,
|
25
|
+
'sandbox_mode': self.sandbox_mode,
|
26
|
+
}
|
27
|
+
|
28
|
+
|
29
|
+
# Future provider configs (commented out for now)
|
30
|
+
# class StripeProviderConfig(BaseProviderConfig):
|
31
|
+
# """Stripe provider configuration."""
|
32
|
+
#
|
33
|
+
# provider_name: str = Field(default="stripe", description="Provider name")
|
34
|
+
# api_key: str = Field(default="", description="Stripe API key")
|
35
|
+
# webhook_secret: str = Field(default="", description="Stripe webhook secret")
|
36
|
+
#
|
37
|
+
# def get_provider_config(self) -> Dict[str, any]:
|
38
|
+
# return {
|
39
|
+
# 'provider_name': self.provider_name,
|
40
|
+
# 'enabled': self.enabled and bool(self.api_key.strip()),
|
41
|
+
# 'api_key': self.api_key,
|
42
|
+
# 'webhook_secret': self.webhook_secret,
|
43
|
+
# }
|
44
|
+
|
45
|
+
|
46
|
+
__all__ = [
|
47
|
+
"NowPaymentsProviderConfig",
|
48
|
+
]
|
@@ -0,0 +1,18 @@
|
|
1
|
+
"""
|
2
|
+
Service configuration models for django_cfg.
|
3
|
+
|
4
|
+
Provides type-safe configuration for various services:
|
5
|
+
- EmailConfig: Email/SMTP configuration
|
6
|
+
- TelegramConfig: Telegram bot configuration
|
7
|
+
- ServiceConfig: Generic service configuration
|
8
|
+
"""
|
9
|
+
|
10
|
+
from .email import EmailConfig
|
11
|
+
from .telegram import TelegramConfig
|
12
|
+
from .base import ServiceConfig
|
13
|
+
|
14
|
+
__all__ = [
|
15
|
+
"EmailConfig",
|
16
|
+
"TelegramConfig",
|
17
|
+
"ServiceConfig",
|
18
|
+
]
|
@@ -0,0 +1,65 @@
|
|
1
|
+
"""
|
2
|
+
Base service configuration for django_cfg.
|
3
|
+
|
4
|
+
Generic service configuration for custom services.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from typing import Dict, Any
|
8
|
+
from pydantic import BaseModel, Field, field_validator
|
9
|
+
|
10
|
+
|
11
|
+
class ServiceConfig(BaseModel):
|
12
|
+
"""
|
13
|
+
Generic service configuration for custom services.
|
14
|
+
|
15
|
+
This is a fallback for services that don't have specialized models.
|
16
|
+
Prefer specific models like EmailConfig, TelegramConfig when available.
|
17
|
+
"""
|
18
|
+
|
19
|
+
model_config = {
|
20
|
+
"str_strip_whitespace": True,
|
21
|
+
"validate_assignment": True,
|
22
|
+
"extra": "allow", # Allow additional fields for flexibility
|
23
|
+
}
|
24
|
+
|
25
|
+
name: str = Field(
|
26
|
+
...,
|
27
|
+
description="Service name",
|
28
|
+
min_length=1,
|
29
|
+
max_length=50,
|
30
|
+
)
|
31
|
+
|
32
|
+
enabled: bool = Field(
|
33
|
+
default=True,
|
34
|
+
description="Whether service is enabled",
|
35
|
+
)
|
36
|
+
|
37
|
+
config: Dict[str, Any] = Field(
|
38
|
+
default_factory=dict,
|
39
|
+
description="Service-specific configuration",
|
40
|
+
)
|
41
|
+
|
42
|
+
@field_validator('name')
|
43
|
+
@classmethod
|
44
|
+
def validate_name(cls, v: str) -> str:
|
45
|
+
"""Validate service name format."""
|
46
|
+
if not v.replace('_', '').replace('-', '').isalnum():
|
47
|
+
raise ValueError(
|
48
|
+
"Service name must contain only alphanumeric characters, "
|
49
|
+
"underscores, and hyphens"
|
50
|
+
)
|
51
|
+
|
52
|
+
return v
|
53
|
+
|
54
|
+
def to_config_dict(self) -> Dict[str, Any]:
|
55
|
+
"""Convert to configuration dictionary."""
|
56
|
+
return {
|
57
|
+
'name': self.name,
|
58
|
+
'enabled': self.enabled,
|
59
|
+
**self.config,
|
60
|
+
}
|
61
|
+
|
62
|
+
|
63
|
+
__all__ = [
|
64
|
+
"ServiceConfig",
|
65
|
+
]
|
@@ -0,0 +1,172 @@
|
|
1
|
+
"""
|
2
|
+
Telegram service configuration for django_cfg.
|
3
|
+
|
4
|
+
Type-safe Telegram bot configuration with validation.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from typing import Dict, Optional, Any, Literal
|
8
|
+
from pydantic import BaseModel, Field, field_validator
|
9
|
+
|
10
|
+
|
11
|
+
class TelegramConfig(BaseModel):
|
12
|
+
"""
|
13
|
+
Type-safe Telegram bot configuration.
|
14
|
+
|
15
|
+
Supports Telegram Bot API for notifications and alerts.
|
16
|
+
"""
|
17
|
+
|
18
|
+
model_config = {
|
19
|
+
"str_strip_whitespace": True,
|
20
|
+
"validate_assignment": True,
|
21
|
+
"extra": "forbid",
|
22
|
+
}
|
23
|
+
|
24
|
+
# Bot configuration
|
25
|
+
bot_token: str = Field(
|
26
|
+
...,
|
27
|
+
description="Telegram bot token from @BotFather",
|
28
|
+
min_length=10,
|
29
|
+
repr=False, # Don't show in repr for security
|
30
|
+
)
|
31
|
+
|
32
|
+
chat_id: int = Field(
|
33
|
+
...,
|
34
|
+
description="Telegram chat ID for notifications",
|
35
|
+
)
|
36
|
+
|
37
|
+
# Message settings
|
38
|
+
parse_mode: Literal["HTML", "Markdown", "MarkdownV2", None] = Field(
|
39
|
+
default="HTML",
|
40
|
+
description="Message parse mode",
|
41
|
+
)
|
42
|
+
|
43
|
+
disable_notification: bool = Field(
|
44
|
+
default=False,
|
45
|
+
description="Send messages silently",
|
46
|
+
)
|
47
|
+
|
48
|
+
disable_web_page_preview: bool = Field(
|
49
|
+
default=False,
|
50
|
+
description="Disable link previews in messages",
|
51
|
+
)
|
52
|
+
|
53
|
+
# Connection settings
|
54
|
+
timeout: int = Field(
|
55
|
+
default=30,
|
56
|
+
description="Request timeout in seconds",
|
57
|
+
ge=1,
|
58
|
+
le=300,
|
59
|
+
)
|
60
|
+
|
61
|
+
# Webhook settings (optional)
|
62
|
+
webhook_url: Optional[str] = Field(
|
63
|
+
default=None,
|
64
|
+
description="Webhook URL for receiving updates",
|
65
|
+
)
|
66
|
+
|
67
|
+
webhook_secret: Optional[str] = Field(
|
68
|
+
default=None,
|
69
|
+
description="Webhook secret token",
|
70
|
+
repr=False,
|
71
|
+
)
|
72
|
+
|
73
|
+
# Rate limiting
|
74
|
+
max_retries: int = Field(
|
75
|
+
default=3,
|
76
|
+
description="Maximum retry attempts for failed requests",
|
77
|
+
ge=0,
|
78
|
+
le=10,
|
79
|
+
)
|
80
|
+
|
81
|
+
retry_delay: float = Field(
|
82
|
+
default=1.0,
|
83
|
+
description="Delay between retry attempts in seconds",
|
84
|
+
ge=0.1,
|
85
|
+
le=60.0,
|
86
|
+
)
|
87
|
+
|
88
|
+
@field_validator('bot_token')
|
89
|
+
@classmethod
|
90
|
+
def validate_bot_token(cls, v: str) -> str:
|
91
|
+
"""Validate Telegram bot token format."""
|
92
|
+
# Basic format validation: should be digits:alphanumeric
|
93
|
+
if ':' not in v:
|
94
|
+
raise ValueError("Invalid bot token format: missing ':' separator")
|
95
|
+
|
96
|
+
parts = v.split(':', 1)
|
97
|
+
if len(parts) != 2:
|
98
|
+
raise ValueError("Invalid bot token format: should be 'bot_id:token'")
|
99
|
+
|
100
|
+
bot_id, token = parts
|
101
|
+
|
102
|
+
# Validate bot ID (should be numeric)
|
103
|
+
if not bot_id.isdigit():
|
104
|
+
raise ValueError("Invalid bot token: bot ID must be numeric")
|
105
|
+
|
106
|
+
# Validate token length (should be around 35 characters)
|
107
|
+
if len(token) < 30:
|
108
|
+
raise ValueError("Invalid bot token: token too short")
|
109
|
+
|
110
|
+
return v
|
111
|
+
|
112
|
+
@field_validator('chat_id')
|
113
|
+
@classmethod
|
114
|
+
def validate_chat_id(cls, v: int) -> int:
|
115
|
+
"""Validate Telegram chat ID."""
|
116
|
+
# Chat IDs can be negative (groups/channels) or positive (users)
|
117
|
+
# Just check it's not zero
|
118
|
+
if v == 0:
|
119
|
+
raise ValueError("Chat ID cannot be zero")
|
120
|
+
|
121
|
+
return v
|
122
|
+
|
123
|
+
@field_validator('webhook_url')
|
124
|
+
@classmethod
|
125
|
+
def validate_webhook_url(cls, v: Optional[str]) -> Optional[str]:
|
126
|
+
"""Validate webhook URL format."""
|
127
|
+
if v is None:
|
128
|
+
return v
|
129
|
+
|
130
|
+
if not v.startswith('https://'):
|
131
|
+
raise ValueError("Webhook URL must use HTTPS")
|
132
|
+
|
133
|
+
from urllib.parse import urlparse
|
134
|
+
try:
|
135
|
+
parsed = urlparse(v)
|
136
|
+
if not parsed.netloc:
|
137
|
+
raise ValueError("Invalid webhook URL: missing domain")
|
138
|
+
except Exception as e:
|
139
|
+
raise ValueError(f"Invalid webhook URL: {e}") from e
|
140
|
+
|
141
|
+
return v
|
142
|
+
|
143
|
+
def to_config_dict(self) -> Dict[str, Any]:
|
144
|
+
"""
|
145
|
+
Convert to configuration dictionary.
|
146
|
+
|
147
|
+
Returns:
|
148
|
+
Telegram configuration dictionary
|
149
|
+
"""
|
150
|
+
config = {
|
151
|
+
'bot_token': self.bot_token,
|
152
|
+
'chat_id': self.chat_id,
|
153
|
+
'parse_mode': self.parse_mode,
|
154
|
+
'disable_notification': self.disable_notification,
|
155
|
+
'disable_web_page_preview': self.disable_web_page_preview,
|
156
|
+
'timeout': self.timeout,
|
157
|
+
'max_retries': self.max_retries,
|
158
|
+
'retry_delay': self.retry_delay,
|
159
|
+
}
|
160
|
+
|
161
|
+
if self.webhook_url:
|
162
|
+
config['webhook_url'] = self.webhook_url
|
163
|
+
|
164
|
+
if self.webhook_secret:
|
165
|
+
config['webhook_secret'] = self.webhook_secret
|
166
|
+
|
167
|
+
return config
|
168
|
+
|
169
|
+
|
170
|
+
__all__ = [
|
171
|
+
"TelegramConfig",
|
172
|
+
]
|
@@ -0,0 +1,51 @@
|
|
1
|
+
"""
|
2
|
+
Task processing configuration models for Django-CFG.
|
3
|
+
|
4
|
+
This module provides type-safe Pydantic models for configuring background task
|
5
|
+
processing with Dramatiq, including worker management, queue configuration,
|
6
|
+
and monitoring settings.
|
7
|
+
|
8
|
+
Architecture:
|
9
|
+
config.py - Main TaskConfig and enums
|
10
|
+
backends.py - DramatiqConfig and WorkerConfig
|
11
|
+
utils.py - Utility functions
|
12
|
+
|
13
|
+
Example:
|
14
|
+
```python
|
15
|
+
from django_cfg.models.tasks import TaskConfig, DramatiqConfig
|
16
|
+
|
17
|
+
# Basic configuration
|
18
|
+
tasks = TaskConfig(
|
19
|
+
enabled=True,
|
20
|
+
dramatiq=DramatiqConfig(
|
21
|
+
processes=4,
|
22
|
+
threads=8,
|
23
|
+
queues=["default", "high", "low"],
|
24
|
+
)
|
25
|
+
)
|
26
|
+
|
27
|
+
# Get environment-aware defaults
|
28
|
+
from django_cfg.models.tasks import get_default_task_config
|
29
|
+
tasks = get_default_task_config(debug=True)
|
30
|
+
```
|
31
|
+
"""
|
32
|
+
|
33
|
+
from .config import TaskConfig, TaskBackend, QueuePriority
|
34
|
+
from .backends import DramatiqConfig, WorkerConfig
|
35
|
+
from .utils import get_default_task_config, validate_task_config, get_smart_queues
|
36
|
+
|
37
|
+
__all__ = [
|
38
|
+
# Main configuration
|
39
|
+
"TaskConfig",
|
40
|
+
"TaskBackend",
|
41
|
+
"QueuePriority",
|
42
|
+
|
43
|
+
# Backend configurations
|
44
|
+
"DramatiqConfig",
|
45
|
+
"WorkerConfig",
|
46
|
+
|
47
|
+
# Utility functions
|
48
|
+
"get_default_task_config",
|
49
|
+
"validate_task_config",
|
50
|
+
"get_smart_queues",
|
51
|
+
]
|
@@ -0,0 +1,250 @@
|
|
1
|
+
"""
|
2
|
+
Backend-specific configurations.
|
3
|
+
|
4
|
+
Contains Dramatiq and Worker configuration models.
|
5
|
+
Size: ~200 lines (focused on backend settings)
|
6
|
+
"""
|
7
|
+
|
8
|
+
from pydantic import BaseModel, Field, field_validator
|
9
|
+
from typing import Optional, List, Literal
|
10
|
+
import os
|
11
|
+
import logging
|
12
|
+
|
13
|
+
logger = logging.getLogger(__name__)
|
14
|
+
|
15
|
+
|
16
|
+
class DramatiqConfig(BaseModel):
|
17
|
+
"""
|
18
|
+
Dramatiq-specific configuration with production-ready defaults.
|
19
|
+
|
20
|
+
This model provides comprehensive configuration for Dramatiq background
|
21
|
+
task processing, including Redis settings, worker configuration,
|
22
|
+
middleware stack, and monitoring options.
|
23
|
+
|
24
|
+
Example:
|
25
|
+
```python
|
26
|
+
from django_cfg.models.tasks import DramatiqConfig
|
27
|
+
|
28
|
+
dramatiq = DramatiqConfig(
|
29
|
+
redis_db=1,
|
30
|
+
processes=4,
|
31
|
+
threads=8,
|
32
|
+
)
|
33
|
+
```
|
34
|
+
"""
|
35
|
+
|
36
|
+
# === Redis Configuration ===
|
37
|
+
redis_db: int = Field(
|
38
|
+
default=1,
|
39
|
+
ge=0,
|
40
|
+
le=15,
|
41
|
+
description="Redis database number for tasks (separate from cache)"
|
42
|
+
)
|
43
|
+
redis_key_prefix: str = Field(
|
44
|
+
default="dramatiq",
|
45
|
+
description="Redis key prefix for task data"
|
46
|
+
)
|
47
|
+
|
48
|
+
# === Task Configuration ===
|
49
|
+
max_retries: int = Field(
|
50
|
+
default=3,
|
51
|
+
ge=0,
|
52
|
+
le=10,
|
53
|
+
description="Default maximum retry count for failed tasks"
|
54
|
+
)
|
55
|
+
default_priority: int = Field(
|
56
|
+
default=5,
|
57
|
+
ge=0,
|
58
|
+
le=10,
|
59
|
+
description="Default task priority (0=highest, 10=lowest)"
|
60
|
+
)
|
61
|
+
max_age_seconds: int = Field(
|
62
|
+
default=3600,
|
63
|
+
ge=60,
|
64
|
+
description="Maximum age for tasks before they expire"
|
65
|
+
)
|
66
|
+
time_limit_seconds: int = Field(
|
67
|
+
default=600,
|
68
|
+
ge=30,
|
69
|
+
description="Maximum execution time per task"
|
70
|
+
)
|
71
|
+
|
72
|
+
# === Worker Configuration ===
|
73
|
+
processes: int = Field(
|
74
|
+
default=4,
|
75
|
+
ge=1,
|
76
|
+
le=32,
|
77
|
+
description="Number of worker processes"
|
78
|
+
)
|
79
|
+
threads: int = Field(
|
80
|
+
default=8,
|
81
|
+
ge=1,
|
82
|
+
le=64,
|
83
|
+
description="Number of threads per worker process"
|
84
|
+
)
|
85
|
+
queues: List[str] = Field(
|
86
|
+
default=["default", "high", "low"],
|
87
|
+
description="Available task queues"
|
88
|
+
)
|
89
|
+
|
90
|
+
# === Middleware Stack ===
|
91
|
+
middleware: List[str] = Field(
|
92
|
+
default=[
|
93
|
+
"dramatiq.middleware.AgeLimit",
|
94
|
+
"dramatiq.middleware.TimeLimit",
|
95
|
+
"dramatiq.middleware.Callbacks",
|
96
|
+
"dramatiq.middleware.Retries",
|
97
|
+
"dramatiq.middleware.Prometheus",
|
98
|
+
"django_dramatiq.middleware.AdminMiddleware",
|
99
|
+
"django_dramatiq.middleware.DbConnectionsMiddleware",
|
100
|
+
],
|
101
|
+
description="Middleware stack for task processing"
|
102
|
+
)
|
103
|
+
|
104
|
+
# === Monitoring & Admin ===
|
105
|
+
prometheus_enabled: bool = Field(
|
106
|
+
default=True,
|
107
|
+
description="Enable Prometheus metrics collection"
|
108
|
+
)
|
109
|
+
admin_enabled: bool = Field(
|
110
|
+
default=True,
|
111
|
+
description="Enable Django admin interface integration"
|
112
|
+
)
|
113
|
+
|
114
|
+
# === Performance Tuning ===
|
115
|
+
prefetch_multiplier: int = Field(
|
116
|
+
default=2,
|
117
|
+
ge=1,
|
118
|
+
le=10,
|
119
|
+
description="Message prefetch multiplier for workers"
|
120
|
+
)
|
121
|
+
max_memory_mb: Optional[int] = Field(
|
122
|
+
default=512,
|
123
|
+
ge=128,
|
124
|
+
description="Maximum memory usage per worker (MB)"
|
125
|
+
)
|
126
|
+
|
127
|
+
@field_validator("processes")
|
128
|
+
@classmethod
|
129
|
+
def validate_processes(cls, v: int) -> int:
|
130
|
+
"""Ensure reasonable process count based on CPU cores."""
|
131
|
+
cpu_count = os.cpu_count() or 4
|
132
|
+
max_recommended = cpu_count * 2
|
133
|
+
|
134
|
+
if v > max_recommended:
|
135
|
+
logger.warning(
|
136
|
+
f"Process count ({v}) exceeds recommended maximum ({max_recommended}). "
|
137
|
+
f"Consider reducing to avoid resource contention."
|
138
|
+
)
|
139
|
+
|
140
|
+
return v
|
141
|
+
|
142
|
+
@field_validator("queues")
|
143
|
+
@classmethod
|
144
|
+
def validate_queues(cls, v: List[str]) -> List[str]:
|
145
|
+
"""Ensure queue names are valid and include default."""
|
146
|
+
if not v:
|
147
|
+
raise ValueError("At least one queue must be specified")
|
148
|
+
|
149
|
+
# Ensure 'default' queue exists
|
150
|
+
if "default" not in v:
|
151
|
+
v.append("default")
|
152
|
+
|
153
|
+
# Validate queue names (alphanumeric + underscore/hyphen)
|
154
|
+
import re
|
155
|
+
pattern = re.compile(r'^[a-zA-Z0-9_-]+$')
|
156
|
+
|
157
|
+
for queue in v:
|
158
|
+
if not pattern.match(queue):
|
159
|
+
raise ValueError(f"Invalid queue name: {queue}. Use only alphanumeric, underscore, and hyphen.")
|
160
|
+
|
161
|
+
return v
|
162
|
+
|
163
|
+
@field_validator("middleware")
|
164
|
+
@classmethod
|
165
|
+
def validate_middleware(cls, v: List[str]) -> List[str]:
|
166
|
+
"""Ensure essential middleware is included."""
|
167
|
+
essential_middleware = [
|
168
|
+
"dramatiq.middleware.Retries",
|
169
|
+
"django_dramatiq.middleware.DbConnectionsMiddleware",
|
170
|
+
]
|
171
|
+
|
172
|
+
for middleware in essential_middleware:
|
173
|
+
if middleware not in v:
|
174
|
+
logger.warning(f"Adding essential middleware: {middleware}")
|
175
|
+
v.append(middleware)
|
176
|
+
|
177
|
+
return v
|
178
|
+
|
179
|
+
|
180
|
+
class WorkerConfig(BaseModel):
|
181
|
+
"""
|
182
|
+
Worker process and resource configuration.
|
183
|
+
|
184
|
+
Provides fine-grained control over worker behavior, resource limits,
|
185
|
+
and health monitoring settings.
|
186
|
+
|
187
|
+
Example:
|
188
|
+
```python
|
189
|
+
from django_cfg.models.tasks import WorkerConfig
|
190
|
+
|
191
|
+
worker = WorkerConfig(
|
192
|
+
shutdown_timeout=30,
|
193
|
+
max_memory_mb=512,
|
194
|
+
health_check_enabled=True,
|
195
|
+
)
|
196
|
+
```
|
197
|
+
"""
|
198
|
+
|
199
|
+
# === Process Management ===
|
200
|
+
shutdown_timeout: int = Field(
|
201
|
+
default=30,
|
202
|
+
ge=5,
|
203
|
+
le=300,
|
204
|
+
description="Graceful shutdown timeout in seconds"
|
205
|
+
)
|
206
|
+
heartbeat_interval: int = Field(
|
207
|
+
default=5,
|
208
|
+
ge=1,
|
209
|
+
le=60,
|
210
|
+
description="Worker heartbeat interval in seconds"
|
211
|
+
)
|
212
|
+
|
213
|
+
# === Resource Limits ===
|
214
|
+
max_memory_mb: Optional[int] = Field(
|
215
|
+
default=512,
|
216
|
+
ge=128,
|
217
|
+
description="Maximum memory per worker process (MB)"
|
218
|
+
)
|
219
|
+
max_cpu_percent: Optional[float] = Field(
|
220
|
+
default=80.0,
|
221
|
+
ge=10.0,
|
222
|
+
le=100.0,
|
223
|
+
description="Maximum CPU usage per worker (%)"
|
224
|
+
)
|
225
|
+
|
226
|
+
# === Health Monitoring ===
|
227
|
+
health_check_enabled: bool = Field(
|
228
|
+
default=True,
|
229
|
+
description="Enable worker health monitoring"
|
230
|
+
)
|
231
|
+
restart_on_memory_limit: bool = Field(
|
232
|
+
default=True,
|
233
|
+
description="Restart worker if memory limit exceeded"
|
234
|
+
)
|
235
|
+
|
236
|
+
# === Logging ===
|
237
|
+
log_level: Literal["DEBUG", "INFO", "WARNING", "ERROR"] = Field(
|
238
|
+
default="INFO",
|
239
|
+
description="Worker log level"
|
240
|
+
)
|
241
|
+
log_format: str = Field(
|
242
|
+
default="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
|
243
|
+
description="Log message format"
|
244
|
+
)
|
245
|
+
|
246
|
+
|
247
|
+
__all__ = [
|
248
|
+
"DramatiqConfig",
|
249
|
+
"WorkerConfig",
|
250
|
+
]
|