django-cfg 1.2.29__py3-none-any.whl → 1.3.1__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/api/health/views.py +4 -2
- django_cfg/apps/knowbase/config/settings.py +16 -15
- django_cfg/apps/payments/README.md +326 -0
- django_cfg/apps/payments/admin/__init__.py +20 -9
- django_cfg/apps/payments/admin/api_keys_admin.py +521 -237
- django_cfg/apps/payments/admin/balance_admin.py +592 -297
- django_cfg/apps/payments/admin/currencies_admin.py +600 -108
- django_cfg/apps/payments/admin/filters.py +306 -199
- django_cfg/apps/payments/admin/payments_admin.py +470 -64
- django_cfg/apps/payments/admin/subscriptions_admin.py +578 -128
- django_cfg/apps/payments/admin_interface/__init__.py +18 -0
- django_cfg/apps/payments/admin_interface/templates/payments/base.html +162 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/dev_tool_card.html +38 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/loading_spinner.html +16 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/notification.html +27 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/provider_card.html +86 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/status_card.html +39 -0
- django_cfg/apps/payments/admin_interface/templates/payments/currency_converter.html +382 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_dashboard.html +300 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +303 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_list.html +382 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_status.html +500 -0
- django_cfg/apps/payments/admin_interface/templates/payments/webhook_dashboard.html +594 -0
- django_cfg/apps/payments/admin_interface/views/__init__.py +23 -0
- django_cfg/apps/payments/admin_interface/views/payment_views.py +259 -0
- django_cfg/apps/payments/admin_interface/views/webhook_dashboard.py +37 -0
- django_cfg/apps/payments/apps.py +34 -9
- django_cfg/apps/payments/config/__init__.py +28 -51
- django_cfg/apps/payments/config/constance/__init__.py +22 -0
- django_cfg/apps/payments/config/constance/config_service.py +123 -0
- django_cfg/apps/payments/config/constance/fields.py +69 -0
- django_cfg/apps/payments/config/constance/settings.py +160 -0
- django_cfg/apps/payments/config/django_cfg_integration.py +202 -0
- django_cfg/apps/payments/config/helpers.py +130 -0
- django_cfg/apps/payments/management/__init__.py +1 -3
- django_cfg/apps/payments/management/commands/__init__.py +1 -3
- django_cfg/apps/payments/management/commands/manage_currencies.py +381 -0
- django_cfg/apps/payments/management/commands/manage_providers.py +408 -0
- django_cfg/apps/payments/middleware/__init__.py +3 -1
- django_cfg/apps/payments/middleware/api_access.py +329 -222
- django_cfg/apps/payments/middleware/rate_limiting.py +343 -163
- django_cfg/apps/payments/middleware/usage_tracking.py +250 -238
- django_cfg/apps/payments/migrations/0001_initial.py +708 -536
- django_cfg/apps/payments/models/__init__.py +16 -20
- django_cfg/apps/payments/models/api_keys.py +121 -43
- django_cfg/apps/payments/models/balance.py +150 -115
- django_cfg/apps/payments/models/base.py +68 -15
- django_cfg/apps/payments/models/currencies.py +207 -67
- django_cfg/apps/payments/models/managers/__init__.py +44 -0
- django_cfg/apps/payments/models/managers/api_key_managers.py +329 -0
- django_cfg/apps/payments/models/managers/balance_managers.py +599 -0
- django_cfg/apps/payments/models/managers/currency_managers.py +385 -0
- django_cfg/apps/payments/models/managers/payment_managers.py +511 -0
- django_cfg/apps/payments/models/managers/subscription_managers.py +641 -0
- django_cfg/apps/payments/models/payments.py +235 -284
- django_cfg/apps/payments/models/subscriptions.py +257 -177
- django_cfg/apps/payments/models/tariffs.py +147 -40
- django_cfg/apps/payments/services/__init__.py +209 -56
- django_cfg/apps/payments/services/cache/__init__.py +6 -6
- django_cfg/apps/payments/services/cache/{simple_cache.py → cache_service.py} +112 -12
- django_cfg/apps/payments/services/core/__init__.py +10 -6
- django_cfg/apps/payments/services/core/balance_service.py +435 -360
- django_cfg/apps/payments/services/core/base.py +166 -0
- django_cfg/apps/payments/services/core/currency_service.py +478 -0
- django_cfg/apps/payments/services/core/payment_service.py +344 -468
- django_cfg/apps/payments/services/core/subscription_service.py +425 -484
- django_cfg/apps/payments/services/core/webhook_service.py +410 -0
- django_cfg/apps/payments/services/integrations/__init__.py +29 -0
- django_cfg/apps/payments/services/integrations/ngrok_service.py +47 -0
- django_cfg/apps/payments/services/integrations/providers_config.py +107 -0
- django_cfg/apps/payments/services/providers/__init__.py +9 -14
- django_cfg/apps/payments/services/providers/base.py +232 -71
- django_cfg/apps/payments/services/providers/nowpayments.py +404 -219
- django_cfg/apps/payments/services/providers/registry.py +429 -80
- django_cfg/apps/payments/services/types/__init__.py +78 -0
- django_cfg/apps/payments/services/types/data.py +177 -0
- django_cfg/apps/payments/services/types/requests.py +150 -0
- django_cfg/apps/payments/services/types/responses.py +156 -0
- django_cfg/apps/payments/services/types/webhooks.py +232 -0
- django_cfg/apps/payments/signals/__init__.py +33 -8
- django_cfg/apps/payments/signals/api_key_signals.py +211 -130
- django_cfg/apps/payments/signals/balance_signals.py +174 -0
- django_cfg/apps/payments/signals/payment_signals.py +129 -98
- django_cfg/apps/payments/signals/subscription_signals.py +195 -143
- django_cfg/apps/payments/static/payments/css/components.css +380 -0
- django_cfg/apps/payments/static/payments/css/dashboard.css +188 -0
- django_cfg/apps/payments/static/payments/js/components.js +545 -0
- django_cfg/apps/payments/static/payments/js/utils.js +412 -0
- django_cfg/apps/payments/templatetags/__init__.py +1 -1
- django_cfg/apps/payments/templatetags/payment_tags.py +466 -0
- django_cfg/apps/payments/urls.py +46 -47
- django_cfg/apps/payments/urls_admin.py +49 -0
- django_cfg/apps/payments/views/api/__init__.py +101 -0
- django_cfg/apps/payments/views/api/api_keys.py +387 -0
- django_cfg/apps/payments/views/api/balances.py +381 -0
- django_cfg/apps/payments/views/api/base.py +298 -0
- django_cfg/apps/payments/views/api/currencies.py +402 -0
- django_cfg/apps/payments/views/api/payments.py +415 -0
- django_cfg/apps/payments/views/api/subscriptions.py +475 -0
- django_cfg/apps/payments/views/api/webhooks.py +476 -0
- django_cfg/apps/payments/views/serializers/__init__.py +99 -0
- django_cfg/apps/payments/views/serializers/api_keys.py +424 -0
- django_cfg/apps/payments/views/serializers/balances.py +300 -0
- django_cfg/apps/payments/views/serializers/currencies.py +335 -0
- django_cfg/apps/payments/views/serializers/payments.py +387 -0
- django_cfg/apps/payments/views/serializers/subscriptions.py +429 -0
- django_cfg/apps/payments/views/serializers/webhooks.py +137 -0
- django_cfg/apps/tasks/urls.py +0 -2
- django_cfg/apps/tasks/urls_admin.py +14 -0
- django_cfg/apps/urls.py +4 -4
- django_cfg/config.py +1 -1
- django_cfg/core/config.py +75 -4
- django_cfg/core/generation.py +25 -4
- django_cfg/core/integration/README.md +363 -0
- django_cfg/core/integration/__init__.py +47 -0
- django_cfg/core/integration/commands_collector.py +239 -0
- django_cfg/core/integration/display/__init__.py +15 -0
- django_cfg/core/integration/display/base.py +157 -0
- django_cfg/core/integration/display/ngrok.py +164 -0
- django_cfg/core/integration/display/startup.py +815 -0
- django_cfg/core/integration/url_integration.py +123 -0
- django_cfg/core/integration/version_checker.py +160 -0
- django_cfg/management/commands/auto_generate.py +4 -0
- django_cfg/management/commands/check_settings.py +6 -0
- django_cfg/management/commands/clear_constance.py +5 -2
- django_cfg/management/commands/create_token.py +6 -0
- django_cfg/management/commands/list_urls.py +6 -0
- django_cfg/management/commands/migrate_all.py +6 -0
- django_cfg/management/commands/migrator.py +3 -0
- django_cfg/management/commands/rundramatiq.py +6 -0
- django_cfg/management/commands/runserver_ngrok.py +51 -29
- django_cfg/management/commands/script.py +6 -0
- django_cfg/management/commands/show_config.py +12 -2
- django_cfg/management/commands/show_urls.py +4 -0
- django_cfg/management/commands/superuser.py +6 -0
- django_cfg/management/commands/task_clear.py +4 -1
- django_cfg/management/commands/task_status.py +3 -1
- django_cfg/management/commands/test_email.py +3 -0
- django_cfg/management/commands/test_telegram.py +6 -0
- django_cfg/management/commands/test_twilio.py +6 -0
- django_cfg/management/commands/tree.py +6 -0
- django_cfg/management/commands/validate_config.py +155 -149
- django_cfg/models/constance.py +31 -11
- django_cfg/models/payments.py +175 -498
- django_cfg/modules/django_currency/__init__.py +16 -11
- django_cfg/modules/django_currency/clients/__init__.py +4 -4
- django_cfg/modules/django_currency/clients/coinpaprika_client.py +289 -0
- django_cfg/modules/django_currency/clients/yahoo_client.py +157 -0
- django_cfg/modules/django_currency/core/__init__.py +1 -7
- django_cfg/modules/django_currency/core/converter.py +18 -23
- django_cfg/modules/django_currency/core/models.py +122 -11
- django_cfg/modules/django_currency/database/__init__.py +4 -4
- django_cfg/modules/django_currency/database/database_loader.py +190 -309
- django_cfg/modules/django_logger.py +160 -146
- django_cfg/modules/django_unfold/dashboard.py +65 -12
- django_cfg/registry/core.py +1 -0
- django_cfg/template_archive/django_sample.zip +0 -0
- django_cfg/templates/admin/components/action_grid.html +9 -9
- django_cfg/templates/admin/components/metric_card.html +5 -5
- django_cfg/templates/admin/components/status_badge.html +2 -2
- django_cfg/templates/admin/layouts/dashboard_with_tabs.html +152 -24
- django_cfg/templates/admin/snippets/components/quick_actions.html +3 -3
- django_cfg/templates/admin/snippets/components/system_health.html +1 -1
- django_cfg/templates/admin/snippets/tabs/overview_tab.html +49 -52
- django_cfg/utils/smart_defaults.py +222 -571
- django_cfg/utils/toolkit.py +51 -11
- {django_cfg-1.2.29.dist-info → django_cfg-1.3.1.dist-info}/METADATA +5 -4
- {django_cfg-1.2.29.dist-info → django_cfg-1.3.1.dist-info}/RECORD +172 -182
- django_cfg/apps/payments/__init__.py +0 -8
- django_cfg/apps/payments/admin/tariffs_admin.py +0 -199
- django_cfg/apps/payments/config/module.py +0 -70
- django_cfg/apps/payments/config/providers.py +0 -105
- django_cfg/apps/payments/config/settings.py +0 -96
- django_cfg/apps/payments/config/utils.py +0 -52
- django_cfg/apps/payments/decorators.py +0 -291
- django_cfg/apps/payments/management/commands/README.md +0 -178
- django_cfg/apps/payments/management/commands/currency_stats.py +0 -323
- django_cfg/apps/payments/management/commands/populate_currencies.py +0 -246
- django_cfg/apps/payments/management/commands/update_currencies.py +0 -336
- django_cfg/apps/payments/managers/__init__.py +0 -22
- django_cfg/apps/payments/managers/api_key_manager.py +0 -35
- django_cfg/apps/payments/managers/balance_manager.py +0 -361
- django_cfg/apps/payments/managers/currency_manager.py +0 -83
- django_cfg/apps/payments/managers/payment_manager.py +0 -44
- django_cfg/apps/payments/managers/subscription_manager.py +0 -37
- django_cfg/apps/payments/managers/tariff_manager.py +0 -29
- django_cfg/apps/payments/models/events.py +0 -73
- django_cfg/apps/payments/serializers/__init__.py +0 -56
- django_cfg/apps/payments/serializers/api_keys.py +0 -51
- django_cfg/apps/payments/serializers/balance.py +0 -59
- django_cfg/apps/payments/serializers/currencies.py +0 -55
- django_cfg/apps/payments/serializers/payments.py +0 -62
- django_cfg/apps/payments/serializers/subscriptions.py +0 -71
- django_cfg/apps/payments/serializers/tariffs.py +0 -56
- django_cfg/apps/payments/services/billing/__init__.py +0 -8
- django_cfg/apps/payments/services/cache/base.py +0 -30
- django_cfg/apps/payments/services/core/fallback_service.py +0 -432
- django_cfg/apps/payments/services/internal_types.py +0 -297
- django_cfg/apps/payments/services/middleware/__init__.py +0 -8
- django_cfg/apps/payments/services/monitoring/__init__.py +0 -22
- django_cfg/apps/payments/services/monitoring/api_schemas.py +0 -222
- django_cfg/apps/payments/services/monitoring/provider_health.py +0 -372
- django_cfg/apps/payments/services/providers/cryptapi.py +0 -273
- django_cfg/apps/payments/services/providers/cryptomus.py +0 -311
- django_cfg/apps/payments/services/security/__init__.py +0 -34
- django_cfg/apps/payments/services/security/error_handler.py +0 -637
- django_cfg/apps/payments/services/security/payment_notifications.py +0 -342
- django_cfg/apps/payments/services/security/webhook_validator.py +0 -475
- django_cfg/apps/payments/services/validators/__init__.py +0 -8
- django_cfg/apps/payments/static/payments/css/payments.css +0 -340
- django_cfg/apps/payments/static/payments/js/notifications.js +0 -202
- django_cfg/apps/payments/static/payments/js/payment-utils.js +0 -318
- django_cfg/apps/payments/static/payments/js/theme.js +0 -86
- django_cfg/apps/payments/tasks/__init__.py +0 -12
- django_cfg/apps/payments/tasks/webhook_processing.py +0 -177
- django_cfg/apps/payments/templates/payments/base.html +0 -182
- django_cfg/apps/payments/templates/payments/components/payment_card.html +0 -201
- django_cfg/apps/payments/templates/payments/components/payment_qr_code.html +0 -109
- django_cfg/apps/payments/templates/payments/components/progress_bar.html +0 -36
- django_cfg/apps/payments/templates/payments/components/provider_stats.html +0 -40
- django_cfg/apps/payments/templates/payments/components/status_badge.html +0 -27
- django_cfg/apps/payments/templates/payments/components/status_overview.html +0 -144
- django_cfg/apps/payments/templates/payments/dashboard.html +0 -346
- django_cfg/apps/payments/templatetags/payments_tags.py +0 -315
- django_cfg/apps/payments/urls_templates.py +0 -52
- django_cfg/apps/payments/utils/__init__.py +0 -45
- django_cfg/apps/payments/utils/billing_utils.py +0 -342
- django_cfg/apps/payments/utils/config_utils.py +0 -245
- django_cfg/apps/payments/utils/middleware_utils.py +0 -228
- django_cfg/apps/payments/utils/validation_utils.py +0 -94
- django_cfg/apps/payments/views/__init__.py +0 -62
- django_cfg/apps/payments/views/api_key_views.py +0 -164
- django_cfg/apps/payments/views/balance_views.py +0 -75
- django_cfg/apps/payments/views/currency_views.py +0 -111
- django_cfg/apps/payments/views/payment_views.py +0 -149
- django_cfg/apps/payments/views/subscription_views.py +0 -135
- django_cfg/apps/payments/views/tariff_views.py +0 -131
- django_cfg/apps/payments/views/templates/__init__.py +0 -25
- django_cfg/apps/payments/views/templates/ajax.py +0 -312
- django_cfg/apps/payments/views/templates/base.py +0 -204
- django_cfg/apps/payments/views/templates/dashboard.py +0 -60
- django_cfg/apps/payments/views/templates/payment_detail.py +0 -102
- django_cfg/apps/payments/views/templates/payment_management.py +0 -164
- django_cfg/apps/payments/views/templates/qr_code.py +0 -174
- django_cfg/apps/payments/views/templates/stats.py +0 -240
- django_cfg/apps/payments/views/templates/utils.py +0 -181
- django_cfg/apps/payments/views/webhook_views.py +0 -266
- django_cfg/apps/payments/viewsets.py +0 -65
- django_cfg/core/integration.py +0 -160
- django_cfg/modules/django_currency/clients/coingecko_client.py +0 -257
- django_cfg/modules/django_currency/clients/yfinance_client.py +0 -246
- django_cfg/template_archive/.gitignore +0 -1
- django_cfg/template_archive/__init__.py +0 -0
- django_cfg/urls.py +0 -33
- {django_cfg-1.2.29.dist-info → django_cfg-1.3.1.dist-info}/WHEEL +0 -0
- {django_cfg-1.2.29.dist-info → django_cfg-1.3.1.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.2.29.dist-info → django_cfg-1.3.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,123 @@
|
|
1
|
+
"""
|
2
|
+
Django CFG URL integration utilities.
|
3
|
+
|
4
|
+
Provides automatic URL registration for django_cfg endpoints and integrations.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from typing import List
|
8
|
+
from django.urls import path, include, URLPattern
|
9
|
+
from django_cfg.core.environment import EnvironmentDetector
|
10
|
+
from django.conf import settings
|
11
|
+
|
12
|
+
|
13
|
+
def add_django_cfg_urls(urlpatterns: List[URLPattern], cfg_prefix: str = "cfg/") -> List[URLPattern]:
|
14
|
+
"""
|
15
|
+
Automatically add django_cfg URLs and all integrations to the main URL configuration.
|
16
|
+
|
17
|
+
This function adds:
|
18
|
+
- Django CFG management URLs (cfg/)
|
19
|
+
- Django Revolution URLs (if available)
|
20
|
+
- Startup information display (based on config)
|
21
|
+
|
22
|
+
Args:
|
23
|
+
urlpatterns: Existing URL patterns list
|
24
|
+
cfg_prefix: URL prefix for django_cfg endpoints (default: "cfg/")
|
25
|
+
|
26
|
+
Returns:
|
27
|
+
Updated URL patterns list with all URLs added
|
28
|
+
|
29
|
+
Example:
|
30
|
+
# In your main urls.py
|
31
|
+
from django_cfg import add_django_cfg_urls
|
32
|
+
|
33
|
+
urlpatterns = [
|
34
|
+
path("", home_view, name="home"),
|
35
|
+
path("admin/", admin.site.urls),
|
36
|
+
]
|
37
|
+
|
38
|
+
# Automatically adds:
|
39
|
+
# - path("cfg/", include("django_cfg.apps.urls"))
|
40
|
+
# - Django Revolution URLs (if available)
|
41
|
+
# - Startup info display (based on config.startup_info_mode)
|
42
|
+
urlpatterns = add_django_cfg_urls(urlpatterns)
|
43
|
+
"""
|
44
|
+
# Add django_cfg API URLs
|
45
|
+
new_patterns = urlpatterns + [
|
46
|
+
path(cfg_prefix, include("django_cfg.apps.urls")),
|
47
|
+
]
|
48
|
+
|
49
|
+
# Try to add Django Revolution URLs if available
|
50
|
+
try:
|
51
|
+
from django_revolution import add_revolution_urls
|
52
|
+
new_patterns = add_revolution_urls(new_patterns)
|
53
|
+
except ImportError:
|
54
|
+
# Django Revolution not available - skip
|
55
|
+
pass
|
56
|
+
|
57
|
+
# Show startup info based on config
|
58
|
+
try:
|
59
|
+
from . import print_startup_info
|
60
|
+
print_startup_info()
|
61
|
+
except ImportError:
|
62
|
+
pass
|
63
|
+
|
64
|
+
return new_patterns
|
65
|
+
|
66
|
+
|
67
|
+
def get_django_cfg_urls_info() -> dict:
|
68
|
+
"""
|
69
|
+
Get information about django_cfg URL integration and all integrations.
|
70
|
+
|
71
|
+
Returns:
|
72
|
+
Dictionary with complete URL integration info
|
73
|
+
"""
|
74
|
+
from django_cfg.config import (
|
75
|
+
LIB_NAME,
|
76
|
+
LIB_SITE_URL,
|
77
|
+
LIB_DOCS_URL,
|
78
|
+
LIB_GITHUB_URL,
|
79
|
+
LIB_SUPPORT_URL,
|
80
|
+
LIB_HEALTH_URL,
|
81
|
+
)
|
82
|
+
|
83
|
+
try:
|
84
|
+
from django_cfg import __version__
|
85
|
+
version = __version__
|
86
|
+
except ImportError:
|
87
|
+
version = "unknown"
|
88
|
+
|
89
|
+
# Get current config directly from Pydantic
|
90
|
+
config = None
|
91
|
+
try:
|
92
|
+
from django_cfg.core.config import get_current_config
|
93
|
+
config = get_current_config()
|
94
|
+
except Exception:
|
95
|
+
pass
|
96
|
+
|
97
|
+
|
98
|
+
info = {
|
99
|
+
"django_cfg": {
|
100
|
+
"version": version,
|
101
|
+
"prefix": "cfg/",
|
102
|
+
"description": LIB_NAME,
|
103
|
+
"site_url": LIB_SITE_URL,
|
104
|
+
"docs_url": LIB_DOCS_URL,
|
105
|
+
"github_url": LIB_GITHUB_URL,
|
106
|
+
"support_url": LIB_SUPPORT_URL,
|
107
|
+
"health_url": LIB_HEALTH_URL,
|
108
|
+
"env_mode": config.env_mode if config else "unknown",
|
109
|
+
"debug": config.debug if config else False,
|
110
|
+
"startup_info_mode": config.startup_info_mode if config else "full",
|
111
|
+
}
|
112
|
+
}
|
113
|
+
|
114
|
+
# Add Django Revolution info if available
|
115
|
+
try:
|
116
|
+
from django_revolution import get_revolution_urls_info
|
117
|
+
revolution_info = get_revolution_urls_info()
|
118
|
+
if revolution_info:
|
119
|
+
info["django_revolution"] = revolution_info
|
120
|
+
except ImportError:
|
121
|
+
pass
|
122
|
+
|
123
|
+
return info
|
@@ -0,0 +1,160 @@
|
|
1
|
+
"""
|
2
|
+
Version checker for django-cfg library.
|
3
|
+
|
4
|
+
Checks PyPI for the latest version and caches results for 24 hours using cachetools.
|
5
|
+
"""
|
6
|
+
|
7
|
+
import importlib.metadata
|
8
|
+
import requests
|
9
|
+
from typing import Optional, Dict, Any
|
10
|
+
from cachetools import TTLCache
|
11
|
+
|
12
|
+
|
13
|
+
class VersionChecker:
|
14
|
+
"""
|
15
|
+
Checks for library updates on PyPI with 24-hour caching using cachetools.
|
16
|
+
"""
|
17
|
+
|
18
|
+
# Cache for 24 hours (86400 seconds)
|
19
|
+
CACHE_TTL = 86400
|
20
|
+
|
21
|
+
def __init__(self):
|
22
|
+
"""Initialize version checker with TTL cache."""
|
23
|
+
self._cache = TTLCache(maxsize=10, ttl=self.CACHE_TTL)
|
24
|
+
|
25
|
+
def get_package_name(self) -> str:
|
26
|
+
"""
|
27
|
+
Get package name automatically using importlib.metadata.
|
28
|
+
|
29
|
+
Returns:
|
30
|
+
Package name for PyPI
|
31
|
+
"""
|
32
|
+
try:
|
33
|
+
# Get package metadata
|
34
|
+
metadata = importlib.metadata.metadata('django-cfg')
|
35
|
+
return metadata['Name']
|
36
|
+
except importlib.metadata.PackageNotFoundError:
|
37
|
+
# Fallback to hardcoded name
|
38
|
+
return 'django-cfg'
|
39
|
+
|
40
|
+
def get_latest_version(self) -> Optional[str]:
|
41
|
+
"""
|
42
|
+
Get latest version from PyPI with caching.
|
43
|
+
|
44
|
+
Returns:
|
45
|
+
Latest version string or None if unavailable
|
46
|
+
"""
|
47
|
+
# Check cache first
|
48
|
+
cached_version = self._cache.get('latest_version')
|
49
|
+
if cached_version:
|
50
|
+
return cached_version
|
51
|
+
|
52
|
+
try:
|
53
|
+
package_name = self.get_package_name()
|
54
|
+
url = f"https://pypi.org/pypi/{package_name}/json"
|
55
|
+
|
56
|
+
response = requests.get(url, timeout=5)
|
57
|
+
response.raise_for_status()
|
58
|
+
|
59
|
+
data = response.json()
|
60
|
+
version = data["info"]["version"]
|
61
|
+
|
62
|
+
# Cache the result
|
63
|
+
self._cache['latest_version'] = version
|
64
|
+
|
65
|
+
return version
|
66
|
+
|
67
|
+
except Exception:
|
68
|
+
# Silently fail - version checking is not critical
|
69
|
+
return None
|
70
|
+
|
71
|
+
def get_current_version(self) -> Optional[str]:
|
72
|
+
"""
|
73
|
+
Get current installed version using importlib.metadata.
|
74
|
+
|
75
|
+
Returns:
|
76
|
+
Current version string or None if unavailable
|
77
|
+
"""
|
78
|
+
try:
|
79
|
+
# First try to get from __version__
|
80
|
+
from django_cfg import __version__
|
81
|
+
return __version__
|
82
|
+
except ImportError:
|
83
|
+
try:
|
84
|
+
# Fallback to importlib.metadata
|
85
|
+
return importlib.metadata.version('django-cfg')
|
86
|
+
except importlib.metadata.PackageNotFoundError:
|
87
|
+
return None
|
88
|
+
|
89
|
+
def check_for_updates(self) -> Dict[str, Any]:
|
90
|
+
"""
|
91
|
+
Check if an update is available.
|
92
|
+
|
93
|
+
Returns:
|
94
|
+
Dictionary with update information
|
95
|
+
"""
|
96
|
+
current = self.get_current_version()
|
97
|
+
latest = self.get_latest_version()
|
98
|
+
|
99
|
+
result = {
|
100
|
+
'current_version': current,
|
101
|
+
'latest_version': latest,
|
102
|
+
'update_available': False,
|
103
|
+
'update_url': None,
|
104
|
+
}
|
105
|
+
|
106
|
+
if current and latest and current != latest:
|
107
|
+
# Simple version comparison (assumes semantic versioning)
|
108
|
+
try:
|
109
|
+
current_parts = [int(x) for x in current.split('.')]
|
110
|
+
latest_parts = [int(x) for x in latest.split('.')]
|
111
|
+
|
112
|
+
# Pad shorter version with zeros
|
113
|
+
max_len = max(len(current_parts), len(latest_parts))
|
114
|
+
current_parts.extend([0] * (max_len - len(current_parts)))
|
115
|
+
latest_parts.extend([0] * (max_len - len(latest_parts)))
|
116
|
+
|
117
|
+
if latest_parts > current_parts:
|
118
|
+
result['update_available'] = True
|
119
|
+
package_name = self.get_package_name()
|
120
|
+
result['update_url'] = f"https://pypi.org/project/{package_name}/"
|
121
|
+
|
122
|
+
except (ValueError, AttributeError):
|
123
|
+
# Version comparison failed - skip update check
|
124
|
+
pass
|
125
|
+
|
126
|
+
return result
|
127
|
+
|
128
|
+
|
129
|
+
# Global instance
|
130
|
+
_version_checker = VersionChecker()
|
131
|
+
|
132
|
+
|
133
|
+
def get_version_info() -> Dict[str, Any]:
|
134
|
+
"""
|
135
|
+
Get version information and update status.
|
136
|
+
|
137
|
+
Returns:
|
138
|
+
Dictionary with version and update information
|
139
|
+
"""
|
140
|
+
return _version_checker.check_for_updates()
|
141
|
+
|
142
|
+
|
143
|
+
def get_latest_version() -> Optional[str]:
|
144
|
+
"""
|
145
|
+
Get latest version from PyPI.
|
146
|
+
|
147
|
+
Returns:
|
148
|
+
Latest version string or None if unavailable
|
149
|
+
"""
|
150
|
+
return _version_checker.get_latest_version()
|
151
|
+
|
152
|
+
|
153
|
+
def get_current_version() -> Optional[str]:
|
154
|
+
"""
|
155
|
+
Get current installed version.
|
156
|
+
|
157
|
+
Returns:
|
158
|
+
Current version string or None if unavailable
|
159
|
+
"""
|
160
|
+
return _version_checker.get_current_version()
|
@@ -11,9 +11,12 @@ from django.core.management import call_command
|
|
11
11
|
from django.conf import settings
|
12
12
|
import questionary
|
13
13
|
from datetime import datetime
|
14
|
+
from django_cfg.modules.django_logger import get_logger
|
14
15
|
|
15
16
|
from django_cfg import ConfigToolkit
|
16
17
|
|
18
|
+
logger = get_logger('auto_generate')
|
19
|
+
|
17
20
|
|
18
21
|
class Command(BaseCommand):
|
19
22
|
help = 'Auto-generate configuration files and Django components'
|
@@ -36,6 +39,7 @@ class Command(BaseCommand):
|
|
36
39
|
)
|
37
40
|
|
38
41
|
def handle(self, *args, **options):
|
42
|
+
logger.info("Starting auto_generate command")
|
39
43
|
if options['all']:
|
40
44
|
self.generate_all()
|
41
45
|
elif options['config']:
|
@@ -13,11 +13,16 @@ from django.conf import settings
|
|
13
13
|
from django.core.exceptions import ImproperlyConfigured
|
14
14
|
from django.core.mail import get_connection
|
15
15
|
from datetime import datetime
|
16
|
+
from django_cfg.modules.django_logger import get_logger
|
16
17
|
|
17
18
|
|
19
|
+
|
20
|
+
logger = get_logger('check_settings')
|
21
|
+
|
18
22
|
class Command(BaseCommand):
|
19
23
|
"""Command to check and debug django-cfg settings."""
|
20
24
|
|
25
|
+
|
21
26
|
help = "Check and debug django-cfg configuration settings"
|
22
27
|
|
23
28
|
def add_arguments(self, parser):
|
@@ -34,6 +39,7 @@ class Command(BaseCommand):
|
|
34
39
|
|
35
40
|
def handle(self, *args, **options):
|
36
41
|
"""Main command handler."""
|
42
|
+
logger.info("Starting check_settings command")
|
37
43
|
self.stdout.write(self.style.SUCCESS("\n🔍 Django CFG Settings Checker\n"))
|
38
44
|
|
39
45
|
# Show basic info
|
@@ -6,12 +6,14 @@ Clear Constance configuration cache and database records.
|
|
6
6
|
from django.core.management.base import BaseCommand
|
7
7
|
from django.core.cache import cache
|
8
8
|
from django.conf import settings
|
9
|
-
import
|
9
|
+
from django_cfg.modules.django_logger import get_logger
|
10
|
+
|
10
11
|
|
11
|
-
logger = logging.getLogger(__name__)
|
12
12
|
|
13
13
|
|
14
14
|
class Command(BaseCommand):
|
15
|
+
logger = get_logger('clear_constance')
|
16
|
+
|
15
17
|
help = 'Clear Constance configuration cache and database records'
|
16
18
|
|
17
19
|
def add_arguments(self, parser):
|
@@ -38,6 +40,7 @@ class Command(BaseCommand):
|
|
38
40
|
|
39
41
|
def handle(self, *args, **options):
|
40
42
|
"""Handle the command execution."""
|
43
|
+
self.logger.info("Starting clear_constance command")
|
41
44
|
self.stdout.write(self.style.SUCCESS('🧹 Constance Clear Tool - Django Config Toolkit\n'))
|
42
45
|
|
43
46
|
# Check if constance is installed
|
@@ -12,13 +12,18 @@ from django.contrib.auth import get_user_model
|
|
12
12
|
from django.conf import settings
|
13
13
|
import questionary
|
14
14
|
from datetime import datetime, timedelta
|
15
|
+
from django_cfg.modules.django_logger import get_logger
|
16
|
+
|
15
17
|
|
16
18
|
from django_cfg import ConfigToolkit
|
17
19
|
|
18
20
|
User = get_user_model()
|
19
21
|
|
20
22
|
|
23
|
+
logger = get_logger('create_token')
|
24
|
+
|
21
25
|
class Command(BaseCommand):
|
26
|
+
|
22
27
|
help = 'Create API tokens and authentication tokens'
|
23
28
|
|
24
29
|
def add_arguments(self, parser):
|
@@ -46,6 +51,7 @@ class Command(BaseCommand):
|
|
46
51
|
)
|
47
52
|
|
48
53
|
def handle(self, *args, **options):
|
54
|
+
logger.info("Starting create_token command")
|
49
55
|
if options['user'] and options['type']:
|
50
56
|
self.create_token_for_user(
|
51
57
|
username=options['user'],
|
@@ -9,6 +9,8 @@ import re
|
|
9
9
|
from django.core.management.base import BaseCommand
|
10
10
|
from django.urls import get_resolver
|
11
11
|
from django.conf import settings
|
12
|
+
from django_cfg.modules.django_logger import get_logger
|
13
|
+
|
12
14
|
|
13
15
|
# Rich imports for beautiful output
|
14
16
|
from rich.console import Console
|
@@ -20,8 +22,11 @@ from rich.align import Align
|
|
20
22
|
from django_cfg.core.config import get_current_config
|
21
23
|
|
22
24
|
|
25
|
+
logger = get_logger('list_urls')
|
26
|
+
|
23
27
|
class Command(BaseCommand):
|
24
28
|
"""Command to display all available URLs in the project."""
|
29
|
+
|
25
30
|
help = "Display all available URLs with Rich formatting"
|
26
31
|
|
27
32
|
def __init__(self, *args, **kwargs):
|
@@ -53,6 +58,7 @@ class Command(BaseCommand):
|
|
53
58
|
)
|
54
59
|
|
55
60
|
def handle(self, *args, **options):
|
61
|
+
logger.info("Starting list_urls command")
|
56
62
|
filter_str = options["filter"]
|
57
63
|
webhook_only = options["webhook"]
|
58
64
|
api_only = options["api"]
|
@@ -6,11 +6,16 @@ Migrate all databases based on django-cfg configuration.
|
|
6
6
|
from django.core.management.base import BaseCommand
|
7
7
|
from django.core.management import call_command
|
8
8
|
from django.apps import apps
|
9
|
+
from django_cfg.modules.django_logger import get_logger
|
10
|
+
|
9
11
|
|
10
12
|
from django_cfg.core.config import get_current_config
|
11
13
|
|
12
14
|
|
15
|
+
logger = get_logger('migrate_all')
|
16
|
+
|
13
17
|
class Command(BaseCommand):
|
18
|
+
|
14
19
|
help = "Migrate all databases based on django-cfg configuration"
|
15
20
|
|
16
21
|
def add_arguments(self, parser):
|
@@ -27,6 +32,7 @@ class Command(BaseCommand):
|
|
27
32
|
|
28
33
|
def handle(self, *args, **options):
|
29
34
|
"""Run migrations for all configured databases."""
|
35
|
+
logger.info("Starting migrate_all command")
|
30
36
|
dry_run = options.get("dry_run", False)
|
31
37
|
skip_makemigrations = options.get("skip_makemigrations", False)
|
32
38
|
|
@@ -14,6 +14,9 @@ from django.conf import settings
|
|
14
14
|
import questionary
|
15
15
|
from datetime import datetime
|
16
16
|
from django_cfg.core.config import DEFAULT_APPS
|
17
|
+
from django_cfg.modules.django_logger import get_logger
|
18
|
+
|
19
|
+
logger = get_logger('migrator')
|
17
20
|
|
18
21
|
|
19
22
|
class Command(BaseCommand):
|
@@ -15,6 +15,8 @@ from django.apps import apps
|
|
15
15
|
from django.conf import settings
|
16
16
|
from django.core.management.base import BaseCommand
|
17
17
|
from django.utils.module_loading import module_has_submodule
|
18
|
+
from django_cfg.modules.django_logger import get_logger
|
19
|
+
|
18
20
|
|
19
21
|
from django_cfg.modules.django_tasks import get_task_service
|
20
22
|
|
@@ -24,6 +26,9 @@ NPROCS = multiprocessing.cpu_count()
|
|
24
26
|
NTHREADS = 8
|
25
27
|
|
26
28
|
|
29
|
+
logger = get_logger('rundramatiq')
|
30
|
+
|
31
|
+
|
27
32
|
class Command(BaseCommand):
|
28
33
|
help = "Run Dramatiq workers with Django-CFG configuration."
|
29
34
|
|
@@ -77,6 +82,7 @@ class Command(BaseCommand):
|
|
77
82
|
|
78
83
|
def handle(self, watch_dir, processes, threads, verbosity, queues,
|
79
84
|
pid_file, log_file, worker_shutdown_timeout, dry_run, **options):
|
85
|
+
logger.info("Starting rundramatiq command")
|
80
86
|
|
81
87
|
# Get task service and validate
|
82
88
|
task_service = get_task_service()
|
@@ -5,11 +5,12 @@ Simple implementation following KISS principle.
|
|
5
5
|
"""
|
6
6
|
|
7
7
|
import os
|
8
|
+
import time
|
8
9
|
from django.core.management.commands.runserver import Command as RunServerCommand
|
9
10
|
from django_cfg.modules.django_ngrok import get_ngrok_service
|
10
|
-
import
|
11
|
+
from django_cfg.modules.django_logger import get_logger
|
11
12
|
|
12
|
-
logger =
|
13
|
+
logger = get_logger('runserver_ngrok')
|
13
14
|
|
14
15
|
|
15
16
|
class Command(RunServerCommand):
|
@@ -66,36 +67,61 @@ class Command(RunServerCommand):
|
|
66
67
|
|
67
68
|
# Start ngrok tunnel
|
68
69
|
ngrok_service = get_ngrok_service()
|
70
|
+
|
71
|
+
self.stdout.write("🚇 Starting ngrok tunnel...")
|
72
|
+
logger.info(f"Starting ngrok tunnel for port {server_port}")
|
73
|
+
|
69
74
|
tunnel_url = ngrok_service.start_tunnel(server_port)
|
70
75
|
|
71
76
|
if tunnel_url:
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
f"from ingress url: {tunnel_url}"
|
76
|
-
)
|
77
|
-
)
|
77
|
+
# Wait for tunnel to be fully established
|
78
|
+
self.stdout.write("⏳ Waiting for tunnel to be established...")
|
79
|
+
logger.info("Waiting for ngrok tunnel to be fully established")
|
78
80
|
|
79
|
-
|
80
|
-
|
81
|
+
max_retries = 10
|
82
|
+
retry_count = 0
|
83
|
+
tunnel_ready = False
|
81
84
|
|
82
|
-
|
83
|
-
|
85
|
+
while retry_count < max_retries and not tunnel_ready:
|
86
|
+
time.sleep(1)
|
87
|
+
retry_count += 1
|
88
|
+
|
89
|
+
# Check if tunnel is actually accessible
|
90
|
+
try:
|
91
|
+
current_url = ngrok_service.get_tunnel_url()
|
92
|
+
if current_url and current_url == tunnel_url:
|
93
|
+
tunnel_ready = True
|
94
|
+
logger.info(f"Ngrok tunnel established successfully: {tunnel_url}")
|
95
|
+
break
|
96
|
+
except Exception as e:
|
97
|
+
logger.warning(f"Tunnel check attempt {retry_count} failed: {e}")
|
98
|
+
|
99
|
+
self.stdout.write(f"⏳ Tunnel check {retry_count}/{max_retries}...")
|
84
100
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
101
|
+
if tunnel_ready:
|
102
|
+
# Set environment variables for ngrok URL
|
103
|
+
self._set_ngrok_env_vars(tunnel_url)
|
104
|
+
|
105
|
+
# Update ALLOWED_HOSTS if needed
|
106
|
+
self._update_allowed_hosts(tunnel_url)
|
107
|
+
|
108
|
+
# Update config URLs if enabled
|
109
|
+
ngrok_service.update_config_urls()
|
110
|
+
|
111
|
+
# Brief success message - detailed info will be shown by startup_display
|
112
|
+
self.stdout.write(
|
113
|
+
self.style.SUCCESS(f"✅ Ngrok tunnel ready: {tunnel_url}")
|
114
|
+
)
|
115
|
+
logger.info(f"Ngrok tunnel fully ready: {tunnel_url}")
|
116
|
+
else:
|
117
|
+
self.stdout.write(
|
118
|
+
self.style.WARNING("⚠️ Ngrok tunnel started but may not be fully ready")
|
93
119
|
)
|
94
|
-
|
120
|
+
logger.warning("Ngrok tunnel started but readiness check failed")
|
95
121
|
else:
|
96
|
-
|
97
|
-
|
98
|
-
)
|
122
|
+
error_msg = "Failed to start ngrok tunnel"
|
123
|
+
self.stdout.write(self.style.ERROR(f"❌ {error_msg}"))
|
124
|
+
logger.error(error_msg)
|
99
125
|
|
100
126
|
def _set_ngrok_env_vars(self, tunnel_url: str):
|
101
127
|
"""Set environment variables with ngrok URL for easy access."""
|
@@ -114,11 +140,7 @@ class Command(RunServerCommand):
|
|
114
140
|
# Set API URL (same as tunnel URL for most cases)
|
115
141
|
os.environ['NGROK_API_URL'] = tunnel_url
|
116
142
|
|
117
|
-
|
118
|
-
self.style.HTTP_INFO(
|
119
|
-
f"Environment variables set: NGROK_URL={tunnel_url}"
|
120
|
-
)
|
121
|
-
)
|
143
|
+
# Environment variables set - no need for verbose output
|
122
144
|
logger.info(f"Set ngrok environment variables: {tunnel_url}")
|
123
145
|
|
124
146
|
except Exception as e:
|
@@ -13,11 +13,16 @@ from django.core.management import call_command
|
|
13
13
|
from django.conf import settings
|
14
14
|
import questionary
|
15
15
|
from datetime import datetime
|
16
|
+
from django_cfg.modules.django_logger import get_logger
|
17
|
+
|
16
18
|
|
17
19
|
from django_cfg import ConfigToolkit
|
18
20
|
|
19
21
|
|
22
|
+
logger = get_logger('script')
|
23
|
+
|
20
24
|
class Command(BaseCommand):
|
25
|
+
|
21
26
|
help = 'Run custom scripts and manage Django applications'
|
22
27
|
|
23
28
|
def add_arguments(self, parser):
|
@@ -48,6 +53,7 @@ class Command(BaseCommand):
|
|
48
53
|
)
|
49
54
|
|
50
55
|
def handle(self, *args, **options):
|
56
|
+
logger.info("Starting script command")
|
51
57
|
if options['list']:
|
52
58
|
self.list_scripts()
|
53
59
|
elif options['create']:
|
@@ -10,6 +10,9 @@ import json
|
|
10
10
|
import os
|
11
11
|
from django.core.management.base import BaseCommand
|
12
12
|
from django.conf import settings
|
13
|
+
from django_cfg.modules.django_logger import get_logger
|
14
|
+
|
15
|
+
logger = get_logger('show_config')
|
13
16
|
|
14
17
|
|
15
18
|
class Command(BaseCommand):
|
@@ -30,18 +33,25 @@ class Command(BaseCommand):
|
|
30
33
|
|
31
34
|
def handle(self, *args, **options):
|
32
35
|
"""Show configuration in requested format."""
|
36
|
+
logger.info("Starting show_config command")
|
33
37
|
try:
|
34
38
|
# Get the config instance from Django settings
|
35
39
|
config = self._get_config_instance()
|
40
|
+
logger.info("Successfully retrieved configuration instance")
|
36
41
|
|
37
42
|
if options['format'] == 'json':
|
43
|
+
logger.info("Displaying configuration in JSON format")
|
38
44
|
self._show_json_format(config, options['include_secrets'])
|
39
45
|
else:
|
46
|
+
logger.info("Displaying configuration in table format")
|
40
47
|
self._show_table_format(config, options['include_secrets'])
|
41
48
|
|
49
|
+
logger.info("show_config command completed successfully")
|
42
50
|
except Exception as e:
|
51
|
+
error_msg = f'Failed to show configuration: {e}'
|
52
|
+
logger.error(error_msg, exc_info=True)
|
43
53
|
self.stdout.write(
|
44
|
-
self.style.ERROR(f'❌
|
54
|
+
self.style.ERROR(f'❌ {error_msg}')
|
45
55
|
)
|
46
56
|
|
47
57
|
def _get_config_instance(self):
|
@@ -92,7 +102,7 @@ class Command(BaseCommand):
|
|
92
102
|
env_data = [
|
93
103
|
('Environment', getattr(config, '_environment', 'auto-detected')),
|
94
104
|
('Debug Mode', config.debug),
|
95
|
-
('
|
105
|
+
('Security Domains', ', '.join(config.security_domains) if config.security_domains else 'None'),
|
96
106
|
]
|
97
107
|
|
98
108
|
if include_secrets:
|
@@ -8,6 +8,9 @@ from django.core.management.base import BaseCommand, CommandParser
|
|
8
8
|
from django.urls import get_resolver
|
9
9
|
from django.conf import settings
|
10
10
|
from django.utils.termcolors import make_style
|
11
|
+
from django_cfg.modules.django_logger import get_logger
|
12
|
+
|
13
|
+
logger = get_logger('show_urls')
|
11
14
|
|
12
15
|
|
13
16
|
class Command(BaseCommand):
|
@@ -78,6 +81,7 @@ class Command(BaseCommand):
|
|
78
81
|
|
79
82
|
def handle(self, *args, **options) -> None:
|
80
83
|
"""Main command handler."""
|
84
|
+
logger.info("Starting show_urls command")
|
81
85
|
self.options = options
|
82
86
|
|
83
87
|
# Disable colors if requested
|