django-cfg 1.1.55__py3-none-any.whl → 1.1.58__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 CHANGED
@@ -38,7 +38,7 @@ default_app_config = "django_cfg.apps.DjangoCfgConfig"
38
38
  from typing import TYPE_CHECKING
39
39
 
40
40
  # Version information
41
- __version__ = "1.1.55"
41
+ __version__ = "1.1.58"
42
42
  __author__ = "Unrealos Team"
43
43
  __email__ = "info@unrealos.com"
44
44
  __license__ = "MIT"
@@ -192,9 +192,7 @@ class SettingsGenerator:
192
192
  for alias, db_config in config.databases.items():
193
193
  if db_config.has_routing_rules():
194
194
  for app in db_config.apps:
195
- # Extract app_label from full path (e.g., "apps.knowbase" -> "knowbase")
196
- app_label = app.split('.')[-1] if '.' in app else app
197
- routing_rules[app_label] = alias
195
+ routing_rules[app] = alias
198
196
 
199
197
  if routing_rules:
200
198
  settings["DATABASE_ROUTERS"] = ["django_cfg.routers.DatabaseRouter"]
@@ -143,8 +143,7 @@ class Command(BaseCommand):
143
143
  if options.get("pid_file"):
144
144
  args.extend(["--pid-file", options["pid_file"]])
145
145
 
146
- # Add broker (required positional argument)
147
- args.append("django_dramatiq.setup")
146
+ # Note: Using Python API instead of CLI, so no broker argument needed
148
147
 
149
148
  # Add discovered task modules
150
149
  discovered_modules = get_task_service().discover_tasks()
@@ -184,7 +183,7 @@ class Command(BaseCommand):
184
183
  self.stdout.write(f" {' '.join(worker_args)}")
185
184
 
186
185
  def _start_workers(self, worker_args, options):
187
- """Start Dramatiq workers."""
186
+ """Start Dramatiq workers using Python API instead of CLI."""
188
187
  self.stdout.write(
189
188
  self.style.SUCCESS("Starting Dramatiq workers...")
190
189
  )
@@ -193,9 +192,15 @@ class Command(BaseCommand):
193
192
  task_service = get_task_service()
194
193
  config = task_service.config
195
194
 
196
- self.stdout.write(f"Processes: {config.get_effective_processes()}")
197
- self.stdout.write(f"Threads: {config.dramatiq.threads}")
198
- self.stdout.write(f"Queues: {', '.join(config.get_effective_queues())}")
195
+ processes = options.get("processes") or config.get_effective_processes()
196
+ threads = options.get("threads") or config.dramatiq.threads
197
+ queues = config.get_effective_queues()
198
+ if options.get("queues"):
199
+ queues = [q.strip() for q in options["queues"].split(",")]
200
+
201
+ self.stdout.write(f"Processes: {processes}")
202
+ self.stdout.write(f"Threads: {threads}")
203
+ self.stdout.write(f"Queues: {', '.join(queues)}")
199
204
 
200
205
  # Write PID file if requested
201
206
  if options.get("pid_file"):
@@ -204,20 +209,26 @@ class Command(BaseCommand):
204
209
  self.stdout.write(f"PID written to: {options['pid_file']}")
205
210
 
206
211
  try:
207
- # Import and run dramatiq
212
+ # Import dramatiq and get broker
208
213
  import dramatiq
209
- from dramatiq.cli import main as dramatiq_main
214
+ from dramatiq.worker import Worker
215
+ from django_cfg.modules.django_tasks import get_dramatiq_broker
216
+
217
+ # Get the configured broker
218
+ broker = get_dramatiq_broker()
210
219
 
211
- # Replace sys.argv with our arguments
212
- original_argv = sys.argv[:]
213
- sys.argv = worker_args
220
+ # Discover and import task modules
221
+ discovered_modules = get_task_service().discover_tasks()
222
+ for module_name in discovered_modules:
223
+ try:
224
+ __import__(module_name)
225
+ self.stdout.write(f"Loaded tasks from: {module_name}")
226
+ except ImportError as e:
227
+ self.stdout.write(f"Warning: Could not import {module_name}: {e}")
214
228
 
215
- try:
216
- # Run dramatiq CLI
217
- dramatiq_main()
218
- finally:
219
- # Restore original argv
220
- sys.argv = original_argv
229
+ # Create and start worker
230
+ worker = Worker(broker, worker_timeout=600000)
231
+ worker.start()
221
232
 
222
233
  except KeyboardInterrupt:
223
234
  self.stdout.write("\nShutting down workers...")
@@ -712,6 +712,72 @@ def extend_constance_config_with_tasks():
712
712
  return []
713
713
 
714
714
 
