django-cfg 1.1.56__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.56"
41
+ __version__ = "1.1.58"
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,26 @@ 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
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()
211
219
 
212
- # Replace sys.argv with our arguments
213
- original_argv = sys.argv[:]
214
- 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}")
215
228
 
216
- try:
217
- # Run dramatiq CLI
218
- dramatiq_main()
219
- finally:
220
- # Restore original argv
221
- sys.argv = original_argv
229
+ # Create and start worker
230
+ worker = Worker(broker, worker_timeout=600000)
231
+ worker.start()
222
232
 
223
233
  except KeyboardInterrupt:
224
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.56
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=QfEcj-OA9Y8t400zz0Bdm2xffpmYAB0qeg8B5_pemUI,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
@@ -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=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.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.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,,