django-cfg 1.4.107__py3-none-any.whl → 1.4.109__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.

Potentially problematic release.


This version of django-cfg might be problematic. Click here for more details.

Files changed (140) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/apps/accounts/views/profile.py +19 -9
  3. django_cfg/apps/centrifugo/views/admin_api.py +4 -7
  4. django_cfg/apps/centrifugo/views/monitoring.py +3 -6
  5. django_cfg/apps/centrifugo/views/testing_api.py +3 -6
  6. django_cfg/apps/dashboard/services/system_health_service.py +16 -11
  7. django_cfg/apps/dashboard/views/activity_views.py +3 -5
  8. django_cfg/apps/dashboard/views/apizones_views.py +4 -5
  9. django_cfg/apps/dashboard/views/charts_views.py +4 -5
  10. django_cfg/apps/dashboard/views/overview_views.py +4 -5
  11. django_cfg/apps/dashboard/views/statistics_views.py +4 -5
  12. django_cfg/apps/dashboard/views/system_views.py +4 -5
  13. django_cfg/apps/knowbase/__init__.py +2 -2
  14. django_cfg/apps/knowbase/apps.py +2 -8
  15. django_cfg/apps/knowbase/views/base.py +9 -4
  16. django_cfg/apps/support/views/api.py +16 -7
  17. django_cfg/apps/tasks/__init__.py +61 -2
  18. django_cfg/apps/tasks/admin/__init__.py +3 -10
  19. django_cfg/apps/tasks/admin/config.py +98 -0
  20. django_cfg/apps/tasks/admin/task_log.py +265 -0
  21. django_cfg/apps/tasks/apps.py +7 -9
  22. django_cfg/apps/tasks/filters/__init__.py +10 -0
  23. django_cfg/apps/tasks/filters/task_log.py +121 -0
  24. django_cfg/apps/tasks/migrations/0001_initial.py +196 -0
  25. django_cfg/apps/tasks/models/__init__.py +4 -0
  26. django_cfg/apps/tasks/models/task_log.py +246 -0
  27. django_cfg/apps/tasks/serializers/__init__.py +28 -0
  28. django_cfg/apps/tasks/serializers/task_log.py +249 -0
  29. django_cfg/apps/tasks/services/__init__.py +10 -0
  30. django_cfg/apps/tasks/services/client/__init__.py +7 -0
  31. django_cfg/apps/tasks/services/client/client.py +234 -0
  32. django_cfg/apps/tasks/services/config_helper.py +63 -0
  33. django_cfg/apps/tasks/services/sync.py +204 -0
  34. django_cfg/apps/tasks/urls.py +7 -13
  35. django_cfg/apps/tasks/views/__init__.py +4 -10
  36. django_cfg/apps/tasks/views/task_log.py +41 -0
  37. django_cfg/apps/tasks/views/task_log_base.py +41 -0
  38. django_cfg/apps/tasks/views/task_log_overview.py +100 -0
  39. django_cfg/apps/tasks/views/task_log_related.py +41 -0
  40. django_cfg/apps/tasks/views/task_log_stats.py +91 -0
  41. django_cfg/apps/tasks/views/task_log_timeline.py +81 -0
  42. django_cfg/apps/urls.py +0 -1
  43. django_cfg/cli/commands/info.py +1 -1
  44. django_cfg/cli/utils.py +1 -1
  45. django_cfg/core/base/config_model.py +1 -1
  46. django_cfg/core/builders/apps_builder.py +1 -1
  47. django_cfg/core/generation/integration_generators/__init__.py +1 -1
  48. django_cfg/core/generation/integration_generators/tasks.py +14 -18
  49. django_cfg/core/generation/security_generators/crypto_fields.py +2 -1
  50. django_cfg/core/integration/display/startup.py +1 -1
  51. django_cfg/mixins/__init__.py +12 -0
  52. django_cfg/mixins/admin_api.py +37 -0
  53. django_cfg/mixins/client_api.py +39 -0
  54. django_cfg/models/django/constance.py +2 -8
  55. django_cfg/models/django/crypto_fields.py +13 -48
  56. django_cfg/models/tasks/__init__.py +8 -10
  57. django_cfg/models/tasks/backends.py +76 -207
  58. django_cfg/models/tasks/config.py +20 -127
  59. django_cfg/models/tasks/utils.py +17 -29
  60. django_cfg/modules/django_client/management/commands/generate_client.py +13 -1
  61. django_cfg/modules/django_unfold/navigation.py +121 -22
  62. django_cfg/pyproject.toml +2 -2
  63. django_cfg/registry/core.py +1 -1
  64. django_cfg/static/frontend/admin.zip +0 -0
  65. {django_cfg-1.4.107.dist-info → django_cfg-1.4.109.dist-info}/METADATA +3 -3
  66. {django_cfg-1.4.107.dist-info → django_cfg-1.4.109.dist-info}/RECORD +70 -117
  67. django_cfg/apps/tasks/admin/actions.py +0 -29
  68. django_cfg/apps/tasks/admin/tasks_admin.py +0 -154
  69. django_cfg/apps/tasks/api/serializers.py +0 -82
  70. django_cfg/apps/tasks/api/views.py +0 -571
  71. django_cfg/apps/tasks/serializers.py +0 -82
  72. django_cfg/apps/tasks/static/tasks/css/dashboard-alpine.css +0 -299
  73. django_cfg/apps/tasks/static/tasks/css/dashboard.css +0 -120
  74. django_cfg/apps/tasks/static/tasks/js/alpine/README.md +0 -47
  75. django_cfg/apps/tasks/static/tasks/js/alpine/actions/index.js +0 -8
  76. django_cfg/apps/tasks/static/tasks/js/alpine/actions/management.js +0 -123
  77. django_cfg/apps/tasks/static/tasks/js/alpine/actions/pagination.js +0 -21
  78. django_cfg/apps/tasks/static/tasks/js/alpine/actions/tasks.js +0 -101
  79. django_cfg/apps/tasks/static/tasks/js/alpine/actions/workers.js +0 -59
  80. django_cfg/apps/tasks/static/tasks/js/alpine/computed.js +0 -35
  81. django_cfg/apps/tasks/static/tasks/js/alpine/index.js +0 -148
  82. django_cfg/apps/tasks/static/tasks/js/alpine/loaders/index.js +0 -36
  83. django_cfg/apps/tasks/static/tasks/js/alpine/loaders/overview.js +0 -37
  84. django_cfg/apps/tasks/static/tasks/js/alpine/loaders/queues.js +0 -27
  85. django_cfg/apps/tasks/static/tasks/js/alpine/loaders/tasks.js +0 -32
  86. django_cfg/apps/tasks/static/tasks/js/alpine/loaders/workers.js +0 -21
  87. django_cfg/apps/tasks/static/tasks/js/alpine/state.js +0 -36
  88. django_cfg/apps/tasks/static/tasks/js/alpine/utils/formatters.js +0 -42
  89. django_cfg/apps/tasks/static/tasks/js/alpine/utils/helpers.js +0 -68
  90. django_cfg/apps/tasks/static/tasks/js/dashboard-alpine.js +0 -725
  91. django_cfg/apps/tasks/tasks/__init__.py +0 -10
  92. django_cfg/apps/tasks/tasks/demo_tasks.py +0 -127
  93. django_cfg/apps/tasks/templates/tasks/components/management_actions.html +0 -71
  94. django_cfg/apps/tasks/templates/tasks/components/overview_content.html +0 -94
  95. django_cfg/apps/tasks/templates/tasks/components/queues_content.html +0 -44
  96. django_cfg/apps/tasks/templates/tasks/components/tab_navigation.html +0 -45
  97. django_cfg/apps/tasks/templates/tasks/components/task_details_modal.html +0 -151
  98. django_cfg/apps/tasks/templates/tasks/components/tasks_content.html +0 -61
  99. django_cfg/apps/tasks/templates/tasks/components/tasks_mjs_integration.html +0 -269
  100. django_cfg/apps/tasks/templates/tasks/components/workers_content.html +0 -60
  101. django_cfg/apps/tasks/templates/tasks/layout/base.html +0 -20
  102. django_cfg/apps/tasks/templates/tasks/pages/dashboard-improved.html +0 -168
  103. django_cfg/apps/tasks/templates/tasks/pages/dashboard.html +0 -77
  104. django_cfg/apps/tasks/templates/tasks/partials/task_row_template.html +0 -40
  105. django_cfg/apps/tasks/templates/tasks/widgets/task_filters.html +0 -40
  106. django_cfg/apps/tasks/templates/tasks/widgets/task_footer.html +0 -86
  107. django_cfg/apps/tasks/templates/tasks/widgets/task_table.html +0 -90
  108. django_cfg/apps/tasks/urls_admin.py +0 -15
  109. django_cfg/apps/tasks/utils/__init__.py +0 -1
  110. django_cfg/apps/tasks/utils/simulator.py +0 -353
  111. django_cfg/apps/tasks/views/api.py +0 -571
  112. django_cfg/apps/tasks/views/dashboard.py +0 -89
  113. django_cfg/management/commands/rundramatiq.py +0 -24
  114. django_cfg/management/commands/rundramatiq_simulator.py +0 -22
  115. django_cfg/management/commands/task_clear.py +0 -25
  116. django_cfg/management/commands/task_status.py +0 -24
  117. django_cfg/modules/django_client/system/__init__.py +0 -24
  118. django_cfg/modules/django_client/system/base_generator.py +0 -123
  119. django_cfg/modules/django_client/system/generate_mjs_clients.py +0 -176
  120. django_cfg/modules/django_client/system/mjs_generator.py +0 -219
  121. django_cfg/modules/django_client/system/schema_parser.py +0 -199
  122. django_cfg/modules/django_client/system/templates/api_client.js.j2 +0 -87
  123. django_cfg/modules/django_client/system/templates/app_index.js.j2 +0 -13
  124. django_cfg/modules/django_client/system/templates/base_client.js.j2 +0 -166
  125. django_cfg/modules/django_client/system/templates/main_index.js.j2 +0 -80
  126. django_cfg/modules/django_client/system/templates/types.js.j2 +0 -24
  127. django_cfg/modules/django_tasks/__init__.py +0 -29
  128. django_cfg/modules/django_tasks/dramatiq_setup.py +0 -20
  129. django_cfg/modules/django_tasks/factory.py +0 -127
  130. django_cfg/modules/django_tasks/management/commands/__init__.py +0 -0
  131. django_cfg/modules/django_tasks/management/commands/rundramatiq.py +0 -253
  132. django_cfg/modules/django_tasks/management/commands/rundramatiq_simulator.py +0 -436
  133. django_cfg/modules/django_tasks/management/commands/task_clear.py +0 -226
  134. django_cfg/modules/django_tasks/management/commands/task_status.py +0 -257
  135. django_cfg/modules/django_tasks/service.py +0 -281
  136. django_cfg/modules/django_tasks/settings.py +0 -107
  137. /django_cfg/{modules/django_tasks/management → apps/tasks/migrations}/__init__.py +0 -0
  138. {django_cfg-1.4.107.dist-info → django_cfg-1.4.109.dist-info}/WHEEL +0 -0
  139. {django_cfg-1.4.107.dist-info → django_cfg-1.4.109.dist-info}/entry_points.txt +0 -0
  140. {django_cfg-1.4.107.dist-info → django_cfg-1.4.109.dist-info}/licenses/LICENSE +0 -0
