django-cfg 1.3.9__py3-none-any.whl → 1.3.11__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 +1 -1
- django_cfg/apps/payments/admin/networks_admin.py +12 -1
- django_cfg/apps/payments/admin/payments_admin.py +13 -0
- django_cfg/apps/payments/admin_interface/serializers/payment_serializers.py +62 -14
- django_cfg/apps/payments/admin_interface/templates/payments/components/payment_card.html +121 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/payment_qr_code.html +95 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/progress_bar.html +37 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/provider_stats.html +60 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/status_badge.html +41 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/status_overview.html +83 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_detail.html +363 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +33 -3
- django_cfg/apps/payments/admin_interface/views/api/payments.py +102 -0
- django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +96 -45
- django_cfg/apps/payments/admin_interface/views/forms.py +5 -1
- django_cfg/apps/payments/config/__init__.py +14 -15
- django_cfg/apps/payments/config/django_cfg_integration.py +59 -1
- django_cfg/apps/payments/config/helpers.py +8 -13
- django_cfg/apps/payments/migrations/0001_initial.py +33 -46
- django_cfg/apps/payments/migrations/0002_rename_payments_un_user_id_7f6e79_idx_payments_un_user_id_8ce187_idx_and_more.py +46 -0
- django_cfg/apps/payments/migrations/0003_universalpayment_status_changed_at.py +25 -0
- django_cfg/apps/payments/models/managers/payment_managers.py +142 -25
- django_cfg/apps/payments/models/payments.py +94 -0
- django_cfg/apps/payments/services/core/base.py +4 -4
- django_cfg/apps/payments/services/core/payment_service.py +265 -38
- django_cfg/apps/payments/services/providers/base.py +209 -3
- django_cfg/apps/payments/services/providers/models/__init__.py +2 -0
- django_cfg/apps/payments/services/providers/models/base.py +25 -2
- django_cfg/apps/payments/services/providers/nowpayments/models.py +2 -2
- django_cfg/apps/payments/services/providers/nowpayments/provider.py +57 -9
- django_cfg/apps/payments/services/providers/registry.py +5 -5
- django_cfg/apps/payments/services/types/requests.py +19 -7
- django_cfg/apps/payments/signals/payment_signals.py +31 -2
- django_cfg/apps/payments/static/payments/js/api-client.js +6 -1
- django_cfg/apps/payments/static/payments/js/payment-detail.js +167 -0
- django_cfg/apps/payments/static/payments/js/payment-form.js +35 -26
- django_cfg/apps/payments/templatetags/payment_tags.py +8 -0
- django_cfg/apps/payments/urls.py +3 -2
- django_cfg/apps/payments/views/api/currencies.py +3 -0
- django_cfg/apps/payments/views/serializers/currencies.py +18 -5
- django_cfg/apps/tasks/admin/tasks_admin.py +2 -2
- django_cfg/apps/tasks/static/tasks/css/dashboard.css +68 -217
- django_cfg/apps/tasks/static/tasks/js/api.js +40 -84
- django_cfg/apps/tasks/static/tasks/js/components/DataManager.js +24 -0
- django_cfg/apps/tasks/static/tasks/js/components/TabManager.js +85 -0
- django_cfg/apps/tasks/static/tasks/js/components/TaskRenderer.js +216 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/main.mjs +245 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/overview.mjs +123 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/queues.mjs +120 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/tasks.mjs +350 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/workers.mjs +169 -0
- django_cfg/apps/tasks/tasks/__init__.py +10 -0
- django_cfg/apps/tasks/tasks/demo_tasks.py +133 -0
- django_cfg/apps/tasks/templates/tasks/components/management_actions.html +42 -45
- django_cfg/apps/tasks/templates/tasks/components/{status_cards.html → overview_content.html} +30 -11
- django_cfg/apps/tasks/templates/tasks/components/queues_content.html +19 -0
- django_cfg/apps/tasks/templates/tasks/components/tab_navigation.html +16 -10
- django_cfg/apps/tasks/templates/tasks/components/tasks_content.html +51 -0
- django_cfg/apps/tasks/templates/tasks/components/workers_content.html +30 -0
- django_cfg/apps/tasks/templates/tasks/layout/base.html +117 -0
- django_cfg/apps/tasks/templates/tasks/pages/dashboard.html +82 -0
- django_cfg/apps/tasks/templates/tasks/partials/task_row_template.html +40 -0
- django_cfg/apps/tasks/templates/tasks/widgets/task_filters.html +37 -0
- django_cfg/apps/tasks/templates/tasks/widgets/task_footer.html +41 -0
- django_cfg/apps/tasks/templates/tasks/widgets/task_table.html +50 -0
- django_cfg/apps/tasks/urls.py +2 -2
- django_cfg/apps/tasks/urls_admin.py +2 -2
- django_cfg/apps/tasks/utils/__init__.py +1 -0
- django_cfg/apps/tasks/utils/simulator.py +356 -0
- django_cfg/apps/tasks/views/__init__.py +16 -0
- django_cfg/apps/tasks/views/api.py +569 -0
- django_cfg/apps/tasks/views/dashboard.py +58 -0
- django_cfg/core/integration/__init__.py +21 -0
- django_cfg/management/commands/rundramatiq_simulator.py +430 -0
- django_cfg/models/constance.py +0 -11
- django_cfg/models/payments.py +137 -3
- django_cfg/modules/django_tasks.py +54 -21
- django_cfg/registry/core.py +4 -9
- django_cfg/template_archive/django_sample.zip +0 -0
- {django_cfg-1.3.9.dist-info → django_cfg-1.3.11.dist-info}/METADATA +2 -2
- {django_cfg-1.3.9.dist-info → django_cfg-1.3.11.dist-info}/RECORD +84 -152
- django_cfg/apps/payments/config/constance/__init__.py +0 -22
- django_cfg/apps/payments/config/constance/config_service.py +0 -123
- django_cfg/apps/payments/config/constance/fields.py +0 -69
- django_cfg/apps/payments/config/constance/settings.py +0 -160
- django_cfg/apps/payments/migrations/0002_currency_usd_rate_currency_usd_rate_updated_at.py +0 -26
- django_cfg/apps/payments/migrations/0003_remove_provider_currency_fields.py +0 -28
- django_cfg/apps/payments/migrations/0004_add_reserved_usd_field.py +0 -30
- django_cfg/apps/tasks/static/tasks/js/dashboard.js +0 -614
- django_cfg/apps/tasks/static/tasks/js/modals.js +0 -452
- django_cfg/apps/tasks/static/tasks/js/notifications.js +0 -144
- django_cfg/apps/tasks/static/tasks/js/task-monitor.js +0 -454
- django_cfg/apps/tasks/static/tasks/js/theme.js +0 -77
- django_cfg/apps/tasks/templates/tasks/base.html +0 -96
- django_cfg/apps/tasks/templates/tasks/components/info_cards.html +0 -85
- django_cfg/apps/tasks/templates/tasks/components/overview_tab.html +0 -22
- django_cfg/apps/tasks/templates/tasks/components/queues_tab.html +0 -19
- django_cfg/apps/tasks/templates/tasks/components/task_details_modal.html +0 -103
- django_cfg/apps/tasks/templates/tasks/components/tasks_tab.html +0 -32
- django_cfg/apps/tasks/templates/tasks/components/workers_tab.html +0 -29
- django_cfg/apps/tasks/templates/tasks/dashboard.html +0 -29
- django_cfg/apps/tasks/views.py +0 -461
- django_cfg/management/commands/app_agent_diagnose.py +0 -470
- django_cfg/management/commands/app_agent_generate.py +0 -342
- django_cfg/management/commands/app_agent_info.py +0 -308
- django_cfg/management/commands/auto_generate.py +0 -486
- django_cfg/modules/django_app_agent/__init__.py +0 -87
- django_cfg/modules/django_app_agent/agents/__init__.py +0 -40
- django_cfg/modules/django_app_agent/agents/base/__init__.py +0 -24
- django_cfg/modules/django_app_agent/agents/base/agent.py +0 -354
- django_cfg/modules/django_app_agent/agents/base/context.py +0 -236
- django_cfg/modules/django_app_agent/agents/base/executor.py +0 -430
- django_cfg/modules/django_app_agent/agents/generation/__init__.py +0 -12
- django_cfg/modules/django_app_agent/agents/generation/app_generator/__init__.py +0 -15
- django_cfg/modules/django_app_agent/agents/generation/app_generator/config_validator.py +0 -147
- django_cfg/modules/django_app_agent/agents/generation/app_generator/main.py +0 -99
- django_cfg/modules/django_app_agent/agents/generation/app_generator/models.py +0 -32
- django_cfg/modules/django_app_agent/agents/generation/app_generator/prompt_manager.py +0 -290
- django_cfg/modules/django_app_agent/agents/interfaces.py +0 -376
- django_cfg/modules/django_app_agent/core/__init__.py +0 -33
- django_cfg/modules/django_app_agent/core/config.py +0 -300
- django_cfg/modules/django_app_agent/core/exceptions.py +0 -359
- django_cfg/modules/django_app_agent/models/__init__.py +0 -71
- django_cfg/modules/django_app_agent/models/base.py +0 -283
- django_cfg/modules/django_app_agent/models/context.py +0 -496
- django_cfg/modules/django_app_agent/models/enums.py +0 -481
- django_cfg/modules/django_app_agent/models/requests.py +0 -500
- django_cfg/modules/django_app_agent/models/responses.py +0 -585
- django_cfg/modules/django_app_agent/pytest.ini +0 -6
- django_cfg/modules/django_app_agent/services/__init__.py +0 -42
- django_cfg/modules/django_app_agent/services/app_generator/__init__.py +0 -30
- django_cfg/modules/django_app_agent/services/app_generator/ai_integration.py +0 -133
- django_cfg/modules/django_app_agent/services/app_generator/context.py +0 -40
- django_cfg/modules/django_app_agent/services/app_generator/main.py +0 -202
- django_cfg/modules/django_app_agent/services/app_generator/structure.py +0 -316
- django_cfg/modules/django_app_agent/services/app_generator/validation.py +0 -125
- django_cfg/modules/django_app_agent/services/base.py +0 -437
- django_cfg/modules/django_app_agent/services/context_builder/__init__.py +0 -34
- django_cfg/modules/django_app_agent/services/context_builder/code_extractor.py +0 -141
- django_cfg/modules/django_app_agent/services/context_builder/context_generator.py +0 -276
- django_cfg/modules/django_app_agent/services/context_builder/main.py +0 -272
- django_cfg/modules/django_app_agent/services/context_builder/models.py +0 -40
- django_cfg/modules/django_app_agent/services/context_builder/pattern_analyzer.py +0 -85
- django_cfg/modules/django_app_agent/services/project_scanner/__init__.py +0 -31
- django_cfg/modules/django_app_agent/services/project_scanner/app_discovery.py +0 -311
- django_cfg/modules/django_app_agent/services/project_scanner/main.py +0 -221
- django_cfg/modules/django_app_agent/services/project_scanner/models.py +0 -59
- django_cfg/modules/django_app_agent/services/project_scanner/pattern_detection.py +0 -94
- django_cfg/modules/django_app_agent/services/questioning_service/__init__.py +0 -28
- django_cfg/modules/django_app_agent/services/questioning_service/main.py +0 -273
- django_cfg/modules/django_app_agent/services/questioning_service/models.py +0 -111
- django_cfg/modules/django_app_agent/services/questioning_service/question_generator.py +0 -251
- django_cfg/modules/django_app_agent/services/questioning_service/response_processor.py +0 -347
- django_cfg/modules/django_app_agent/services/questioning_service/session_manager.py +0 -356
- django_cfg/modules/django_app_agent/services/report_service.py +0 -332
- django_cfg/modules/django_app_agent/services/template_manager/__init__.py +0 -18
- django_cfg/modules/django_app_agent/services/template_manager/jinja_engine.py +0 -236
- django_cfg/modules/django_app_agent/services/template_manager/main.py +0 -159
- django_cfg/modules/django_app_agent/services/template_manager/models.py +0 -36
- django_cfg/modules/django_app_agent/services/template_manager/template_loader.py +0 -100
- django_cfg/modules/django_app_agent/services/template_manager/templates/admin.py.j2 +0 -105
- django_cfg/modules/django_app_agent/services/template_manager/templates/apps.py.j2 +0 -31
- django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_config.py.j2 +0 -44
- django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_module.py.j2 +0 -81
- django_cfg/modules/django_app_agent/services/template_manager/templates/forms.py.j2 +0 -107
- django_cfg/modules/django_app_agent/services/template_manager/templates/models.py.j2 +0 -139
- django_cfg/modules/django_app_agent/services/template_manager/templates/serializers.py.j2 +0 -91
- django_cfg/modules/django_app_agent/services/template_manager/templates/tests.py.j2 +0 -195
- django_cfg/modules/django_app_agent/services/template_manager/templates/urls.py.j2 +0 -35
- django_cfg/modules/django_app_agent/services/template_manager/templates/views.py.j2 +0 -211
- django_cfg/modules/django_app_agent/services/template_manager/variable_processor.py +0 -200
- django_cfg/modules/django_app_agent/services/validation_service/__init__.py +0 -25
- django_cfg/modules/django_app_agent/services/validation_service/django_validator.py +0 -333
- django_cfg/modules/django_app_agent/services/validation_service/main.py +0 -242
- django_cfg/modules/django_app_agent/services/validation_service/models.py +0 -66
- django_cfg/modules/django_app_agent/services/validation_service/quality_validator.py +0 -352
- django_cfg/modules/django_app_agent/services/validation_service/security_validator.py +0 -272
- django_cfg/modules/django_app_agent/services/validation_service/syntax_validator.py +0 -203
- django_cfg/modules/django_app_agent/ui/__init__.py +0 -25
- django_cfg/modules/django_app_agent/ui/cli.py +0 -419
- django_cfg/modules/django_app_agent/ui/rich_components.py +0 -622
- django_cfg/modules/django_app_agent/utils/__init__.py +0 -38
- django_cfg/modules/django_app_agent/utils/logging.py +0 -360
- django_cfg/modules/django_app_agent/utils/validation.py +0 -417
- {django_cfg-1.3.9.dist-info → django_cfg-1.3.11.dist-info}/WHEEL +0 -0
- {django_cfg-1.3.9.dist-info → django_cfg-1.3.11.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.3.9.dist-info → django_cfg-1.3.11.dist-info}/licenses/LICENSE +0 -0
@@ -1,236 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Jinja2 Template Engine for Django App Agent.
|
3
|
-
|
4
|
-
This module provides a powerful Jinja2-based template engine
|
5
|
-
with custom filters and functions for Django code generation.
|
6
|
-
"""
|
7
|
-
|
8
|
-
from typing import Dict, Any, Set, Optional, List
|
9
|
-
import re
|
10
|
-
from pathlib import Path
|
11
|
-
|
12
|
-
from jinja2 import Environment, BaseLoader, TemplateNotFound, select_autoescape
|
13
|
-
from jinja2.exceptions import TemplateError
|
14
|
-
|
15
|
-
from ...core.exceptions import ValidationError
|
16
|
-
|
17
|
-
|
18
|
-
class StringTemplateLoader(BaseLoader):
|
19
|
-
"""Custom Jinja2 loader for string-based templates."""
|
20
|
-
|
21
|
-
def __init__(self, templates: Dict[str, str]):
|
22
|
-
"""Initialize with template dictionary."""
|
23
|
-
self.templates = templates
|
24
|
-
|
25
|
-
def get_source(self, environment: Environment, template: str) -> tuple:
|
26
|
-
"""Get template source."""
|
27
|
-
if template not in self.templates:
|
28
|
-
raise TemplateNotFound(template)
|
29
|
-
|
30
|
-
source = self.templates[template]
|
31
|
-
return source, None, lambda: True
|
32
|
-
|
33
|
-
|
34
|
-
class JinjaTemplateEngine:
|
35
|
-
"""Jinja2-based template engine with Django-specific features."""
|
36
|
-
|
37
|
-
def __init__(self):
|
38
|
-
"""Initialize Jinja2 environment with custom filters."""
|
39
|
-
self.templates: Dict[str, str] = {}
|
40
|
-
self.env = self._create_environment()
|
41
|
-
|
42
|
-
def _create_environment(self) -> Environment:
|
43
|
-
"""Create Jinja2 environment with custom filters and functions."""
|
44
|
-
env = Environment(
|
45
|
-
loader=StringTemplateLoader(self.templates),
|
46
|
-
autoescape=select_autoescape(['html', 'xml']),
|
47
|
-
trim_blocks=True,
|
48
|
-
lstrip_blocks=True
|
49
|
-
)
|
50
|
-
|
51
|
-
# Add custom filters
|
52
|
-
env.filters.update({
|
53
|
-
'snake_case': self._snake_case,
|
54
|
-
'camel_case': self._camel_case,
|
55
|
-
'pascal_case': self._pascal_case,
|
56
|
-
'kebab_case': self._kebab_case,
|
57
|
-
'title_case': self._title_case,
|
58
|
-
'plural': self._pluralize,
|
59
|
-
'singular': self._singularize,
|
60
|
-
'django_field': self._django_field_repr,
|
61
|
-
'python_repr': self._python_repr,
|
62
|
-
'indent': self._indent,
|
63
|
-
'comment_block': self._comment_block
|
64
|
-
})
|
65
|
-
|
66
|
-
# Add custom functions
|
67
|
-
env.globals.update({
|
68
|
-
'now': self._now,
|
69
|
-
'uuid4': self._uuid4,
|
70
|
-
'range': range,
|
71
|
-
'enumerate': enumerate,
|
72
|
-
'zip': zip
|
73
|
-
})
|
74
|
-
|
75
|
-
return env
|
76
|
-
|
77
|
-
def add_template(self, name: str, content: str) -> None:
|
78
|
-
"""Add a template to the engine."""
|
79
|
-
self.templates[name] = content
|
80
|
-
# Recreate environment to update loader
|
81
|
-
self.env = self._create_environment()
|
82
|
-
|
83
|
-
def add_templates(self, templates: Dict[str, str]) -> None:
|
84
|
-
"""Add multiple templates to the engine."""
|
85
|
-
self.templates.update(templates)
|
86
|
-
# Recreate environment to update loader
|
87
|
-
self.env = self._create_environment()
|
88
|
-
|
89
|
-
def render(
|
90
|
-
self,
|
91
|
-
template_name: str,
|
92
|
-
variables: Dict[str, Any]
|
93
|
-
) -> tuple[str, Set[str], Set[str]]:
|
94
|
-
"""
|
95
|
-
Render template with variables.
|
96
|
-
|
97
|
-
Returns:
|
98
|
-
tuple: (rendered_content, variables_used, missing_variables)
|
99
|
-
"""
|
100
|
-
try:
|
101
|
-
template = self.env.get_template(template_name)
|
102
|
-
|
103
|
-
# Get template variables (simplified approach - read template source from file)
|
104
|
-
template_vars = set()
|
105
|
-
try:
|
106
|
-
# Get template source from the loader
|
107
|
-
source, _ = self.env.loader.get_source(self.env, template_name)
|
108
|
-
ast = self.env.parse(source)
|
109
|
-
for node in ast.find_all('Name'):
|
110
|
-
if node.ctx == 'load':
|
111
|
-
template_vars.add(node.name)
|
112
|
-
except Exception:
|
113
|
-
# Fallback: assume all provided variables are used
|
114
|
-
template_vars = set(variables.keys())
|
115
|
-
|
116
|
-
# Remove Jinja2 built-ins and our custom functions
|
117
|
-
builtin_vars = {
|
118
|
-
'range', 'enumerate', 'zip', 'now', 'uuid4',
|
119
|
-
'loop', 'super', 'self', 'varargs', 'kwargs'
|
120
|
-
}
|
121
|
-
template_vars = template_vars - builtin_vars
|
122
|
-
|
123
|
-
# Check for missing variables
|
124
|
-
missing_vars = template_vars - set(variables.keys())
|
125
|
-
variables_used = template_vars - missing_vars
|
126
|
-
|
127
|
-
# Render template
|
128
|
-
rendered = template.render(**variables)
|
129
|
-
|
130
|
-
return rendered, variables_used, missing_vars
|
131
|
-
|
132
|
-
except TemplateNotFound:
|
133
|
-
raise ValidationError(
|
134
|
-
f"Template '{template_name}' not found",
|
135
|
-
validation_type="template_not_found"
|
136
|
-
)
|
137
|
-
except TemplateError as e:
|
138
|
-
raise ValidationError(
|
139
|
-
f"Template rendering failed: {e}",
|
140
|
-
validation_type="template_rendering"
|
141
|
-
)
|
142
|
-
|
143
|
-
# Custom filters
|
144
|
-
def _snake_case(self, text: str) -> str:
|
145
|
-
"""Convert text to snake_case."""
|
146
|
-
# Handle camelCase and PascalCase
|
147
|
-
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', text)
|
148
|
-
s2 = re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1)
|
149
|
-
return s2.lower().replace(' ', '_').replace('-', '_')
|
150
|
-
|
151
|
-
def _camel_case(self, text: str) -> str:
|
152
|
-
"""Convert text to camelCase."""
|
153
|
-
components = re.split(r'[_\s-]+', text.lower())
|
154
|
-
return components[0] + ''.join(word.capitalize() for word in components[1:])
|
155
|
-
|
156
|
-
def _pascal_case(self, text: str) -> str:
|
157
|
-
"""Convert text to PascalCase."""
|
158
|
-
components = re.split(r'[_\s-]+', text.lower())
|
159
|
-
return ''.join(word.capitalize() for word in components)
|
160
|
-
|
161
|
-
def _kebab_case(self, text: str) -> str:
|
162
|
-
"""Convert text to kebab-case."""
|
163
|
-
return self._snake_case(text).replace('_', '-')
|
164
|
-
|
165
|
-
def _title_case(self, text: str) -> str:
|
166
|
-
"""Convert text to Title Case."""
|
167
|
-
return text.replace('_', ' ').replace('-', ' ').title()
|
168
|
-
|
169
|
-
def _pluralize(self, text: str) -> str:
|
170
|
-
"""Simple pluralization."""
|
171
|
-
if text.endswith('y'):
|
172
|
-
return text[:-1] + 'ies'
|
173
|
-
elif text.endswith(('s', 'sh', 'ch', 'x', 'z')):
|
174
|
-
return text + 'es'
|
175
|
-
else:
|
176
|
-
return text + 's'
|
177
|
-
|
178
|
-
def _singularize(self, text: str) -> str:
|
179
|
-
"""Simple singularization."""
|
180
|
-
if text.endswith('ies'):
|
181
|
-
return text[:-3] + 'y'
|
182
|
-
elif text.endswith('es'):
|
183
|
-
return text[:-2]
|
184
|
-
elif text.endswith('s') and not text.endswith('ss'):
|
185
|
-
return text[:-1]
|
186
|
-
else:
|
187
|
-
return text
|
188
|
-
|
189
|
-
def _django_field_repr(self, field_type: str, **kwargs) -> str:
|
190
|
-
"""Generate Django field representation."""
|
191
|
-
args = []
|
192
|
-
for key, value in kwargs.items():
|
193
|
-
if isinstance(value, str):
|
194
|
-
args.append(f"{key}='{value}'")
|
195
|
-
else:
|
196
|
-
args.append(f"{key}={value}")
|
197
|
-
|
198
|
-
if args:
|
199
|
-
return f"models.{field_type}({', '.join(args)})"
|
200
|
-
else:
|
201
|
-
return f"models.{field_type}()"
|
202
|
-
|
203
|
-
def _python_repr(self, value: Any) -> str:
|
204
|
-
"""Python representation of value."""
|
205
|
-
return repr(value)
|
206
|
-
|
207
|
-
def _indent(self, text: str, width: int = 4, first: bool = False) -> str:
|
208
|
-
"""Indent text by specified width."""
|
209
|
-
lines = text.split('\n')
|
210
|
-
indent_str = ' ' * width
|
211
|
-
|
212
|
-
if first:
|
213
|
-
return '\n'.join(indent_str + line for line in lines)
|
214
|
-
else:
|
215
|
-
return lines[0] + '\n' + '\n'.join(indent_str + line for line in lines[1:])
|
216
|
-
|
217
|
-
def _comment_block(self, text: str, style: str = 'python') -> str:
|
218
|
-
"""Create comment block in specified style."""
|
219
|
-
if style == 'python':
|
220
|
-
lines = text.split('\n')
|
221
|
-
return '\n'.join(f'# {line}' for line in lines)
|
222
|
-
elif style == 'docstring':
|
223
|
-
return f'"""\n{text}\n"""'
|
224
|
-
else:
|
225
|
-
return text
|
226
|
-
|
227
|
-
# Custom functions
|
228
|
-
def _now(self) -> str:
|
229
|
-
"""Current timestamp."""
|
230
|
-
from datetime import datetime
|
231
|
-
return datetime.now().isoformat()
|
232
|
-
|
233
|
-
def _uuid4(self) -> str:
|
234
|
-
"""Generate UUID4."""
|
235
|
-
import uuid
|
236
|
-
return str(uuid.uuid4())
|
@@ -1,159 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Template Manager Service for Django App Agent Module.
|
3
|
-
|
4
|
-
This service provides sophisticated Jinja2-based template rendering
|
5
|
-
with feature-driven code generation capabilities.
|
6
|
-
"""
|
7
|
-
|
8
|
-
from typing import Dict, Any, Set, Optional, List
|
9
|
-
from pathlib import Path
|
10
|
-
|
11
|
-
from pydantic import BaseModel, Field
|
12
|
-
|
13
|
-
from ...core.config import AgentConfig
|
14
|
-
from ...core.exceptions import ValidationError
|
15
|
-
from ...models.enums import AppType, AppFeature
|
16
|
-
from ...models.requests import TemplateRequest
|
17
|
-
from ...models.responses import TemplateResult
|
18
|
-
from ..base import BaseService, ServiceDependencies
|
19
|
-
from .jinja_engine import JinjaTemplateEngine
|
20
|
-
from .template_loader import TemplateLoader
|
21
|
-
from .variable_processor import VariableProcessor
|
22
|
-
|
23
|
-
|
24
|
-
class TemplateManagerService(BaseService[TemplateRequest, TemplateResult]):
|
25
|
-
"""
|
26
|
-
Advanced template management service with Jinja2 support.
|
27
|
-
|
28
|
-
Features:
|
29
|
-
- Jinja2 template engine with custom filters
|
30
|
-
- File-based template loading
|
31
|
-
- Feature-driven template selection
|
32
|
-
- Variable processing and validation
|
33
|
-
- Template caching and optimization
|
34
|
-
"""
|
35
|
-
|
36
|
-
def __init__(self, config: AgentConfig):
|
37
|
-
"""Initialize template manager service."""
|
38
|
-
super().__init__("template_manager", config)
|
39
|
-
self.config = config
|
40
|
-
|
41
|
-
# Initialize components
|
42
|
-
self.template_loader = TemplateLoader()
|
43
|
-
self.jinja_engine = JinjaTemplateEngine()
|
44
|
-
self.variable_processor = VariableProcessor()
|
45
|
-
|
46
|
-
# Load all templates into engine
|
47
|
-
self._load_templates()
|
48
|
-
|
49
|
-
async def process(
|
50
|
-
self,
|
51
|
-
request: TemplateRequest,
|
52
|
-
dependencies: ServiceDependencies
|
53
|
-
) -> TemplateResult:
|
54
|
-
"""
|
55
|
-
Process template rendering request.
|
56
|
-
|
57
|
-
Args:
|
58
|
-
request: Template processing request
|
59
|
-
dependencies: Service dependencies
|
60
|
-
|
61
|
-
Returns:
|
62
|
-
TemplateResult with rendered content
|
63
|
-
"""
|
64
|
-
dependencies.log_operation(
|
65
|
-
f"Processing template '{request.template_name}'",
|
66
|
-
app_type=request.app_type if isinstance(request.app_type, str) else request.app_type.value,
|
67
|
-
features_count=len(request.features),
|
68
|
-
variables_count=len(request.variables)
|
69
|
-
)
|
70
|
-
|
71
|
-
try:
|
72
|
-
# Determine template name
|
73
|
-
template_name = self._resolve_template_name(request, dependencies)
|
74
|
-
|
75
|
-
# Process variables
|
76
|
-
processed_variables = await self.variable_processor.process_variables(
|
77
|
-
request, dependencies
|
78
|
-
)
|
79
|
-
|
80
|
-
# Render template
|
81
|
-
rendered_content, variables_used, missing_vars = self.jinja_engine.render(
|
82
|
-
template_name, processed_variables
|
83
|
-
)
|
84
|
-
|
85
|
-
# Create result
|
86
|
-
result = TemplateResult(
|
87
|
-
rendered_content=rendered_content,
|
88
|
-
template_name=template_name,
|
89
|
-
variables_used=list(variables_used),
|
90
|
-
missing_variables=list(missing_vars),
|
91
|
-
template_metadata={
|
92
|
-
"app_type": request.app_type if isinstance(request.app_type, str) else request.app_type.value,
|
93
|
-
"features": [(f.value if hasattr(f, 'value') else f) for f in request.features],
|
94
|
-
"template_engine": "jinja2",
|
95
|
-
"rendered_size": len(rendered_content),
|
96
|
-
"variables_processed": len(processed_variables)
|
97
|
-
}
|
98
|
-
)
|
99
|
-
|
100
|
-
dependencies.log_operation(
|
101
|
-
"Template processing completed successfully",
|
102
|
-
template_name=template_name,
|
103
|
-
rendered_size=len(rendered_content),
|
104
|
-
variables_used=len(variables_used),
|
105
|
-
missing_variables=len(missing_vars)
|
106
|
-
)
|
107
|
-
|
108
|
-
return result
|
109
|
-
|
110
|
-
except Exception as e:
|
111
|
-
dependencies.log_error("Template processing failed", e)
|
112
|
-
raise
|
113
|
-
|
114
|
-
def _load_templates(self) -> None:
|
115
|
-
"""Load all templates into the Jinja2 engine."""
|
116
|
-
templates = self.template_loader.load_all_templates()
|
117
|
-
self.jinja_engine.add_templates(templates)
|
118
|
-
|
119
|
-
def _resolve_template_name(
|
120
|
-
self,
|
121
|
-
request: TemplateRequest,
|
122
|
-
dependencies: ServiceDependencies
|
123
|
-
) -> str:
|
124
|
-
"""Resolve the actual template name to use."""
|
125
|
-
template_name = request.template_name
|
126
|
-
|
127
|
-
# If template_name doesn't end with .j2, add it
|
128
|
-
if not template_name.endswith('.j2'):
|
129
|
-
template_name = f"{template_name}.j2"
|
130
|
-
|
131
|
-
# Check if template exists
|
132
|
-
available_templates = self.template_loader.get_available_templates()
|
133
|
-
|
134
|
-
if template_name not in available_templates:
|
135
|
-
# Try app-type specific template
|
136
|
-
app_type_str = request.app_type if isinstance(request.app_type, str) else request.app_type.value
|
137
|
-
app_specific_name = f"{app_type_str}_{template_name}"
|
138
|
-
if app_specific_name in available_templates:
|
139
|
-
template_name = app_specific_name
|
140
|
-
else:
|
141
|
-
raise ValidationError(
|
142
|
-
f"Template '{template_name}' not found. Available templates: {available_templates}",
|
143
|
-
validation_type="template_not_found"
|
144
|
-
)
|
145
|
-
|
146
|
-
return template_name
|
147
|
-
|
148
|
-
def reload_templates(self) -> None:
|
149
|
-
"""Reload all templates from disk."""
|
150
|
-
self.template_loader.clear_cache()
|
151
|
-
self._load_templates()
|
152
|
-
|
153
|
-
def get_available_templates(self) -> List[str]:
|
154
|
-
"""Get list of available template names."""
|
155
|
-
return self.template_loader.get_available_templates()
|
156
|
-
|
157
|
-
def add_custom_template(self, name: str, content: str) -> None:
|
158
|
-
"""Add a custom template at runtime."""
|
159
|
-
self.jinja_engine.add_template(name, content)
|
@@ -1,36 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Data Models for Template Manager Service.
|
3
|
-
|
4
|
-
This module contains Pydantic models for template processing
|
5
|
-
requests, results, and related data structures.
|
6
|
-
"""
|
7
|
-
|
8
|
-
from typing import Dict, Any, Optional, List, Set
|
9
|
-
|
10
|
-
from pydantic import BaseModel, Field, ConfigDict
|
11
|
-
|
12
|
-
from ...models.enums import AppType, AppFeature
|
13
|
-
|
14
|
-
|
15
|
-
class TemplateRequest(BaseModel):
|
16
|
-
"""Request for template processing."""
|
17
|
-
|
18
|
-
model_config = ConfigDict(extra='forbid', validate_assignment=True)
|
19
|
-
|
20
|
-
template_name: str = Field(description="Name of the template to process")
|
21
|
-
app_type: AppType = Field(description="Type of application")
|
22
|
-
variables: Dict[str, Any] = Field(default_factory=dict, description="Template variables")
|
23
|
-
features: List[AppFeature] = Field(default_factory=list, description="Requested features")
|
24
|
-
custom_templates: Dict[str, str] = Field(default_factory=dict, description="Custom template overrides")
|
25
|
-
|
26
|
-
|
27
|
-
class TemplateResult(BaseModel):
|
28
|
-
"""Result of template processing."""
|
29
|
-
|
30
|
-
model_config = ConfigDict(extra='forbid', validate_assignment=True)
|
31
|
-
|
32
|
-
rendered_content: str = Field(description="Rendered template content")
|
33
|
-
template_name: str = Field(description="Name of the processed template")
|
34
|
-
variables_used: Set[str] = Field(default_factory=set, description="Variables that were used in rendering")
|
35
|
-
missing_variables: Set[str] = Field(default_factory=set, description="Variables that were missing")
|
36
|
-
template_metadata: Dict[str, Any] = Field(default_factory=dict, description="Template processing metadata")
|
@@ -1,100 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Template Loader for Django App Agent.
|
3
|
-
|
4
|
-
This module handles loading Jinja2 templates from files and
|
5
|
-
providing them to the template engine.
|
6
|
-
"""
|
7
|
-
|
8
|
-
from typing import Dict, Optional
|
9
|
-
from pathlib import Path
|
10
|
-
|
11
|
-
from pydantic import BaseModel, Field
|
12
|
-
|
13
|
-
from ...core.exceptions import ValidationError
|
14
|
-
|
15
|
-
|
16
|
-
class TemplateLoader(BaseModel):
|
17
|
-
"""Loads Jinja2 templates from the templates directory."""
|
18
|
-
|
19
|
-
templates_dir: Path = Field(description="Directory containing template files")
|
20
|
-
template_cache: Dict[str, str] = Field(default_factory=dict, description="Template cache")
|
21
|
-
|
22
|
-
def __init__(self, **data):
|
23
|
-
"""Initialize template loader."""
|
24
|
-
if 'templates_dir' not in data:
|
25
|
-
# Default to templates directory relative to this file
|
26
|
-
current_dir = Path(__file__).parent
|
27
|
-
data['templates_dir'] = current_dir / "templates"
|
28
|
-
|
29
|
-
super().__init__(**data)
|
30
|
-
|
31
|
-
# Validate templates directory exists
|
32
|
-
if not self.templates_dir.exists():
|
33
|
-
raise ValidationError(
|
34
|
-
f"Templates directory does not exist: {self.templates_dir}",
|
35
|
-
validation_type="template_directory"
|
36
|
-
)
|
37
|
-
|
38
|
-
def load_template(self, template_name: str) -> str:
|
39
|
-
"""Load a template by name."""
|
40
|
-
# Check cache first
|
41
|
-
if template_name in self.template_cache:
|
42
|
-
return self.template_cache[template_name]
|
43
|
-
|
44
|
-
# Try to load from file
|
45
|
-
template_path = self.templates_dir / template_name
|
46
|
-
|
47
|
-
if not template_path.exists():
|
48
|
-
# Try with .j2 extension if not provided
|
49
|
-
if not template_name.endswith('.j2'):
|
50
|
-
template_path = self.templates_dir / f"{template_name}.j2"
|
51
|
-
|
52
|
-
if not template_path.exists():
|
53
|
-
raise ValidationError(
|
54
|
-
f"Template file not found: {template_name}",
|
55
|
-
validation_type="template_not_found"
|
56
|
-
)
|
57
|
-
|
58
|
-
try:
|
59
|
-
content = template_path.read_text(encoding='utf-8')
|
60
|
-
# Cache the template
|
61
|
-
self.template_cache[template_name] = content
|
62
|
-
return content
|
63
|
-
|
64
|
-
except Exception as e:
|
65
|
-
raise ValidationError(
|
66
|
-
f"Failed to read template file {template_name}: {e}",
|
67
|
-
validation_type="template_read_error"
|
68
|
-
)
|
69
|
-
|
70
|
-
def load_all_templates(self) -> Dict[str, str]:
|
71
|
-
"""Load all templates from the templates directory."""
|
72
|
-
templates = {}
|
73
|
-
|
74
|
-
for template_path in self.templates_dir.glob("*.j2"):
|
75
|
-
template_name = template_path.name
|
76
|
-
try:
|
77
|
-
content = self.load_template(template_name)
|
78
|
-
templates[template_name] = content
|
79
|
-
except ValidationError:
|
80
|
-
# Skip templates that can't be loaded
|
81
|
-
continue
|
82
|
-
|
83
|
-
return templates
|
84
|
-
|
85
|
-
def get_available_templates(self) -> list[str]:
|
86
|
-
"""Get list of available template names."""
|
87
|
-
return [p.name for p in self.templates_dir.glob("*.j2")]
|
88
|
-
|
89
|
-
def clear_cache(self) -> None:
|
90
|
-
"""Clear the template cache."""
|
91
|
-
self.template_cache.clear()
|
92
|
-
|
93
|
-
def reload_template(self, template_name: str) -> str:
|
94
|
-
"""Reload a template, bypassing cache."""
|
95
|
-
# Remove from cache if present
|
96
|
-
if template_name in self.template_cache:
|
97
|
-
del self.template_cache[template_name]
|
98
|
-
|
99
|
-
# Load fresh copy
|
100
|
-
return self.load_template(template_name)
|
@@ -1,105 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Admin configuration for {{ app_name }} application.
|
3
|
-
|
4
|
-
{{ description }}
|
5
|
-
"""
|
6
|
-
|
7
|
-
from django.contrib import admin
|
8
|
-
{% if features.advanced_admin %}
|
9
|
-
from django.utils.html import format_html
|
10
|
-
from django.urls import reverse
|
11
|
-
from django.utils.safestring import mark_safe
|
12
|
-
{% endif %}
|
13
|
-
from .models import {{ app_name|pascal_case }}Model
|
14
|
-
{% if features.related_models %}
|
15
|
-
from .models import {{ app_name|pascal_case }}Category, {{ app_name|pascal_case }}Tag
|
16
|
-
{% endif %}
|
17
|
-
|
18
|
-
|
19
|
-
@admin.register({{ app_name|pascal_case }}Model)
|
20
|
-
class {{ app_name|pascal_case }}Admin(admin.ModelAdmin):
|
21
|
-
"""Admin interface for {{ app_name }} model."""
|
22
|
-
|
23
|
-
list_display = [
|
24
|
-
'name',
|
25
|
-
{% if features.status_tracking %}'status', {% endif %}
|
26
|
-
{% if features.user_relations %}'owner', {% endif %}
|
27
|
-
'created_at',
|
28
|
-
'updated_at'
|
29
|
-
]
|
30
|
-
|
31
|
-
list_filter = [
|
32
|
-
{% if features.status_tracking %}'status', {% endif %}
|
33
|
-
'created_at',
|
34
|
-
{% if features.user_relations %}'owner', {% endif %}
|
35
|
-
]
|
36
|
-
|
37
|
-
search_fields = ['name', 'description']
|
38
|
-
|
39
|
-
{% if features.status_tracking %}
|
40
|
-
list_editable = ['status']
|
41
|
-
{% endif %}
|
42
|
-
|
43
|
-
readonly_fields = ['created_at', 'updated_at']
|
44
|
-
|
45
|
-
{% if features.advanced_admin %}
|
46
|
-
fieldsets = (
|
47
|
-
('Basic Information', {
|
48
|
-
'fields': ('name', 'description')
|
49
|
-
}),
|
50
|
-
{% if features.status_tracking %}
|
51
|
-
('Status', {
|
52
|
-
'fields': ('status',)
|
53
|
-
}),
|
54
|
-
{% endif %}
|
55
|
-
{% if features.user_relations %}
|
56
|
-
('Ownership', {
|
57
|
-
'fields': ('owner',)
|
58
|
-
}),
|
59
|
-
{% endif %}
|
60
|
-
('Timestamps', {
|
61
|
-
'fields': ('created_at', 'updated_at'),
|
62
|
-
'classes': ('collapse',)
|
63
|
-
}),
|
64
|
-
)
|
65
|
-
{% endif %}
|
66
|
-
|
67
|
-
{% if features.user_relations %}
|
68
|
-
def save_model(self, request, obj, form, change):
|
69
|
-
if not change: # Creating new object
|
70
|
-
obj.owner = request.user
|
71
|
-
super().save_model(request, obj, form, change)
|
72
|
-
|
73
|
-
def get_queryset(self, request):
|
74
|
-
qs = super().get_queryset(request)
|
75
|
-
if request.user.is_superuser:
|
76
|
-
return qs
|
77
|
-
return qs.filter(owner=request.user)
|
78
|
-
{% endif %}
|
79
|
-
|
80
|
-
{% if features.advanced_admin %}
|
81
|
-
def get_readonly_fields(self, request, obj=None):
|
82
|
-
if obj: # Editing existing object
|
83
|
-
return self.readonly_fields + ['name']
|
84
|
-
return self.readonly_fields
|
85
|
-
{% endif %}
|
86
|
-
|
87
|
-
|
88
|
-
{% if features.related_models %}
|
89
|
-
@admin.register({{ app_name|pascal_case }}Category)
|
90
|
-
class {{ app_name|pascal_case }}CategoryAdmin(admin.ModelAdmin):
|
91
|
-
"""Admin interface for {{ app_name }} categories."""
|
92
|
-
|
93
|
-
list_display = ['name', 'slug', 'description']
|
94
|
-
search_fields = ['name', 'description']
|
95
|
-
prepopulated_fields = {'slug': ('name',)}
|
96
|
-
|
97
|
-
|
98
|
-
@admin.register({{ app_name|pascal_case }}Tag)
|
99
|
-
class {{ app_name|pascal_case }}TagAdmin(admin.ModelAdmin):
|
100
|
-
"""Admin interface for {{ app_name }} tags."""
|
101
|
-
|
102
|
-
list_display = ['name', 'color']
|
103
|
-
search_fields = ['name']
|
104
|
-
list_editable = ['color']
|
105
|
-
{% endif %}
|
@@ -1,31 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
App configuration for {{ app_name }}.
|
3
|
-
|
4
|
-
{{ description }}
|
5
|
-
"""
|
6
|
-
|
7
|
-
from django.apps import AppConfig
|
8
|
-
{% if app_type == 'django_cfg' %}
|
9
|
-
from django_cfg.apps import BaseCfgAppConfig
|
10
|
-
{% endif %}
|
11
|
-
|
12
|
-
|
13
|
-
{% if app_type == 'django_cfg' %}
|
14
|
-
class {{ app_name|pascal_case }}Config(BaseCfgAppConfig):
|
15
|
-
{% else %}
|
16
|
-
class {{ app_name|pascal_case }}Config(AppConfig):
|
17
|
-
{% endif %}
|
18
|
-
"""Configuration for {{ app_name }} application."""
|
19
|
-
|
20
|
-
default_auto_field = 'django.db.models.BigAutoField'
|
21
|
-
name = '{{ app_name }}'
|
22
|
-
verbose_name = '{{ app_name|title_case }}'
|
23
|
-
|
24
|
-
{% if features.signals %}
|
25
|
-
def ready(self):
|
26
|
-
"""Import signals when app is ready."""
|
27
|
-
try:
|
28
|
-
import {{ app_name }}.signals # noqa F401
|
29
|
-
except ImportError:
|
30
|
-
pass
|
31
|
-
{% endif %}
|