django-cfg 1.1.56__py3-none-any.whl → 1.1.59__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.56"
41
+ __version__ = "1.1.59"
42
42
  __author__ = "Unrealos Team"
43
43
  __email__ = "info@unrealos.com"
44
44
  __license__ = "MIT"
@@ -143,9 +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 - must be first after options)
147
- # Use our custom broker module
148
- args.append("broker")
146
+ # Note: Using Python API instead of CLI, so no broker argument needed
149
147
 
150
148
  # Add discovered task modules
151
149
  discovered_modules = get_task_service().discover_tasks()
@@ -185,7 +183,7 @@ class Command(BaseCommand):
185
183
  self.stdout.write(f" {' '.join(worker_args)}")
186
184
 
187
185
  def _start_workers(self, worker_args, options):
188
- """Start Dramatiq workers."""
186
+ """Start Dramatiq workers using Python API instead of CLI."""
189
187
  self.stdout.write(
190
188
  self.style.SUCCESS("Starting Dramatiq workers...")
191
189
  )
@@ -194,9 +192,15 @@ class Command(BaseCommand):
194
192
  task_service = get_task_service()
195
193
  config = task_service.config
196
194
 
197
- self.stdout.write(f"Processes: {config.get_effective_processes()}")
198
- self.stdout.write(f"Threads: {config.dramatiq.threads}")
199
- 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)}")
200
204
 
201
205
  # Write PID file if requested
202
206
  if options.get("pid_file"):
@@ -205,20 +209,33 @@ class Command(BaseCommand):
205
209
  self.stdout.write(f"PID written to: {options['pid_file']}")
206
210
 
207
211
  try:
208
- # Import and run dramatiq
212
+ # Import dramatiq and get broker FIRST
209
213
  import dramatiq
210
- 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()
219
+
220
+ # CRITICAL: Set the broker as the global default BEFORE importing tasks
221
+ dramatiq.set_broker(broker)
222
+
223
+ # Now discover and import task modules with the correct broker set
224
+ discovered_modules = get_task_service().discover_tasks()
225
+ for module_name in discovered_modules:
226
+ try:
227
+ __import__(module_name)
228
+ self.stdout.write(f"Loaded tasks from: {module_name}")
229
+ except ImportError as e:
230
+ self.stdout.write(f"Warning: Could not import {module_name}: {e}")
211
231
 
212
- # Replace sys.argv with our arguments
213
- original_argv = sys.argv[:]
214
- sys.argv = worker_args
232
+ # Verify broker is set correctly
233
+ current_broker = dramatiq.get_broker()
234
+ self.stdout.write(f"Using broker: {current_broker}")
215
235
 
216
- try:
217
- # Run dramatiq CLI
218
- dramatiq_main()
219
- finally:
220
- # Restore original argv
221
- sys.argv = original_argv
236
+ # Create and start worker
237
+ worker = Worker(broker, worker_timeout=600000)
238
+ worker.start()
222
239
 
223
240
  except KeyboardInterrupt:
224
241
  self.stdout.write("\nShutting down workers...")
@@ -681,6 +681,16 @@ def initialize_task_system():
681
681
 
682
682
  if config and config.enabled:
683
683
  logger.info("🔧 Initializing Django-CFG task system...")
684
+
685
+ # CRITICAL: Set up global broker for task sending
686
+ try:
687
+ import dramatiq
688
+ broker = get_dramatiq_broker()
689
+ dramatiq.set_broker(broker)
690
+ logger.debug(f"Set global Dramatiq broker: {broker}")
691
+ except Exception as e:
692
+ logger.warning(f"Failed to set global broker: {e}")
693
+
684
694
  logger.info("✅ Task system initialized successfully")
685
695
  logger.info("💡 To start workers, run: python manage.py rundramatiq")
686
696
  else:
@@ -712,6 +722,72 @@ def extend_constance_config_with_tasks():
712
722
  return []
713
723
 
714
724
 
