django-cfg 1.4.113__py3-none-any.whl → 1.4.114__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.
- django_cfg/__init__.py +1 -1
- django_cfg/apps/dashboard/serializers/__init__.py +10 -8
- django_cfg/apps/dashboard/serializers/django_q2.py +50 -0
- django_cfg/apps/dashboard/services/__init__.py +2 -2
- django_cfg/apps/dashboard/services/django_q2_service.py +159 -0
- django_cfg/apps/dashboard/services/system_health_service.py +39 -26
- django_cfg/apps/dashboard/urls.py +2 -2
- django_cfg/apps/dashboard/views/__init__.py +2 -2
- django_cfg/apps/dashboard/views/django_q2_views.py +79 -0
- django_cfg/apps/tasks/migrations/0002_delete_tasklog.py +16 -0
- django_cfg/core/base/config_model.py +15 -5
- django_cfg/core/builders/apps_builder.py +3 -3
- django_cfg/core/generation/data_generators/cache.py +28 -2
- django_cfg/core/generation/integration_generators/__init__.py +4 -3
- django_cfg/core/generation/integration_generators/django_q2.py +133 -0
- django_cfg/core/generation/orchestrator.py +7 -7
- django_cfg/models/__init__.py +3 -3
- django_cfg/models/django/__init__.py +3 -3
- django_cfg/models/django/django_q2.py +491 -0
- django_cfg/pyproject.toml +2 -2
- django_cfg/registry/core.py +3 -3
- django_cfg/static/frontend/admin.zip +0 -0
- {django_cfg-1.4.113.dist-info → django_cfg-1.4.114.dist-info}/METADATA +3 -2
- {django_cfg-1.4.113.dist-info → django_cfg-1.4.114.dist-info}/RECORD +27 -26
- django_cfg/apps/dashboard/serializers/crontab.py +0 -84
- django_cfg/apps/dashboard/services/crontab_service.py +0 -210
- django_cfg/apps/dashboard/views/crontab_views.py +0 -72
- django_cfg/core/generation/integration_generators/crontab.py +0 -64
- django_cfg/models/django/crontab.py +0 -303
- {django_cfg-1.4.113.dist-info → django_cfg-1.4.114.dist-info}/WHEEL +0 -0
- {django_cfg-1.4.113.dist-info → django_cfg-1.4.114.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.4.113.dist-info → django_cfg-1.4.114.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,303 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Crontab Configuration for django-cfg.
|
|
3
|
-
|
|
4
|
-
Type-safe configuration for django-crontab with automatic
|
|
5
|
-
Django settings generation and support for management commands.
|
|
6
|
-
|
|
7
|
-
Features:
|
|
8
|
-
- Type-safe crontab job definitions
|
|
9
|
-
- Django management command support
|
|
10
|
-
- Schedule validation
|
|
11
|
-
- Timezone support
|
|
12
|
-
- Lock file prevention of concurrent runs
|
|
13
|
-
- Command prefix configuration
|
|
14
|
-
"""
|
|
15
|
-
|
|
16
|
-
from typing import Any, Dict, List, Literal, Optional, Union
|
|
17
|
-
|
|
18
|
-
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class CrontabJobConfig(BaseModel):
|
|
22
|
-
"""
|
|
23
|
-
Configuration for a single crontab job.
|
|
24
|
-
|
|
25
|
-
Supports both management commands and Python callables.
|
|
26
|
-
"""
|
|
27
|
-
|
|
28
|
-
model_config = ConfigDict(
|
|
29
|
-
validate_assignment=True,
|
|
30
|
-
extra="forbid",
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
# Job identification
|
|
34
|
-
name: str = Field(
|
|
35
|
-
...,
|
|
36
|
-
description="Human-readable job name (for identification and logging)",
|
|
37
|
-
min_length=1,
|
|
38
|
-
max_length=100,
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
# Schedule definition (crontab format)
|
|
42
|
-
minute: str = Field(
|
|
43
|
-
default="*",
|
|
44
|
-
description="Crontab minute (0-59, *, */N, or comma-separated)",
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
hour: str = Field(
|
|
48
|
-
default="*",
|
|
49
|
-
description="Crontab hour (0-23, *, */N, or comma-separated)",
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
day_of_week: str = Field(
|
|
53
|
-
default="*",
|
|
54
|
-
description="Crontab day of week (0-6, *, */N, or comma-separated)",
|
|
55
|
-
)
|
|
56
|
-
|
|
57
|
-
day_of_month: str = Field(
|
|
58
|
-
default="*",
|
|
59
|
-
description="Crontab day of month (1-31, *, */N, or comma-separated)",
|
|
60
|
-
)
|
|
61
|
-
|
|
62
|
-
month_of_year: str = Field(
|
|
63
|
-
default="*",
|
|
64
|
-
description="Crontab month (1-12, *, */N, or comma-separated)",
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
# Job execution configuration
|
|
68
|
-
job_type: Literal["command", "callable"] = Field(
|
|
69
|
-
default="command",
|
|
70
|
-
description="Job type: 'command' for Django management commands, 'callable' for Python functions",
|
|
71
|
-
)
|
|
72
|
-
|
|
73
|
-
# For management commands
|
|
74
|
-
command: Optional[str] = Field(
|
|
75
|
-
default=None,
|
|
76
|
-
description="Django management command name (e.g., 'sync_account_balances')",
|
|
77
|
-
)
|
|
78
|
-
|
|
79
|
-
command_args: List[str] = Field(
|
|
80
|
-
default_factory=list,
|
|
81
|
-
description="Command positional arguments",
|
|
82
|
-
)
|
|
83
|
-
|
|
84
|
-
command_kwargs: Dict[str, Any] = Field(
|
|
85
|
-
default_factory=dict,
|
|
86
|
-
description="Command keyword arguments (e.g., {'verbosity': 0})",
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
# For Python callables
|
|
90
|
-
callable_path: Optional[str] = Field(
|
|
91
|
-
default=None,
|
|
92
|
-
description="Full Python path to callable (e.g., 'myapp.tasks.my_task')",
|
|
93
|
-
pattern=r"^[\w.]+$",
|
|
94
|
-
)
|
|
95
|
-
|
|
96
|
-
callable_args: List[Any] = Field(
|
|
97
|
-
default_factory=list,
|
|
98
|
-
description="Callable positional arguments",
|
|
99
|
-
)
|
|
100
|
-
|
|
101
|
-
callable_kwargs: Dict[str, Any] = Field(
|
|
102
|
-
default_factory=dict,
|
|
103
|
-
description="Callable keyword arguments",
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
# Job options
|
|
107
|
-
enabled: bool = Field(
|
|
108
|
-
default=True,
|
|
109
|
-
description="Whether job is enabled",
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
comment: Optional[str] = Field(
|
|
113
|
-
default=None,
|
|
114
|
-
description="Optional comment describing the job",
|
|
115
|
-
max_length=200,
|
|
116
|
-
)
|
|
117
|
-
|
|
118
|
-
@field_validator("minute", "hour", "day_of_week", "day_of_month", "month_of_year")
|
|
119
|
-
@classmethod
|
|
120
|
-
def validate_crontab_field(cls, v: str) -> str:
|
|
121
|
-
"""Validate crontab field format."""
|
|
122
|
-
if v == "*":
|
|
123
|
-
return v
|
|
124
|
-
|
|
125
|
-
# Allow */N (e.g., */15)
|
|
126
|
-
if v.startswith("*/"):
|
|
127
|
-
try:
|
|
128
|
-
int(v[2:])
|
|
129
|
-
return v
|
|
130
|
-
except ValueError:
|
|
131
|
-
raise ValueError(f"Invalid step value in crontab field: {v}")
|
|
132
|
-
|
|
133
|
-
# Allow ranges (e.g., 1-5)
|
|
134
|
-
if "-" in v:
|
|
135
|
-
parts = v.split("-")
|
|
136
|
-
if len(parts) != 2:
|
|
137
|
-
raise ValueError(f"Invalid range format in crontab field: {v}")
|
|
138
|
-
try:
|
|
139
|
-
int(parts[0])
|
|
140
|
-
int(parts[1])
|
|
141
|
-
return v
|
|
142
|
-
except ValueError:
|
|
143
|
-
raise ValueError(f"Invalid range values in crontab field: {v}")
|
|
144
|
-
|
|
145
|
-
# Allow comma-separated (e.g., 1,3,5)
|
|
146
|
-
if "," in v:
|
|
147
|
-
parts = v.split(",")
|
|
148
|
-
try:
|
|
149
|
-
for part in parts:
|
|
150
|
-
int(part)
|
|
151
|
-
return v
|
|
152
|
-
except ValueError:
|
|
153
|
-
raise ValueError(f"Invalid comma-separated values in crontab field: {v}")
|
|
154
|
-
|
|
155
|
-
# Allow single number
|
|
156
|
-
try:
|
|
157
|
-
int(v)
|
|
158
|
-
return v
|
|
159
|
-
except ValueError:
|
|
160
|
-
raise ValueError(f"Invalid crontab field format: {v}")
|
|
161
|
-
|
|
162
|
-
def model_post_init(self, __context: Any) -> None:
|
|
163
|
-
"""Validate job configuration after initialization."""
|
|
164
|
-
# Ensure either command or callable_path is set
|
|
165
|
-
if self.job_type == "command" and not self.command:
|
|
166
|
-
raise ValueError("'command' must be set when job_type is 'command'")
|
|
167
|
-
|
|
168
|
-
if self.job_type == "callable" and not self.callable_path:
|
|
169
|
-
raise ValueError("'callable_path' must be set when job_type is 'callable'")
|
|
170
|
-
|
|
171
|
-
@property
|
|
172
|
-
def schedule(self) -> str:
|
|
173
|
-
"""Get crontab schedule string."""
|
|
174
|
-
return f"{self.minute} {self.hour} {self.day_of_month} {self.month_of_year} {self.day_of_week}"
|
|
175
|
-
|
|
176
|
-
def to_django_crontab_format(self) -> tuple:
|
|
177
|
-
"""
|
|
178
|
-
Convert to django-crontab format.
|
|
179
|
-
|
|
180
|
-
Returns:
|
|
181
|
-
Tuple for CRONJOBS list entry
|
|
182
|
-
"""
|
|
183
|
-
if self.job_type == "command":
|
|
184
|
-
# Format: (schedule, 'django.core.management.call_command', [command, *args], kwargs)
|
|
185
|
-
return (
|
|
186
|
-
self.schedule,
|
|
187
|
-
'django.core.management.call_command',
|
|
188
|
-
[self.command] + self.command_args,
|
|
189
|
-
self.command_kwargs,
|
|
190
|
-
)
|
|
191
|
-
else:
|
|
192
|
-
# Format: (schedule, callable_path, args, kwargs)
|
|
193
|
-
return (
|
|
194
|
-
self.schedule,
|
|
195
|
-
self.callable_path,
|
|
196
|
-
self.callable_args,
|
|
197
|
-
self.callable_kwargs,
|
|
198
|
-
)
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
class CrontabConfig(BaseModel):
|
|
202
|
-
"""
|
|
203
|
-
Complete Crontab configuration container.
|
|
204
|
-
|
|
205
|
-
Integrates with django-crontab for scheduled task execution.
|
|
206
|
-
Automatically adds django_crontab to INSTALLED_APPS when enabled.
|
|
207
|
-
"""
|
|
208
|
-
|
|
209
|
-
model_config = ConfigDict(
|
|
210
|
-
validate_assignment=True,
|
|
211
|
-
extra="forbid",
|
|
212
|
-
)
|
|
213
|
-
|
|
214
|
-
enabled: bool = Field(
|
|
215
|
-
default=True,
|
|
216
|
-
description="Enable crontab scheduling (auto-adds django_crontab to INSTALLED_APPS)",
|
|
217
|
-
)
|
|
218
|
-
|
|
219
|
-
jobs: List[CrontabJobConfig] = Field(
|
|
220
|
-
default_factory=list,
|
|
221
|
-
description="List of scheduled jobs",
|
|
222
|
-
)
|
|
223
|
-
|
|
224
|
-
# Django-crontab specific options
|
|
225
|
-
command_prefix: Optional[str] = Field(
|
|
226
|
-
default=None,
|
|
227
|
-
description="Command prefix for all cron jobs (e.g., 'DJANGO_SETTINGS_MODULE=api.settings')",
|
|
228
|
-
)
|
|
229
|
-
|
|
230
|
-
command_suffix: Optional[str] = Field(
|
|
231
|
-
default=None,
|
|
232
|
-
description="Command suffix for all cron jobs",
|
|
233
|
-
)
|
|
234
|
-
|
|
235
|
-
lock_jobs: bool = Field(
|
|
236
|
-
default=True,
|
|
237
|
-
description="Use lock files to prevent concurrent job execution",
|
|
238
|
-
)
|
|
239
|
-
|
|
240
|
-
comment: str = Field(
|
|
241
|
-
default="django-crontab jobs",
|
|
242
|
-
description="Comment added to crontab file",
|
|
243
|
-
max_length=100,
|
|
244
|
-
)
|
|
245
|
-
|
|
246
|
-
def get_enabled_jobs(self) -> List[CrontabJobConfig]:
|
|
247
|
-
"""Get list of enabled jobs."""
|
|
248
|
-
return [job for job in self.jobs if job.enabled]
|
|
249
|
-
|
|
250
|
-
def to_django_settings(self) -> Dict[str, Any]:
|
|
251
|
-
"""
|
|
252
|
-
Convert to Django settings dictionary.
|
|
253
|
-
|
|
254
|
-
Generates CRONJOBS and related settings for django-crontab.
|
|
255
|
-
"""
|
|
256
|
-
if not self.enabled:
|
|
257
|
-
return {}
|
|
258
|
-
|
|
259
|
-
settings = {}
|
|
260
|
-
|
|
261
|
-
# Build CRONJOBS list
|
|
262
|
-
enabled_jobs = self.get_enabled_jobs()
|
|
263
|
-
if enabled_jobs:
|
|
264
|
-
settings["CRONJOBS"] = [
|
|
265
|
-
job.to_django_crontab_format()
|
|
266
|
-
for job in enabled_jobs
|
|
267
|
-
]
|
|
268
|
-
|
|
269
|
-
# Add command prefix if configured
|
|
270
|
-
if self.command_prefix:
|
|
271
|
-
settings["CRONTAB_COMMAND_PREFIX"] = self.command_prefix
|
|
272
|
-
|
|
273
|
-
# Add command suffix if configured
|
|
274
|
-
if self.command_suffix:
|
|
275
|
-
settings["CRONTAB_COMMAND_SUFFIX"] = self.command_suffix
|
|
276
|
-
|
|
277
|
-
# Add lock jobs setting
|
|
278
|
-
settings["CRONTAB_LOCK_JOBS"] = self.lock_jobs
|
|
279
|
-
|
|
280
|
-
# Add comment
|
|
281
|
-
settings["CRONTAB_COMMENT"] = self.comment
|
|
282
|
-
|
|
283
|
-
return settings
|
|
284
|
-
|
|
285
|
-
def get_job_by_name(self, name: str) -> Optional[CrontabJobConfig]:
|
|
286
|
-
"""Get job by name."""
|
|
287
|
-
for job in self.jobs:
|
|
288
|
-
if job.name == name:
|
|
289
|
-
return job
|
|
290
|
-
return None
|
|
291
|
-
|
|
292
|
-
def get_jobs_by_command(self, command: str) -> List[CrontabJobConfig]:
|
|
293
|
-
"""Get all jobs for a specific command."""
|
|
294
|
-
return [
|
|
295
|
-
job for job in self.jobs
|
|
296
|
-
if job.job_type == "command" and job.command == command
|
|
297
|
-
]
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
__all__ = [
|
|
301
|
-
"CrontabJobConfig",
|
|
302
|
-
"CrontabConfig",
|
|
303
|
-
]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|