django-cfg 1.2.14__py3-none-any.whl → 1.2.15__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/core/config.py +8 -0
- django_cfg/core/generation.py +10 -4
- django_cfg/models/tasks.py +55 -1
- django_cfg/modules/django_tasks.py +41 -3
- {django_cfg-1.2.14.dist-info → django_cfg-1.2.15.dist-info}/METADATA +1 -1
- {django_cfg-1.2.14.dist-info → django_cfg-1.2.15.dist-info}/RECORD +10 -10
- {django_cfg-1.2.14.dist-info → django_cfg-1.2.15.dist-info}/WHEEL +0 -0
- {django_cfg-1.2.14.dist-info → django_cfg-1.2.15.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.2.14.dist-info → django_cfg-1.2.15.dist-info}/licenses/LICENSE +0 -0
django_cfg/__init__.py
CHANGED
django_cfg/core/config.py
CHANGED
@@ -20,6 +20,7 @@ from django_cfg import (
|
|
20
20
|
DatabaseConfig, CacheConfig, EmailConfig, TelegramConfig,
|
21
21
|
UnfoldConfig, DRFConfig, SpectacularConfig, LimitsConfig
|
22
22
|
)
|
23
|
+
from django_cfg.models.tasks import TaskConfig
|
23
24
|
|
24
25
|
# Default apps
|
25
26
|
DEFAULT_APPS = [
|
@@ -244,6 +245,12 @@ class DjangoConfig(BaseModel):
|
|
244
245
|
description="Unfold admin interface configuration",
|
245
246
|
)
|
246
247
|
|
248
|
+
# === Background Task Processing ===
|
249
|
+
tasks: Optional[TaskConfig] = Field(
|
250
|
+
default=None,
|
251
|
+
description="Background task processing configuration (Dramatiq)",
|
252
|
+
)
|
253
|
+
|
247
254
|
# === API Configuration ===
|
248
255
|
# Note: DRF base configuration is handled by django-revolution
|
249
256
|
# These fields provide additional/extended settings on top of Revolution
|
@@ -353,6 +360,7 @@ class DjangoConfig(BaseModel):
|
|
353
360
|
if "default" not in self.databases:
|
354
361
|
raise ConfigurationError("'default' database is required", context={"available_databases": list(self.databases.keys())}, suggestions=["Add a database with alias 'default'"])
|
355
362
|
|
363
|
+
|
356
364
|
# Validate database routing consistency - check migrate_to references
|
357
365
|
referenced_databases = set()
|
358
366
|
for alias, db_config in self.databases.items():
|
django_cfg/core/generation.py
CHANGED
@@ -418,11 +418,17 @@ class SettingsGenerator:
|
|
418
418
|
|
419
419
|
# Check for Tasks/Dramatiq configuration
|
420
420
|
try:
|
421
|
+
from django_cfg.models.tasks import TaskConfig
|
421
422
|
from django_cfg.modules.django_tasks import generate_dramatiq_settings_from_config
|
422
|
-
|
423
|
-
if
|
424
|
-
|
425
|
-
|
423
|
+
|
424
|
+
# Auto-initialize TaskConfig if needed and generate settings
|
425
|
+
task_config = TaskConfig.auto_initialize_if_needed()
|
426
|
+
if task_config is not None:
|
427
|
+
dramatiq_settings = generate_dramatiq_settings_from_config()
|
428
|
+
if dramatiq_settings:
|
429
|
+
settings.update(dramatiq_settings)
|
430
|
+
integrations.append("dramatiq")
|
431
|
+
|
426
432
|
except ImportError as e:
|
427
433
|
logger.warning(f"Failed to import django_tasks module: {e}")
|
428
434
|
except Exception as e:
|
django_cfg/models/tasks.py
CHANGED
@@ -11,6 +11,7 @@ from typing import Optional, List, Literal, Dict, Any
|
|
11
11
|
from enum import Enum
|
12
12
|
import os
|
13
13
|
import logging
|
14
|
+
from django_cfg.models.cfg import BaseCfgAutoModule
|
14
15
|
|
15
16
|
logger = logging.getLogger(__name__)
|
16
17
|
|
@@ -239,7 +240,7 @@ class WorkerConfig(BaseModel):
|
|
239
240
|
)
|
240
241
|
|
241
242
|
|
242
|
-
class TaskConfig(BaseModel):
|
243
|
+
class TaskConfig(BaseModel, BaseCfgAutoModule):
|
243
244
|
"""
|
244
245
|
High-level task system configuration.
|
245
246
|
|
@@ -257,6 +258,12 @@ class TaskConfig(BaseModel):
|
|
257
258
|
description="Task processing backend"
|
258
259
|
)
|
259
260
|
|
261
|
+
def __init__(self, **data):
|
262
|
+
"""Initialize TaskConfig with BaseCfgAutoModule support."""
|
263
|
+
super().__init__(**data)
|
264
|
+
# Initialize _config attribute for BaseCfgAutoModule
|
265
|
+
self._config = None
|
266
|
+
|
260
267
|
# === Backend-Specific Configuration ===
|
261
268
|
dramatiq: DramatiqConfig = Field(
|
262
269
|
default_factory=DramatiqConfig,
|
@@ -371,6 +378,53 @@ class TaskConfig(BaseModel):
|
|
371
378
|
"DRAMATIQ_QUEUES": self.dramatiq.queues,
|
372
379
|
}
|
373
380
|
|
381
|
+
def get_smart_defaults(self):
|
382
|
+
"""Get smart default configuration for this module."""
|
383
|
+
config = self.get_config()
|
384
|
+
debug = getattr(config, 'debug', False) if config else False
|
385
|
+
return get_default_task_config(debug=debug)
|
386
|
+
|
387
|
+
def get_module_config(self):
|
388
|
+
"""Get the final configuration for this module."""
|
389
|
+
return self
|
390
|
+
|
391
|
+
@classmethod
|
392
|
+
def auto_initialize_if_needed(cls) -> Optional['TaskConfig']:
|
393
|
+
"""
|
394
|
+
Auto-initialize TaskConfig if needed based on config flags.
|
395
|
+
|
396
|
+
Returns:
|
397
|
+
TaskConfig instance if should be initialized, None otherwise
|
398
|
+
"""
|
399
|
+
# Get config through BaseCfgModule
|
400
|
+
from django_cfg.modules import BaseCfgModule
|
401
|
+
base_module = BaseCfgModule()
|
402
|
+
config = base_module.get_config()
|
403
|
+
|
404
|
+
if not config:
|
405
|
+
return None
|
406
|
+
|
407
|
+
# Check if TaskConfig already exists
|
408
|
+
if hasattr(config, 'tasks') and config.tasks is not None:
|
409
|
+
# Set config reference and return existing
|
410
|
+
config.tasks.set_config(config)
|
411
|
+
return config.tasks
|
412
|
+
|
413
|
+
# Check if tasks should be enabled
|
414
|
+
if base_module.is_tasks_enabled():
|
415
|
+
# Auto-initialize with smart defaults
|
416
|
+
task_config = cls().get_smart_defaults()
|
417
|
+
task_config.set_config(config)
|
418
|
+
config.tasks = task_config
|
419
|
+
|
420
|
+
import logging
|
421
|
+
logger = logging.getLogger(__name__)
|
422
|
+
logger.info("🚀 Auto-initialized TaskConfig (enabled by knowbase/agents/tasks flags)")
|
423
|
+
|
424
|
+
return task_config
|
425
|
+
|
426
|
+
return None
|
427
|
+
|
374
428
|
|
375
429
|
# === Utility Functions ===
|
376
430
|
|
@@ -9,16 +9,14 @@ from typing import Optional, Dict, Any, List
|
|
9
9
|
import logging
|
10
10
|
from urllib.parse import urlparse
|
11
11
|
|
12
|
-
from
|
12
|
+
from . import BaseCfgModule
|
13
13
|
from django_cfg.models.tasks import TaskConfig, validate_task_config
|
14
14
|
from django_cfg.models.constance import ConstanceField
|
15
15
|
|
16
16
|
# Django imports (will be available when Django is configured)
|
17
17
|
try:
|
18
|
-
from django.conf import settings
|
19
18
|
from django.apps import apps
|
20
19
|
except ImportError:
|
21
|
-
settings = None
|
22
20
|
apps = None
|
23
21
|
|
24
22
|
# Optional imports
|
@@ -426,6 +424,46 @@ def extend_constance_config_with_tasks():
|
|
426
424
|
|
427
425
|
# === Exports ===
|
428
426
|
|
427
|
+
def generate_dramatiq_settings_from_config() -> Optional[Dict[str, Any]]:
|
428
|
+
"""
|
429
|
+
Generate Dramatiq settings from auto-discovered DjangoConfig.
|
430
|
+
|
431
|
+
Returns:
|
432
|
+
Dictionary of Dramatiq settings or None if tasks disabled
|
433
|
+
"""
|
434
|
+
try:
|
435
|
+
# Get config through BaseCfgModule
|
436
|
+
base_module = BaseCfgModule()
|
437
|
+
config = base_module.get_config()
|
438
|
+
|
439
|
+
if not config or not hasattr(config, 'tasks') or not config.tasks or not config.tasks.enabled:
|
440
|
+
return None
|
441
|
+
|
442
|
+
# Get Redis URL from cache config or environment
|
443
|
+
redis_url = None
|
444
|
+
if hasattr(config, 'cache_default') and config.cache_default:
|
445
|
+
redis_url = getattr(config.cache_default, 'redis_url', None)
|
446
|
+
|
447
|
+
if not redis_url:
|
448
|
+
# Fallback to environment or default
|
449
|
+
import os
|
450
|
+
redis_url = os.getenv('REDIS_URL', 'redis://localhost:6379/1')
|
451
|
+
|
452
|
+
# Generate Dramatiq settings
|
453
|
+
dramatiq_settings = config.tasks.get_dramatiq_settings(redis_url)
|
454
|
+
|
455
|
+
# Ensure we only use Redis broker (no RabbitMQ)
|
456
|
+
if 'DRAMATIQ_BROKER' in dramatiq_settings:
|
457
|
+
dramatiq_settings['DRAMATIQ_BROKER']['BROKER'] = 'dramatiq.brokers.redis.RedisBroker'
|
458
|
+
|
459
|
+
logger.info(f"✅ Generated Dramatiq settings with Redis broker and {len(config.tasks.dramatiq.queues)} queues")
|
460
|
+
return dramatiq_settings
|
461
|
+
|
462
|
+
except Exception as e:
|
463
|
+
logger.error(f"Failed to generate Dramatiq settings: {e}")
|
464
|
+
return None
|
465
|
+
|
466
|
+
|
429
467
|
__all__ = [
|
430
468
|
"DjangoTasks",
|
431
469
|
"get_task_service",
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: django-cfg
|
3
|
-
Version: 1.2.
|
3
|
+
Version: 1.2.15
|
4
4
|
Summary: 🚀 Next-gen Django configuration: type-safety, AI features, blazing-fast setup, and automated best practices — all in one.
|
5
5
|
Project-URL: Homepage, https://djangocfg.com
|
6
6
|
Project-URL: Documentation, https://docs.djangocfg.com
|
@@ -1,5 +1,5 @@
|
|
1
1
|
django_cfg/README.md,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
django_cfg/__init__.py,sha256=
|
2
|
+
django_cfg/__init__.py,sha256=WO5eQC0F4xNgcT1pvxC4u4-1_fGdLq1oolFLlGmuRKE,1631
|
3
3
|
django_cfg/apps.py,sha256=k84brkeXJI7EgKZLEpTkM9YFZofKI4PzhFOn1cl9Msc,1656
|
4
4
|
django_cfg/config.py,sha256=0cuRJVEnf03WzvEqhwzLvn9Zi1805C5KG1yk27ekABA,1190
|
5
5
|
django_cfg/urls.py,sha256=bpRFjMonQuk4UCUMxx4ueBX3YDNB7HXKFwEghQ3KR3o,793
|
@@ -285,10 +285,10 @@ django_cfg/cli/commands/__init__.py,sha256=EKLXDAx-QttnGmdjsmVANAfhxWplxl2V_2I0S
|
|
285
285
|
django_cfg/cli/commands/create_project.py,sha256=iuf965j8Yg7zxHcPb0GtFHEj73CYXC45ZJRmd6RbA9E,21025
|
286
286
|
django_cfg/cli/commands/info.py,sha256=o4S1xPJSHv2oEVqmH0X9RTF5f-8Wy9579yHkyd_PC3E,4923
|
287
287
|
django_cfg/core/__init__.py,sha256=eVK57qFOok9kTeHoNEMQ1BplkUOaQ7NB9kP9eQK1vg0,358
|
288
|
-
django_cfg/core/config.py,sha256=
|
288
|
+
django_cfg/core/config.py,sha256=y0rvqiO5l_MMqDhQCiyA9c3GHYJlJwRpdOgvN_MfcWU,26536
|
289
289
|
django_cfg/core/environment.py,sha256=MAoEPqIPsLVhSANT2Bz4nnus2wmbMW0RCOQxhQfDrDc,9106
|
290
290
|
django_cfg/core/exceptions.py,sha256=RTQEoU3PfR8lqqNNv5ayd_HY2yJLs3eioqUy8VM6AG4,10378
|
291
|
-
django_cfg/core/generation.py,sha256=
|
291
|
+
django_cfg/core/generation.py,sha256=zSVb3VIv588wzqSF1-wxOb15CW5hX2tf9fq_FRXSOzk,24990
|
292
292
|
django_cfg/core/integration.py,sha256=5kzkZSd45ij0rfrBdeNUYnDalObqvK__XpoP31xFYKo,5224
|
293
293
|
django_cfg/core/validation.py,sha256=PhwDBTs24nuM3xqfIT3hXmN88VrhMT-Bk8Yb8FxjmPk,6590
|
294
294
|
django_cfg/management/__init__.py,sha256=NrLAhiS59hqjy-bipOC1abNuRiNm5BpKXmjN05VzKbM,28
|
@@ -337,14 +337,14 @@ django_cfg/models/ngrok.py,sha256=MVgcKWx0DRSW0QcwhiSx2vVwTSG49vbVrzPkZqDK-zw,35
|
|
337
337
|
django_cfg/models/revolution.py,sha256=gaAhdicd1ji-XiJPqUFQaUmDcgfwFHofSYS3JtLcz4A,7540
|
338
338
|
django_cfg/models/security.py,sha256=Xv19ZVOIenB_-f0wB6fm-Ap4j9kA43bSFaT2XenpSqc,4685
|
339
339
|
django_cfg/models/services.py,sha256=fj9JjrJFrlL4DMnMbx_D8JiiZpz4E5uBqmhquAxau7c,13159
|
340
|
-
django_cfg/models/tasks.py,sha256=
|
340
|
+
django_cfg/models/tasks.py,sha256=G06kEMaJ9mZhW525y-r33q4rHswAwnvPgMt7lpbgiak,15526
|
341
341
|
django_cfg/modules/__init__.py,sha256=Ip9WMpzImEwIAywpFwU056_v0O9oIGG7nCT1YSArxkw,316
|
342
342
|
django_cfg/modules/base.py,sha256=ALlsylzO1rYsrLNwL3MhEK_dqYSZV0BBZAObR6wlGEA,5343
|
343
343
|
django_cfg/modules/django_email.py,sha256=2XXlIKzD6Jao3CT4_zIE2eaM9Cc9ROA1tjp2bJ9z5Lo,16592
|
344
344
|
django_cfg/modules/django_health.py,sha256=7QzuQ6WyjWYj6lecd4auwRvEyrMUL7N6hiAp-tLyoY4,8923
|
345
345
|
django_cfg/modules/django_logger.py,sha256=3oP9jev0lOcFUJ1tYcpbFnK524zIGA2xIOrrAiTwpb8,6331
|
346
346
|
django_cfg/modules/django_ngrok.py,sha256=LjlAIJprbFhFYwDG93acas8XaB6iFQGu4fWvZiDNhyQ,10482
|
347
|
-
django_cfg/modules/django_tasks.py,sha256=
|
347
|
+
django_cfg/modules/django_tasks.py,sha256=SBas2juL6RfDL7ttm4xAxJ7bvS052WmUzixNHPlzJVo,17328
|
348
348
|
django_cfg/modules/django_telegram.py,sha256=qz3EOJnCR_YTJVIu2-Iq8--cla6mU-WPohquQ26eHDQ,16367
|
349
349
|
django_cfg/modules/dramatiq_setup.py,sha256=Jke4aO_L1t6F3OAc4pl12zppKzL0gb1p6ilfQ3zUIZ8,454
|
350
350
|
django_cfg/modules/logger.py,sha256=4_zeasNehr8LGz8r_ckv15-fQS63zCodiqD4CYIEyFI,10546
|
@@ -464,8 +464,8 @@ django_cfg/utils/path_resolution.py,sha256=C9As6p4Q9l3VeoVkFDRPQWGrzAWf8O8UxLVka
|
|
464
464
|
django_cfg/utils/smart_defaults.py,sha256=b6A1z7VO1NJGq0oUQXN5P97c3k_Ssgw6qUi0mK-4TlM,19786
|
465
465
|
django_cfg/utils/toolkit.py,sha256=Td8_iXNaftonF_xdZP4Y3uO65nuA_4_zditn5Q_Pfcw,23310
|
466
466
|
django_cfg/utils/version_check.py,sha256=jI4v3YMdQriUEeb_TvRl511sDghy6I75iKRDUaNpucs,4800
|
467
|
-
django_cfg-1.2.
|
468
|
-
django_cfg-1.2.
|
469
|
-
django_cfg-1.2.
|
470
|
-
django_cfg-1.2.
|
471
|
-
django_cfg-1.2.
|
467
|
+
django_cfg-1.2.15.dist-info/METADATA,sha256=QcWw3jNJ4GU7JwFC9Ya3UdOT-9UFo2Au_7XeCUT3KLE,36406
|
468
|
+
django_cfg-1.2.15.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
469
|
+
django_cfg-1.2.15.dist-info/entry_points.txt,sha256=Ucmde4Z2wEzgb4AggxxZ0zaYDb9HpyE5blM3uJ0_VNg,56
|
470
|
+
django_cfg-1.2.15.dist-info/licenses/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
|
471
|
+
django_cfg-1.2.15.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|