725
+ # === Broker Creation ===
726
+
727
+ def create_dramatiq_broker():
728
+ """
729
+ Create and configure Dramatiq broker from Django settings.
730
+
731
+ This function creates a broker instance that can be used directly
732
+ by the Dramatiq CLI without requiring a separate broker.py file.
733
+
734
+ Returns:
735
+ dramatiq.Broker: Configured Dramatiq broker instance
736
+ """
737
+ try:
738
+ from django.conf import settings
739
+
740
+ if not hasattr(settings, 'DRAMATIQ_BROKER'):
741
+ raise RuntimeError("DRAMATIQ_BROKER not configured in Django settings")
742
+
743
+ broker_config = settings.DRAMATIQ_BROKER
744
+
745
+ # Create broker from Django settings
746
+ broker = RedisBroker(**broker_config['OPTIONS'])
747
+
748
+ # Add middleware (only if not already present)
749
+ existing_middleware_types = {type(mw).__name__ for mw in broker.middleware}
750
+
751
+ for middleware_path in broker_config['MIDDLEWARE']:
752
+ try:
753
+ module_path, class_name = middleware_path.rsplit('.', 1)
754
+
755
+ # Skip if middleware of this type already exists
756
+ if class_name in existing_middleware_types:
757
+ continue
758
+
759
+ module = __import__(module_path, fromlist=[class_name])
760
+ middleware_class = getattr(module, class_name)
761
+ broker.add_middleware(middleware_class())
762
+ except Exception as e:
763
+ logger.warning(f"Failed to add middleware {middleware_path}: {e}")
764
+
765
+ return broker
766
+
767
+ except Exception as e:
768
+ logger.error(f"Failed to create Dramatiq broker: {e}")
769
+ raise
770
+
771
+
772
+ # Global broker instance (lazy-loaded)
773
+ _broker_instance = None
774
+
775
+
776
+ def get_dramatiq_broker():
777
+ """
778
+ Get the global Dramatiq broker instance.
779
+
780
+ Returns:
781
+ dramatiq.Broker: The singleton broker instance
782
+ """
783
+ global _broker_instance
784
+
785
+ if _broker_instance is None:
786
+ _broker_instance = create_dramatiq_broker()
787
+
788
+ return _broker_instance
789
+
790
+
715
791
  # === Exports ===
716
792
 
717
793
  __all__ = [
@@ -725,4 +801,6 @@ __all__ = [
725
801
  "extend_constance_config_with_tasks",
726
802
  "initialize_task_system",
727
803
  "clear_dramatiq_queues",
804
+ "create_dramatiq_broker",
805
+ "get_dramatiq_broker",
728
806
  ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-cfg
3
- Version: 1.1.56
3
+ Version: 1.1.59
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=QfEcj-OA9Y8t400zz0Bdm2xffpmYAB0qeg8B5_pemUI,14288
1
+ django_cfg/__init__.py,sha256=9_vseCVwoJ7CXG8_EjpsdPmqrw021qouoH-wvSSGNwA,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
@@ -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=NbzpwvqimrxuCbXVfNb3DJq4v0QPpYQNcRNVOfAyTOI,8146
159
+ django_cfg/management/commands/rundramatiq.py,sha256=y9LYzko8ppZw_nQZPIIQ3v5-gqxFz6U0Yx35eQzc5Ag,9117
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=qulUuE76sgTykHLaBp6k9A29ULHnp-lUNdsZfNBFZC0,29048
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.56.dist-info/METADATA,sha256=0QKfOqPQDlVxMFbHyQu0zG1KvDiGFAuug4CmJKF3smg,38953
255
- django_cfg-1.1.56.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
256
- django_cfg-1.1.56.dist-info/entry_points.txt,sha256=Ucmde4Z2wEzgb4AggxxZ0zaYDb9HpyE5blM3uJ0_VNg,56
257
- django_cfg-1.1.56.dist-info/licenses/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
258
- django_cfg-1.1.56.dist-info/RECORD,,
254
+ django_cfg-1.1.59.dist-info/METADATA,sha256=fhstTU5UCjrxQMKM692CCMivv-FNyiZleZBBPkQTyKw,38953
255
+ django_cfg-1.1.59.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
256
+ django_cfg-1.1.59.dist-info/entry_points.txt,sha256=Ucmde4Z2wEzgb4AggxxZ0zaYDb9HpyE5blM3uJ0_VNg,56
257
+ django_cfg-1.1.59.dist-info/licenses/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
258
+ django_cfg-1.1.59.dist-info/RECORD,,