715
+ # === Broker Creation ===
716
+
717
+ def create_dramatiq_broker():
718
+ """
719
+ Create and configure Dramatiq broker from Django settings.
720
+
721
+ This function creates a broker instance that can be used directly
722
+ by the Dramatiq CLI without requiring a separate broker.py file.
723
+
724
+ Returns:
725
+ dramatiq.Broker: Configured Dramatiq broker instance
726
+ """
727
+ try:
728
+ from django.conf import settings
729
+
730
+ if not hasattr(settings, 'DRAMATIQ_BROKER'):
731
+ raise RuntimeError("DRAMATIQ_BROKER not configured in Django settings")
732
+
733
+ broker_config = settings.DRAMATIQ_BROKER
734
+
735
+ # Create broker from Django settings
736
+ broker = RedisBroker(**broker_config['OPTIONS'])
737
+
738
+ # Add middleware (only if not already present)
739
+ existing_middleware_types = {type(mw).__name__ for mw in broker.middleware}
740
+
741
+ for middleware_path in broker_config['MIDDLEWARE']:
742
+ try:
743
+ module_path, class_name = middleware_path.rsplit('.', 1)
744
+
745
+ # Skip if middleware of this type already exists
746
+ if class_name in existing_middleware_types:
747
+ continue
748
+
749
+ module = __import__(module_path, fromlist=[class_name])
750
+ middleware_class = getattr(module, class_name)
751
+ broker.add_middleware(middleware_class())
752
+ except Exception as e:
753
+ logger.warning(f"Failed to add middleware {middleware_path}: {e}")
754
+
755
+ return broker
756
+
757
+ except Exception as e:
758
+ logger.error(f"Failed to create Dramatiq broker: {e}")
759
+ raise
760
+
761
+
762
+ # Global broker instance (lazy-loaded)
763
+ _broker_instance = None
764
+
765
+
766
+ def get_dramatiq_broker():
767
+ """
768
+ Get the global Dramatiq broker instance.
769
+
770
+ Returns:
771
+ dramatiq.Broker: The singleton broker instance
772
+ """
773
+ global _broker_instance
774
+
775
+ if _broker_instance is None:
776
+ _broker_instance = create_dramatiq_broker()
777
+
778
+ return _broker_instance
779
+
780
+
715
781
  # === Exports ===
716
782
 