@@ -1,127 +0,0 @@
1
- """
2
- Task service factory and utilities.
3
-
4
- Provides singleton instance and utility functions.
5
- """
6
-
7
- import logging
8
- from typing import Any, Dict
9
-
10
- logger = logging.getLogger(__name__)
11
-
12
- # Lazy import to avoid circular dependency
13
- _task_service_instance = None
14
-
15
-
16
- def get_task_service():
17
- """Get the global task service instance."""
18
- global _task_service_instance
19
-
20
- if _task_service_instance is None:
21
- from .service import DjangoTasks
22
- _task_service_instance = DjangoTasks()
23
-
24
- return _task_service_instance
25
-
26
-
27
- def reset_task_service():
28
- """Reset the global task service instance (useful for testing)."""
29
- global _task_service_instance
30
- _task_service_instance = None
31
-
32
-
33
- def is_task_system_available() -> bool:
34
- """Check if task system is available and properly configured."""
35
- try:
36
- service = get_task_service()
37
- return service.is_enabled()
38
- except Exception:
39
- return False
40
-
41
-
42
- def get_task_health() -> Dict[str, Any]:
43
- """Get task system health status."""
44
- try:
45
- service = get_task_service()
46
- return service.get_health_status()
47
- except Exception as e:
48
- return {
49
- "enabled": False,
50
- "error": str(e),
51
- "redis_connection": False,
52
- "configuration_valid": False,
53
- }
54
-
55
-
56
- def initialize_task_system():
57
- """
58
- Initialize the task system during Django app startup.
59
- This function is called from Django AppConfig.ready() method.
60
- """
61
- try:
62
- service = get_task_service()
63
-
64
- # Force config reload to ensure we have fresh config
65
- service._config = None
66
- config = service.config
67
-
68
- if config and config.enabled:
69
- logger.info("🔧 Initializing Django-CFG task system...")
70
-
71
- # Set up Dramatiq broker from Django settings
72
- try:
73
- import dramatiq
74
- from django.conf import settings
75
-
76
- # Django-dramatiq automatically configures the broker from DRAMATIQ_BROKER setting
77
- if hasattr(settings, 'DRAMATIQ_BROKER'):
78
- # Configure broker with middleware
79
- broker_config = settings.DRAMATIQ_BROKER
80
- middleware_list = getattr(settings, 'DRAMATIQ_MIDDLEWARE', [])
81
-
82
- # Import and instantiate middleware
83
- middleware_instances = []
84
- for middleware_path in middleware_list:
85
- try:
86
- module_path, class_name = middleware_path.rsplit('.', 1)
87
- module = __import__(module_path, fromlist=[class_name])
88
- middleware_class = getattr(module, class_name)
89
- middleware_instances.append(middleware_class())
90
- except Exception as e:
91
- logger.warning(f"Failed to load middleware {middleware_path}: {e}")
92
-
93
- # Create broker with middleware
94
- broker_class_path = broker_config['BROKER']
95
- module_path, class_name = broker_class_path.rsplit('.', 1)
96
- module = __import__(module_path, fromlist=[class_name])
97
- broker_class = getattr(module, class_name)
98
-
99
- broker_options = broker_config.get('OPTIONS', {})
100
- broker = broker_class(middleware=middleware_instances, **broker_options)
101
-
102
- # Set as default broker
103
- dramatiq.set_broker(broker)
104
-
105
- logger.debug(f"✅ Dramatiq broker configured with {len(middleware_instances)} middleware")
106
- else:
107
- logger.warning("DRAMATIQ_BROKER not found in Django settings")
108
-
109
- except Exception as e:
110
- logger.warning(f"Failed to configure Dramatiq: {e}")
111
-
112
- logger.info("✅ Task system initialized successfully")
113
- logger.info("💡 To start workers, run: python manage.py rundramatiq")
114
- else:
115
- logger.debug(f"Task system not enabled (config: {config}), skipping initialization")
116
-
117
- except Exception as e:
118
- logger.error(f"Failed to initialize task system: {e}")
119
-
120
-
121
- __all__ = [
122
- "get_task_service",
123
- "reset_task_service",
124
- "is_task_system_available",
125
- "get_task_health",
126
- "initialize_task_system",
127
- ]
@@ -1,253 +0,0 @@
1
- """
2
- Django management command for running Dramatiq workers.
3
-
4
- Based on django_dramatiq.management.commands.rundramatiq with Django-CFG integration.
5
- Simple, clean, and working approach.
6
- """
7
-
8
- import argparse
9
- import importlib
10
- import multiprocessing
11
- import os
12
- import sys
13
-
14
- from django.apps import apps
15
- from django.conf import settings
16
- from django.core.management.base import BaseCommand
17
- from django.utils.module_loading import module_has_submodule
18
-
19
- from django_cfg.modules.django_logging import get_logger
20
- from django_cfg.modules.django_tasks import get_task_service
21
-
22
- # Default values
23
- NPROCS = multiprocessing.cpu_count()
24
- NTHREADS = 8
25
-
26
-
27
- logger = get_logger('rundramatiq')
28
-
29
-
30
- class Command(BaseCommand):
31
- # Web execution metadata
32
- web_executable = False
33
- requires_input = False
34
- is_destructive = False
35
-
36
- help = "Run Dramatiq workers with Django-CFG configuration."
37
-
38
- def add_arguments(self, parser):
39
- parser.formatter_class = argparse.ArgumentDefaultsHelpFormatter
40
-
41
- parser.add_argument(
42
- "--processes", "-p",
43
- default=NPROCS,
44
- type=int,
45
- help="The number of processes to run",
46
- )
47
- parser.add_argument(
48
- "--threads", "-t",
49
- default=NTHREADS,
50
- type=int,
51
- help="The number of threads per process to use",
52
- )
53
- parser.add_argument(
54
- "--queues", "-Q",
55
- nargs="*",
56
- type=str,
57
- help="Listen to a subset of queues, or all when empty",
58
- )
59
- parser.add_argument(
60
- "--watch",
61
- dest="watch_dir",
62
- help="Reload workers when changes are detected in the given directory",
63
- )
64
- parser.add_argument(
65
- "--pid-file",
66
- type=str,
67
- help="Write the PID of the master process to this file",
68
- )
69
- parser.add_argument(
70
- "--log-file",
71
- type=str,
72
- help="Write all logs to a file, or stderr when empty",
73
- )
74
- parser.add_argument(
75
- "--worker-shutdown-timeout",
76
- type=int,
77
- default=600000,
78
- help="Timeout for worker shutdown, in milliseconds"
79
- )
80
- parser.add_argument(
81
- "--dry-run",
82
- action="store_true",
83
- help="Show configuration without starting workers",
84
- )
85
-
86
- def handle(self, watch_dir, processes, threads, verbosity, queues,
87
- pid_file, log_file, worker_shutdown_timeout, dry_run, **options):
88
- logger.info("Starting rundramatiq command")
89
-
90
- # Get task service and validate
91
- task_service = get_task_service()
92
- if not task_service.is_enabled():
93
- self.stdout.write(
94
- self.style.ERROR("Task system is not enabled in Django-CFG configuration")
95
- )
96
- return
97
-
98
- # Discover task modules
99
- tasks_modules = self._discover_tasks_modules()
100
-
101
- # Show configuration info
102
- self.stdout.write(self.style.SUCCESS("Dramatiq Worker Configuration:"))
103
- self.stdout.write(f"Processes: {processes}")
104
- self.stdout.write(f"Threads: {threads}")
105
- if queues:
106
- self.stdout.write(f"Queues: {', '.join(queues)}")
107
- else:
108
- self.stdout.write("Queues: all")
109
-
110
- self.stdout.write("\nDiscovered task modules:")
111
- for module in tasks_modules:
112
- self.stdout.write(f" - {module}")
113
-
114
- # If dry run, show command and exit
115
- if dry_run:
116
- executable_name = "dramatiq"
117
-
118
- process_args = [
119
- executable_name,
120
- "django_cfg.modules.django_tasks.dramatiq_setup", # Broker module
121
- "--processes", str(processes),
122
- "--threads", str(threads),
123
- "--worker-shutdown-timeout", str(worker_shutdown_timeout),
124
- ]
125
-
126
- if watch_dir:
127
- process_args.extend(["--watch", watch_dir])
128
-
129
- verbosity_args = ["-v"] * (verbosity - 1)
130
- process_args.extend(verbosity_args)
131
-
132
- if queues:
133
- process_args.extend(["--queues"] + queues)
134
-
135
- if pid_file:
136
- process_args.extend(["--pid-file", pid_file])
137
-
138
- if log_file:
139
- process_args.extend(["--log-file", log_file])
140
-
141
- # Add task modules (broker module is already first in tasks_modules)
142
- process_args.extend(tasks_modules)
143
-
144
- self.stdout.write("\nCommand that would be executed:")
145
- self.stdout.write(f' {" ".join(process_args)}')
146
- return
147
-
148
- # Show startup info
149
- self.stdout.write(self.style.SUCCESS("\nStarting Dramatiq workers..."))
150
-
151
- # Build dramatiq command
152
- executable_name = "dramatiq"
153
- executable_path = self._resolve_executable(executable_name)
154
-
155
- # Build process arguments exactly like django_dramatiq
156
- process_args = [
157
- executable_name,
158
- "django_cfg.modules.django_tasks.dramatiq_setup", # Broker module
159
- "--processes", str(processes),
160
- "--threads", str(threads),
161
- "--worker-shutdown-timeout", str(worker_shutdown_timeout),
162
- ]
163
-
164
- # Add watch directory if specified
165
- if watch_dir:
166
- process_args.extend(["--watch", watch_dir])
167
-
168
- # Add verbosity
169
- verbosity_args = ["-v"] * (verbosity - 1)
170
- process_args.extend(verbosity_args)
171
-
172
- # Add queues if specified
173
- if queues:
174
- process_args.extend(["--queues"] + queues)
175
-
176
- # Add PID file if specified
177
- if pid_file:
178
- process_args.extend(["--pid-file", pid_file])
179
-
180
- # Add log file if specified
181
- if log_file:
182
- process_args.extend(["--log-file", log_file])
183
-
184
- # Add task modules (broker module is already first in tasks_modules)
185
- process_args.extend(tasks_modules)
186
-
187
- self.stdout.write(f'Running dramatiq: "{" ".join(process_args)}"\n')
188
-
189
- # Ensure DJANGO_SETTINGS_MODULE is set for worker processes
190
- if not os.environ.get('DJANGO_SETTINGS_MODULE'):
191
- if hasattr(settings, 'SETTINGS_MODULE'):
192
- os.environ['DJANGO_SETTINGS_MODULE'] = settings.SETTINGS_MODULE
193
- else:
194
- # Try to detect from manage.py or current settings
195
- from django.conf import settings as django_settings
196
- if hasattr(django_settings, '_wrapped') and hasattr(django_settings._wrapped, '__module__'):
197
- module_name = django_settings._wrapped.__module__
198
- os.environ['DJANGO_SETTINGS_MODULE'] = module_name
199
- else:
200
- self.stdout.write(
201
- self.style.WARNING("Could not detect DJANGO_SETTINGS_MODULE")
202
- )
203
-
204
- # Use os.execvp like django_dramatiq to preserve environment
205
- if sys.platform == "win32":
206
- import subprocess
207
- command = [executable_path] + process_args[1:]
208
- sys.exit(subprocess.run(command))
209
-
210
- os.execvp(executable_path, process_args)
211
-
212
- def _discover_tasks_modules(self):
213
- """Discover task modules like django_dramatiq does."""
214
- # Always include our broker setup module first
215
- tasks_modules = ["django_cfg.modules.django_tasks.dramatiq_setup"]
216
-
217
- # Get task service for configuration
218
- task_service = get_task_service()
219
-
220
- # Try to get task modules from Django-CFG config
221
- if task_service.config and task_service.config.auto_discover_tasks:
222
- discovered = task_service.discover_tasks()
223
- for module_name in discovered:
224
- self.stdout.write(f"Discovered tasks module: '{module_name}'")
225
- tasks_modules.append(module_name)
226
-
227
- # Fallback: use django_dramatiq discovery logic
228
- if len(tasks_modules) == 1: # Only broker module found
229
- task_module_names = getattr(settings, "DRAMATIQ_AUTODISCOVER_MODULES", ("tasks",))
230
-
231
- for app_config in apps.get_app_configs():
232
- for task_module in task_module_names:
233
- if module_has_submodule(app_config.module, task_module):
234
- module_name = f"{app_config.name}.{task_module}"
235
- try:
236
- importlib.import_module(module_name)
237
- self.stdout.write(f"Discovered tasks module: '{module_name}'")
238
- tasks_modules.append(module_name)
239
- except ImportError:
240
- # Module exists but has import errors, skip it
241
- pass
242
-
243
- return tasks_modules
244
-
245
- def _resolve_executable(self, exec_name):
246
- """Resolve executable path like django_dramatiq does."""
247
- bin_dir = os.path.dirname(sys.executable)
248
- if bin_dir:
249
- for d in [bin_dir, os.path.join(bin_dir, "Scripts")]:
250
- exec_path = os.path.join(d, exec_name)
251
- if os.path.isfile(exec_path):
252
- return exec_path
253
- return exec_name