717
783
  __all__ = [
@@ -725,4 +791,6 @@ __all__ = [
725
791
  "extend_constance_config_with_tasks",
726
792
  "initialize_task_system",
727
793
  "clear_dramatiq_queues",
794
+ "create_dramatiq_broker",
795
+ "get_dramatiq_broker",
728
796
  ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-cfg
3
- Version: 1.1.55
3
+ Version: 1.1.58
4
4
  Summary: 🚀 Production-ready Django configuration framework with type-safe settings, smart automation, and modern developer experience
5
5
  Project-URL: Homepage, https://github.com/markolofsen/django-cfg
6
6
  Project-URL: Documentation, https://django-cfg.readthedocs.io
@@ -1,4 +1,4 @@
1
- django_cfg/__init__.py,sha256=ZTcmv4CICkfINCwJpvyAB07eMvcwno-wz_5ySOgJ6QM,14288
1
+ django_cfg/__init__.py,sha256=PGJQnkUVjXVdcLHsEFKEd5OA6phVKID_9p6ju6HFK0Y,14288
2
2
  django_cfg/apps.py,sha256=k84brkeXJI7EgKZLEpTkM9YFZofKI4PzhFOn1cl9Msc,1656
3
3
  django_cfg/exceptions.py,sha256=RTQEoU3PfR8lqqNNv5ayd_HY2yJLs3eioqUy8VM6AG4,10378
4
4
  django_cfg/integration.py,sha256=-7hvd-4ohLdzH4eufCZTOe3yTzPoQyB_HCfvsSm9AAw,5218
@@ -146,7 +146,7 @@ django_cfg/cli/commands/info.py,sha256=tLZmiZX2nEpwrcN9cUwrGKb95X7dasuoeePrqTmK2
146
146
  django_cfg/core/__init__.py,sha256=eVK57qFOok9kTeHoNEMQ1BplkUOaQ7NB9kP9eQK1vg0,358
147
147
  django_cfg/core/config.py,sha256=EO6l39BncNRnvxkWHqyGNAiP-rhoAfwtBtr_UmWLYL8,27799
148
148
  django_cfg/core/environment.py,sha256=AXNKVxcV_3_3gtlafDx3wFTnTPPMGQ9gl40vYm2w-Hg,9101
149
- django_cfg/core/generation.py,sha256=zClvEA0Qq_uMaIJ-2TjacdgldHH9KwNoKRMKSjJV2o0,24849
149
+ django_cfg/core/generation.py,sha256=z4yDoYM-_q6RGIn4ZesLXS8frcHoiHz5oBIREcJON4U,24668
150
150
  django_cfg/core/validation.py,sha256=j0q57oJEJjI6ylb3AzvsgupmvBKsUcrxpmkfKF3ZRF4,6585
151
151
  django_cfg/management/__init__.py,sha256=z8p1jlyajNUleDxRUXL3iXUI99xXWFYNtFAe5nKy1kA,43
152
152
  django_cfg/management/commands/__init__.py,sha256=z8p1jlyajNUleDxRUXL3iXUI99xXWFYNtFAe5nKy1kA,43
@@ -156,7 +156,7 @@ django_cfg/management/commands/create_token.py,sha256=beHtUTuyFZhG97F9vSkaX-u7ti
156
156
  django_cfg/management/commands/generate.py,sha256=w0BF7IMftxNjxTxFuY8cw5pNKGW-LmTScJ8kZpxHu_8,4248
157
157
  django_cfg/management/commands/list_urls.py,sha256=D8ikInA3uE1LbQGLWmfdLnEqPg7wqrI3caQA6iTe_-0,11009
158
158
  django_cfg/management/commands/migrator.py,sha256=mhMM63uv_Jp9zHVVM7TMwCB90uv3iFZn1vOG-rXyi3s,16191
159
- django_cfg/management/commands/rundramatiq.py,sha256=7NkMEBHcSd4K4UT-j135GNNc8r8m7QojMgqgmjyEej4,8092
159
+ django_cfg/management/commands/rundramatiq.py,sha256=6FnSNonO0SAuvANNXm7VOgVqtZvyRMfW8epTd9Jj9Js,8768
160
160
  django_cfg/management/commands/runserver_ngrok.py,sha256=mcTioDIzHgha6sGo5eazlJhdKr8y5-uEQIc3qG3AvCI,5237
161
161
  django_cfg/management/commands/script.py,sha256=I6zOEQEGaED0HoLxl2EqKz39HwbKg9HhdxnGKybfH5s,16974
162
162
  django_cfg/management/commands/show_config.py,sha256=0YJ99P1XvymT3fWritaNmn_HJ-PVb0I-yBy757M_bn8,8337
@@ -189,7 +189,7 @@ django_cfg/modules/base.py,sha256=X90X-0iBfnaUSaC7S8_ULa_rdT41tqTVJnT05_RuyK4,47
189
189
  django_cfg/modules/django_email.py,sha256=uBvvqRVe1DG73Qq2d2IBYTjhFRdvHgsIbkVw3ge9OW8,16586
190
190
  django_cfg/modules/django_logger.py,sha256=VfcPCurTdU3iI593EJNs3wUoWQowu7-ykJGuHNkE79M,6325
191
191
  django_cfg/modules/django_ngrok.py,sha256=OAvir2pBFHfko-XaVgZTjeJwyZw-NSEILaKNlqQziqA,10476
192
- django_cfg/modules/django_tasks.py,sha256=Zn69ewpj_3xZZxeI6sVrQMrAKf4fxtI4ME6bQo5KEmY,26531
192
+ django_cfg/modules/django_tasks.py,sha256=sOSQx7Wr61_I04QzAKF0Hz_kc7fgps6hSxBCvLt3R0I,28647
193
193
  django_cfg/modules/django_telegram.py,sha256=Mun2tAm0P2cUyQlAs8FaPe-FVgcrv7L_-FPTXQQEUT0,16356
194
194
  django_cfg/modules/logger.py,sha256=4_zeasNehr8LGz8r_ckv15-fQS63zCodiqD4CYIEyFI,10546
195
195
  django_cfg/modules/django_currency/README.md,sha256=Ox3jgRtsbOIaMuYDkIhrs9ijLGLbn-2R7mD9n2tjAVE,8512
@@ -251,8 +251,8 @@ django_cfg/templates/emails/base_email.html,sha256=TWcvYa2IHShlF_E8jf1bWZStRO0v8
251
251
  django_cfg/utils/__init__.py,sha256=64wwXJuXytvwt8Ze_erSR2HmV07nGWJ6DV5wloRBvYE,435
252
252
  django_cfg/utils/path_resolution.py,sha256=eML-6-RIGTs5TePktIQN8nxfDUEFJ3JA0AzWBcihAbs,13894
253
253
  django_cfg/utils/smart_defaults.py,sha256=iL6_n3jGDW5812whylWAwXik0xBSYihdLp4IJ26T5eA,20547
254
- django_cfg-1.1.55.dist-info/METADATA,sha256=yjqg7Vz6T_N9tMe_gdeqTzxEV7jo-vZH8nKbH4eHies,38953
255
- django_cfg-1.1.55.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
256
- django_cfg-1.1.55.dist-info/entry_points.txt,sha256=Ucmde4Z2wEzgb4AggxxZ0zaYDb9HpyE5blM3uJ0_VNg,56
257
- django_cfg-1.1.55.dist-info/licenses/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
258
- django_cfg-1.1.55.dist-info/RECORD,,
254
+ django_cfg-1.1.58.dist-info/METADATA,sha256=pVR_L4eFV_gfOVrsanwBT6YbUS7A82DJFV0FuhRIvIk,38953
255
+ django_cfg-1.1.58.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
256
+ django_cfg-1.1.58.dist-info/entry_points.txt,sha256=Ucmde4Z2wEzgb4AggxxZ0zaYDb9HpyE5blM3uJ0_VNg,56
257
+ django_cfg-1.1.58.dist-info/licenses/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
258
+ django_cfg-1.1.58.dist-info/RECORD,,