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.
Files changed (187) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/apps/payments/admin/networks_admin.py +12 -1
  3. django_cfg/apps/payments/admin/payments_admin.py +13 -0
  4. django_cfg/apps/payments/admin_interface/serializers/payment_serializers.py +62 -14
  5. django_cfg/apps/payments/admin_interface/templates/payments/components/payment_card.html +121 -0
  6. django_cfg/apps/payments/admin_interface/templates/payments/components/payment_qr_code.html +95 -0
  7. django_cfg/apps/payments/admin_interface/templates/payments/components/progress_bar.html +37 -0
  8. django_cfg/apps/payments/admin_interface/templates/payments/components/provider_stats.html +60 -0
  9. django_cfg/apps/payments/admin_interface/templates/payments/components/status_badge.html +41 -0
  10. django_cfg/apps/payments/admin_interface/templates/payments/components/status_overview.html +83 -0
  11. django_cfg/apps/payments/admin_interface/templates/payments/payment_detail.html +363 -0
  12. django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +33 -3
  13. django_cfg/apps/payments/admin_interface/views/api/payments.py +102 -0
  14. django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +96 -45
  15. django_cfg/apps/payments/admin_interface/views/forms.py +5 -1
  16. django_cfg/apps/payments/config/__init__.py +14 -15
  17. django_cfg/apps/payments/config/django_cfg_integration.py +59 -1
  18. django_cfg/apps/payments/config/helpers.py +8 -13
  19. django_cfg/apps/payments/migrations/0001_initial.py +33 -46
  20. django_cfg/apps/payments/migrations/0002_rename_payments_un_user_id_7f6e79_idx_payments_un_user_id_8ce187_idx_and_more.py +46 -0
  21. django_cfg/apps/payments/migrations/0003_universalpayment_status_changed_at.py +25 -0
  22. django_cfg/apps/payments/models/managers/payment_managers.py +142 -25
  23. django_cfg/apps/payments/models/payments.py +94 -0
  24. django_cfg/apps/payments/services/core/base.py +4 -4
  25. django_cfg/apps/payments/services/core/payment_service.py +265 -38
  26. django_cfg/apps/payments/services/providers/base.py +209 -3
  27. django_cfg/apps/payments/services/providers/models/__init__.py +2 -0
  28. django_cfg/apps/payments/services/providers/models/base.py +25 -2
  29. django_cfg/apps/payments/services/providers/nowpayments/models.py +2 -2
  30. django_cfg/apps/payments/services/providers/nowpayments/provider.py +57 -9
  31. django_cfg/apps/payments/services/providers/registry.py +5 -5
  32. django_cfg/apps/payments/services/types/requests.py +19 -7
  33. django_cfg/apps/payments/signals/payment_signals.py +31 -2
  34. django_cfg/apps/payments/static/payments/js/api-client.js +6 -1
  35. django_cfg/apps/payments/static/payments/js/payment-detail.js +167 -0
  36. django_cfg/apps/payments/static/payments/js/payment-form.js +35 -26
  37. django_cfg/apps/payments/templatetags/payment_tags.py +8 -0
  38. django_cfg/apps/payments/urls.py +3 -2
  39. django_cfg/apps/payments/views/api/currencies.py +3 -0
  40. django_cfg/apps/payments/views/serializers/currencies.py +18 -5
  41. django_cfg/apps/tasks/admin/tasks_admin.py +2 -2
  42. django_cfg/apps/tasks/static/tasks/css/dashboard.css +68 -217
  43. django_cfg/apps/tasks/static/tasks/js/api.js +40 -84
  44. django_cfg/apps/tasks/static/tasks/js/components/DataManager.js +24 -0
  45. django_cfg/apps/tasks/static/tasks/js/components/TabManager.js +85 -0
  46. django_cfg/apps/tasks/static/tasks/js/components/TaskRenderer.js +216 -0
  47. django_cfg/apps/tasks/static/tasks/js/dashboard/main.mjs +245 -0
  48. django_cfg/apps/tasks/static/tasks/js/dashboard/overview.mjs +123 -0
  49. django_cfg/apps/tasks/static/tasks/js/dashboard/queues.mjs +120 -0
  50. django_cfg/apps/tasks/static/tasks/js/dashboard/tasks.mjs +350 -0
  51. django_cfg/apps/tasks/static/tasks/js/dashboard/workers.mjs +169 -0
  52. django_cfg/apps/tasks/tasks/__init__.py +10 -0
  53. django_cfg/apps/tasks/tasks/demo_tasks.py +133 -0
  54. django_cfg/apps/tasks/templates/tasks/components/management_actions.html +42 -45
  55. django_cfg/apps/tasks/templates/tasks/components/{status_cards.html → overview_content.html} +30 -11
  56. django_cfg/apps/tasks/templates/tasks/components/queues_content.html +19 -0
  57. django_cfg/apps/tasks/templates/tasks/components/tab_navigation.html +16 -10
  58. django_cfg/apps/tasks/templates/tasks/components/tasks_content.html +51 -0
  59. django_cfg/apps/tasks/templates/tasks/components/workers_content.html +30 -0
  60. django_cfg/apps/tasks/templates/tasks/layout/base.html +117 -0
  61. django_cfg/apps/tasks/templates/tasks/pages/dashboard.html +82 -0
  62. django_cfg/apps/tasks/templates/tasks/partials/task_row_template.html +40 -0
  63. django_cfg/apps/tasks/templates/tasks/widgets/task_filters.html +37 -0
  64. django_cfg/apps/tasks/templates/tasks/widgets/task_footer.html +41 -0
  65. django_cfg/apps/tasks/templates/tasks/widgets/task_table.html +50 -0
  66. django_cfg/apps/tasks/urls.py +2 -2
  67. django_cfg/apps/tasks/urls_admin.py +2 -2
  68. django_cfg/apps/tasks/utils/__init__.py +1 -0
  69. django_cfg/apps/tasks/utils/simulator.py +356 -0
  70. django_cfg/apps/tasks/views/__init__.py +16 -0
  71. django_cfg/apps/tasks/views/api.py +569 -0
  72. django_cfg/apps/tasks/views/dashboard.py +58 -0
  73. django_cfg/core/integration/__init__.py +21 -0
  74. django_cfg/management/commands/rundramatiq_simulator.py +430 -0
  75. django_cfg/models/constance.py +0 -11
  76. django_cfg/models/payments.py +137 -3
  77. django_cfg/modules/django_tasks.py +54 -21
  78. django_cfg/registry/core.py +4 -9
  79. django_cfg/template_archive/django_sample.zip +0 -0
  80. {django_cfg-1.3.9.dist-info → django_cfg-1.3.11.dist-info}/METADATA +2 -2
  81. {django_cfg-1.3.9.dist-info → django_cfg-1.3.11.dist-info}/RECORD +84 -152
  82. django_cfg/apps/payments/config/constance/__init__.py +0 -22
  83. django_cfg/apps/payments/config/constance/config_service.py +0 -123
  84. django_cfg/apps/payments/config/constance/fields.py +0 -69
  85. django_cfg/apps/payments/config/constance/settings.py +0 -160
  86. django_cfg/apps/payments/migrations/0002_currency_usd_rate_currency_usd_rate_updated_at.py +0 -26
  87. django_cfg/apps/payments/migrations/0003_remove_provider_currency_fields.py +0 -28
  88. django_cfg/apps/payments/migrations/0004_add_reserved_usd_field.py +0 -30
  89. django_cfg/apps/tasks/static/tasks/js/dashboard.js +0 -614
  90. django_cfg/apps/tasks/static/tasks/js/modals.js +0 -452
  91. django_cfg/apps/tasks/static/tasks/js/notifications.js +0 -144
  92. django_cfg/apps/tasks/static/tasks/js/task-monitor.js +0 -454
  93. django_cfg/apps/tasks/static/tasks/js/theme.js +0 -77
  94. django_cfg/apps/tasks/templates/tasks/base.html +0 -96
  95. django_cfg/apps/tasks/templates/tasks/components/info_cards.html +0 -85
  96. django_cfg/apps/tasks/templates/tasks/components/overview_tab.html +0 -22
  97. django_cfg/apps/tasks/templates/tasks/components/queues_tab.html +0 -19
  98. django_cfg/apps/tasks/templates/tasks/components/task_details_modal.html +0 -103
  99. django_cfg/apps/tasks/templates/tasks/components/tasks_tab.html +0 -32
  100. django_cfg/apps/tasks/templates/tasks/components/workers_tab.html +0 -29
  101. django_cfg/apps/tasks/templates/tasks/dashboard.html +0 -29
  102. django_cfg/apps/tasks/views.py +0 -461
  103. django_cfg/management/commands/app_agent_diagnose.py +0 -470
  104. django_cfg/management/commands/app_agent_generate.py +0 -342
  105. django_cfg/management/commands/app_agent_info.py +0 -308
  106. django_cfg/management/commands/auto_generate.py +0 -486
  107. django_cfg/modules/django_app_agent/__init__.py +0 -87
  108. django_cfg/modules/django_app_agent/agents/__init__.py +0 -40
  109. django_cfg/modules/django_app_agent/agents/base/__init__.py +0 -24
  110. django_cfg/modules/django_app_agent/agents/base/agent.py +0 -354
  111. django_cfg/modules/django_app_agent/agents/base/context.py +0 -236
  112. django_cfg/modules/django_app_agent/agents/base/executor.py +0 -430
  113. django_cfg/modules/django_app_agent/agents/generation/__init__.py +0 -12
  114. django_cfg/modules/django_app_agent/agents/generation/app_generator/__init__.py +0 -15
  115. django_cfg/modules/django_app_agent/agents/generation/app_generator/config_validator.py +0 -147
  116. django_cfg/modules/django_app_agent/agents/generation/app_generator/main.py +0 -99
  117. django_cfg/modules/django_app_agent/agents/generation/app_generator/models.py +0 -32
  118. django_cfg/modules/django_app_agent/agents/generation/app_generator/prompt_manager.py +0 -290
  119. django_cfg/modules/django_app_agent/agents/interfaces.py +0 -376
  120. django_cfg/modules/django_app_agent/core/__init__.py +0 -33
  121. django_cfg/modules/django_app_agent/core/config.py +0 -300
  122. django_cfg/modules/django_app_agent/core/exceptions.py +0 -359
  123. django_cfg/modules/django_app_agent/models/__init__.py +0 -71
  124. django_cfg/modules/django_app_agent/models/base.py +0 -283
  125. django_cfg/modules/django_app_agent/models/context.py +0 -496
  126. django_cfg/modules/django_app_agent/models/enums.py +0 -481
  127. django_cfg/modules/django_app_agent/models/requests.py +0 -500
  128. django_cfg/modules/django_app_agent/models/responses.py +0 -585
  129. django_cfg/modules/django_app_agent/pytest.ini +0 -6
  130. django_cfg/modules/django_app_agent/services/__init__.py +0 -42
  131. django_cfg/modules/django_app_agent/services/app_generator/__init__.py +0 -30
  132. django_cfg/modules/django_app_agent/services/app_generator/ai_integration.py +0 -133
  133. django_cfg/modules/django_app_agent/services/app_generator/context.py +0 -40
  134. django_cfg/modules/django_app_agent/services/app_generator/main.py +0 -202
  135. django_cfg/modules/django_app_agent/services/app_generator/structure.py +0 -316
  136. django_cfg/modules/django_app_agent/services/app_generator/validation.py +0 -125
  137. django_cfg/modules/django_app_agent/services/base.py +0 -437
  138. django_cfg/modules/django_app_agent/services/context_builder/__init__.py +0 -34
  139. django_cfg/modules/django_app_agent/services/context_builder/code_extractor.py +0 -141
  140. django_cfg/modules/django_app_agent/services/context_builder/context_generator.py +0 -276
  141. django_cfg/modules/django_app_agent/services/context_builder/main.py +0 -272
  142. django_cfg/modules/django_app_agent/services/context_builder/models.py +0 -40
  143. django_cfg/modules/django_app_agent/services/context_builder/pattern_analyzer.py +0 -85
  144. django_cfg/modules/django_app_agent/services/project_scanner/__init__.py +0 -31
  145. django_cfg/modules/django_app_agent/services/project_scanner/app_discovery.py +0 -311
  146. django_cfg/modules/django_app_agent/services/project_scanner/main.py +0 -221
  147. django_cfg/modules/django_app_agent/services/project_scanner/models.py +0 -59
  148. django_cfg/modules/django_app_agent/services/project_scanner/pattern_detection.py +0 -94
  149. django_cfg/modules/django_app_agent/services/questioning_service/__init__.py +0 -28
  150. django_cfg/modules/django_app_agent/services/questioning_service/main.py +0 -273
  151. django_cfg/modules/django_app_agent/services/questioning_service/models.py +0 -111
  152. django_cfg/modules/django_app_agent/services/questioning_service/question_generator.py +0 -251
  153. django_cfg/modules/django_app_agent/services/questioning_service/response_processor.py +0 -347
  154. django_cfg/modules/django_app_agent/services/questioning_service/session_manager.py +0 -356
  155. django_cfg/modules/django_app_agent/services/report_service.py +0 -332
  156. django_cfg/modules/django_app_agent/services/template_manager/__init__.py +0 -18
  157. django_cfg/modules/django_app_agent/services/template_manager/jinja_engine.py +0 -236
  158. django_cfg/modules/django_app_agent/services/template_manager/main.py +0 -159
  159. django_cfg/modules/django_app_agent/services/template_manager/models.py +0 -36
  160. django_cfg/modules/django_app_agent/services/template_manager/template_loader.py +0 -100
  161. django_cfg/modules/django_app_agent/services/template_manager/templates/admin.py.j2 +0 -105
  162. django_cfg/modules/django_app_agent/services/template_manager/templates/apps.py.j2 +0 -31
  163. django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_config.py.j2 +0 -44
  164. django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_module.py.j2 +0 -81
  165. django_cfg/modules/django_app_agent/services/template_manager/templates/forms.py.j2 +0 -107
  166. django_cfg/modules/django_app_agent/services/template_manager/templates/models.py.j2 +0 -139
  167. django_cfg/modules/django_app_agent/services/template_manager/templates/serializers.py.j2 +0 -91
  168. django_cfg/modules/django_app_agent/services/template_manager/templates/tests.py.j2 +0 -195
  169. django_cfg/modules/django_app_agent/services/template_manager/templates/urls.py.j2 +0 -35
  170. django_cfg/modules/django_app_agent/services/template_manager/templates/views.py.j2 +0 -211
  171. django_cfg/modules/django_app_agent/services/template_manager/variable_processor.py +0 -200
  172. django_cfg/modules/django_app_agent/services/validation_service/__init__.py +0 -25
  173. django_cfg/modules/django_app_agent/services/validation_service/django_validator.py +0 -333
  174. django_cfg/modules/django_app_agent/services/validation_service/main.py +0 -242
  175. django_cfg/modules/django_app_agent/services/validation_service/models.py +0 -66
  176. django_cfg/modules/django_app_agent/services/validation_service/quality_validator.py +0 -352
  177. django_cfg/modules/django_app_agent/services/validation_service/security_validator.py +0 -272
  178. django_cfg/modules/django_app_agent/services/validation_service/syntax_validator.py +0 -203
  179. django_cfg/modules/django_app_agent/ui/__init__.py +0 -25
  180. django_cfg/modules/django_app_agent/ui/cli.py +0 -419
  181. django_cfg/modules/django_app_agent/ui/rich_components.py +0 -622
  182. django_cfg/modules/django_app_agent/utils/__init__.py +0 -38
  183. django_cfg/modules/django_app_agent/utils/logging.py +0 -360
  184. django_cfg/modules/django_app_agent/utils/validation.py +0 -417
  185. {django_cfg-1.3.9.dist-info → django_cfg-1.3.11.dist-info}/WHEEL +0 -0
  186. {django_cfg-1.3.9.dist-info → django_cfg-1.3.11.dist-info}/entry_points.txt +0 -0
  187. {django_cfg-1.3.9.dist-info → django_cfg-1.3.11.dist-info}/licenses/LICENSE +0 -0
@@ -1,203 +0,0 @@
1
- """
2
- Syntax Validator for Django App Agent.
3
-
4
- This module provides Python syntax validation and AST analysis
5
- for generated code files.
6
- """
7
-
8
- from typing import List, Dict, Any, Optional
9
- import ast
10
- import re
11
-
12
- from pydantic import BaseModel, Field
13
-
14
- from ...models.responses import GeneratedFile
15
- from ..base import ServiceDependencies
16
- from .models import ValidationIssue
17
-
18
-
19
- class SyntaxValidator(BaseModel):
20
- """Validates Python syntax and performs AST analysis."""
21
-
22
- syntax_rules: Dict[str, Dict[str, Any]] = Field(
23
- default_factory=lambda: {
24
- "valid_python": {
25
- "description": "Code must be valid Python syntax",
26
- "severity": "error"
27
- },
28
- "no_syntax_errors": {
29
- "description": "No syntax errors allowed",
30
- "severity": "error"
31
- },
32
- "proper_indentation": {
33
- "description": "Code must use consistent indentation",
34
- "severity": "warning"
35
- },
36
- "no_unused_imports": {
37
- "description": "No unused imports allowed",
38
- "severity": "warning"
39
- }
40
- },
41
- description="Syntax validation rules"
42
- )
43
-
44
- async def validate_syntax(
45
- self,
46
- file: GeneratedFile,
47
- dependencies: ServiceDependencies
48
- ) -> List[ValidationIssue]:
49
- """Validate Python syntax for a single file."""
50
- issues = []
51
-
52
- if file.file_type != "python":
53
- return issues
54
-
55
- try:
56
- # Parse the AST
57
- tree = ast.parse(file.content)
58
-
59
- # Check for syntax issues
60
- issues.extend(self._check_ast_structure(file, tree, dependencies))
61
- issues.extend(self._check_imports(file, tree, dependencies))
62
- issues.extend(self._check_indentation(file, dependencies))
63
-
64
- except SyntaxError as e:
65
- issues.append(ValidationIssue(
66
- severity="error",
67
- category="syntax",
68
- message=f"Syntax error: {e.msg}",
69
- file_path=file.path,
70
- line_number=e.lineno or 1,
71
- column=e.offset,
72
- rule_id="syntax_error",
73
- suggestion="Fix the syntax error according to Python grammar rules"
74
- ))
75
- except Exception as e:
76
- issues.append(ValidationIssue(
77
- severity="error",
78
- category="syntax",
79
- message=f"Failed to parse file: {e}",
80
- file_path=file.path,
81
- line_number=1,
82
- rule_id="parse_error"
83
- ))
84
-
85
- return issues
86
-
87
- def _check_ast_structure(
88
- self,
89
- file: GeneratedFile,
90
- tree: ast.AST,
91
- dependencies: ServiceDependencies
92
- ) -> List[ValidationIssue]:
93
- """Check AST structure for common issues."""
94
- issues = []
95
-
96
- # Check for empty classes/functions
97
- for node in ast.walk(tree):
98
- if isinstance(node, (ast.ClassDef, ast.FunctionDef, ast.AsyncFunctionDef)):
99
- if len(node.body) == 1 and isinstance(node.body[0], ast.Pass):
100
- issues.append(ValidationIssue(
101
- severity="warning",
102
- category="syntax",
103
- message=f"Empty {type(node).__name__.lower()} '{node.name}' with only 'pass'",
104
- file_path=file.path,
105
- line_number=node.lineno,
106
- rule_id="empty_definition",
107
- suggestion=f"Add implementation or docstring to {node.name}"
108
- ))
109
-
110
- return issues
111
-
112
- def _check_imports(
113
- self,
114
- file: GeneratedFile,
115
- tree: ast.AST,
116
- dependencies: ServiceDependencies
117
- ) -> List[ValidationIssue]:
118
- """Check import statements for issues."""
119
- issues = []
120
-
121
- # Collect all imports and their usage
122
- imports = set()
123
- used_names = set()
124
-
125
- for node in ast.walk(tree):
126
- if isinstance(node, ast.Import):
127
- for alias in node.names:
128
- import_name = alias.asname or alias.name
129
- imports.add(import_name)
130
- elif isinstance(node, ast.ImportFrom):
131
- for alias in node.names:
132
- import_name = alias.asname or alias.name
133
- imports.add(import_name)
134
- elif isinstance(node, ast.Name):
135
- used_names.add(node.id)
136
- elif isinstance(node, ast.Attribute):
137
- # Handle attribute access like 'models.Model'
138
- if isinstance(node.value, ast.Name):
139
- used_names.add(node.value.id)
140
-
141
- # Check for unused imports
142
- unused_imports = imports - used_names
143
- for unused in unused_imports:
144
- # Skip common Django imports that might be used in templates
145
- if unused not in ['models', 'admin', 'forms', 'serializers']:
146
- issues.append(ValidationIssue(
147
- severity="warning",
148
- category="syntax",
149
- message=f"Unused import: {unused}",
150
- file_path=file.path,
151
- line_number=1, # Would need more sophisticated tracking for exact line
152
- rule_id="unused_import",
153
- suggestion=f"Remove unused import '{unused}' or use it in the code"
154
- ))
155
-
156
- return issues
157
-
158
- def _check_indentation(
159
- self,
160
- file: GeneratedFile,
161
- dependencies: ServiceDependencies
162
- ) -> List[ValidationIssue]:
163
- """Check for consistent indentation."""
164
- issues = []
165
- lines = file.content.split('\n')
166
-
167
- # Check for mixed tabs and spaces
168
- has_tabs = any('\t' in line for line in lines)
169
- has_spaces = any(line.startswith(' ') for line in lines)
170
-
171
- if has_tabs and has_spaces:
172
- issues.append(ValidationIssue(
173
- severity="warning",
174
- category="syntax",
175
- message="Mixed tabs and spaces for indentation",
176
- file_path=file.path,
177
- line_number=1,
178
- rule_id="mixed_indentation",
179
- suggestion="Use consistent indentation (preferably 4 spaces)"
180
- ))
181
-
182
- # Check for inconsistent indentation levels
183
- indent_levels = set()
184
- for i, line in enumerate(lines, 1):
185
- if line.strip(): # Skip empty lines
186
- leading_spaces = len(line) - len(line.lstrip(' '))
187
- if leading_spaces > 0:
188
- indent_levels.add(leading_spaces)
189
-
190
- # Check if indentation follows 4-space rule
191
- non_standard_indents = [level for level in indent_levels if level % 4 != 0]
192
- if non_standard_indents:
193
- issues.append(ValidationIssue(
194
- severity="info",
195
- category="syntax",
196
- message=f"Non-standard indentation levels found: {non_standard_indents}",
197
- file_path=file.path,
198
- line_number=1,
199
- rule_id="non_standard_indent",
200
- suggestion="Use 4-space indentation consistently"
201
- ))
202
-
203
- return issues
@@ -1,25 +0,0 @@
1
- """
2
- User Interface Components for Django App Agent Module.
3
-
4
- This module provides rich terminal UI components using Rich library
5
- for beautiful and interactive command-line interfaces.
6
- """
7
-
8
- from .cli import DjangoAppAgentCLI
9
- from .rich_components import (
10
- RichProgressTracker,
11
- RichQuestionInterface,
12
- RichErrorDisplay,
13
- RichStatusDisplay
14
- )
15
-
16
- __all__ = [
17
- # Main CLI interface
18
- "DjangoAppAgentCLI",
19
-
20
- # Rich UI components
21
- "RichProgressTracker",
22
- "RichQuestionInterface",
23
- "RichErrorDisplay",
24
- "RichStatusDisplay",
25
- ]
@@ -1,419 +0,0 @@
1
- """
2
- Main CLI Interface for Django App Agent Module.
3
-
4
- This module provides the primary command-line interface using Click
5
- with Rich integration for beautiful terminal output.
6
- """
7
-
8
- from typing import Optional, List, Dict, Any
9
- from pathlib import Path
10
- import asyncio
11
- import sys
12
-
13
- import click
14
- from rich.console import Console
15
- from rich.panel import Panel
16
- from rich.text import Text
17
- from rich.prompt import Prompt, Confirm
18
- from rich.table import Table
19
-
20
- from ..core.config import AgentConfig
21
- from ..models.requests import AppGenerationRequest
22
- from ..models.enums import AppType, AppComplexity, AppFeature
23
- from ..services.app_generator import AppGeneratorService
24
- from ..services.project_scanner import ProjectScannerService
25
- from ..services.base import create_service_dependencies
26
- from ..utils.logging import get_logger
27
- from .rich_components import RichProgressTracker, RichQuestionInterface, RichErrorDisplay
28
-
29
-
30
- class DjangoAppAgentCLI:
31
- """
32
- Main CLI interface for Django App Agent.
33
-
34
- Provides commands for:
35
- - Interactive application generation
36
- - Project scanning and analysis
37
- - Batch processing
38
- - Configuration management
39
- """
40
-
41
- def __init__(self):
42
- """Initialize CLI interface."""
43
- self.console = Console()
44
- self.logger = get_logger("cli")
45
- self.config = None
46
- self.progress_tracker = RichProgressTracker(self.console)
47
- self.question_interface = RichQuestionInterface(self.console)
48
- self.error_display = RichErrorDisplay(self.console)
49
-
50
- def _load_config(self) -> AgentConfig:
51
- """Load agent configuration."""
52
- if self.config is None:
53
- try:
54
- # In real implementation, this would load from django-cfg
55
- self.config = AgentConfig()
56
- except Exception as e:
57
- self.error_display.show_error(
58
- "Configuration Error",
59
- f"Failed to load configuration: {e}",
60
- suggestions=["Check django-cfg setup", "Verify API keys"]
61
- )
62
- sys.exit(1)
63
- return self.config
64
-
65
- def _show_welcome(self):
66
- """Show welcome message."""
67
- welcome_text = Text()
68
- welcome_text.append("🚀 Django App Agent", style="bold blue")
69
- welcome_text.append("\nAI-Powered Django Application Generator", style="italic")
70
-
71
- panel = Panel(
72
- welcome_text,
73
- title="Welcome",
74
- border_style="blue",
75
- padding=(1, 2)
76
- )
77
- self.console.print(panel)
78
- self.console.print()
79
-
80
- def _show_app_types(self) -> AppType:
81
- """Show application type selection."""
82
- self.console.print("[bold]Select Application Type:[/bold]")
83
-
84
- table = Table(show_header=True, header_style="bold magenta")
85
- table.add_column("Option", style="cyan", width=10)
86
- table.add_column("Type", style="green")
87
- table.add_column("Description")
88
-
89
- table.add_row("1", "Django", "Standard Django application")
90
- table.add_row("2", "Django-CFG", "Django-CFG enhanced application with configuration management")
91
-
92
- self.console.print(table)
93
- self.console.print()
94
-
95
- while True:
96
- choice = Prompt.ask("Choose application type", choices=["1", "2"], default="2")
97
- if choice == "1":
98
- return AppType.DJANGO
99
- elif choice == "2":
100
- return AppType.DJANGO_CFG
101
-
102
- def _show_complexity_levels(self) -> AppComplexity:
103
- """Show complexity level selection."""
104
- self.console.print("[bold]Select Complexity Level:[/bold]")
105
-
106
- table = Table(show_header=True, header_style="bold magenta")
107
- table.add_column("Option", style="cyan", width=10)
108
- table.add_column("Level", style="green")
109
- table.add_column("Description")
110
- table.add_column("Est. Time", style="yellow")
111
-
112
- table.add_row("1", "Basic", "Simple app with core features", "~5 min")
113
- table.add_row("2", "Moderate", "Standard app with common features", "~15 min")
114
- table.add_row("3", "Advanced", "Complex app with advanced features", "~30 min")
115
- table.add_row("4", "Enterprise", "Full-featured enterprise application", "~60 min")
116
-
117
- self.console.print(table)
118
- self.console.print()
119
-
120
- choice = Prompt.ask("Choose complexity level", choices=["1", "2", "3", "4"], default="2")
121
-
122
- complexity_map = {
123
- "1": AppComplexity.SIMPLE,
124
- "2": AppComplexity.MODERATE,
125
- "3": AppComplexity.ADVANCED,
126
- "4": AppComplexity.ENTERPRISE
127
- }
128
-
129
- return complexity_map[choice]
130
-
131
- def _select_features(self, complexity: AppComplexity) -> List[AppFeature]:
132
- """Interactive feature selection."""
133
- recommended = complexity.get_recommended_features()
134
-
135
- self.console.print(f"[bold]Select Features for {complexity.value.title()} Application:[/bold]")
136
- self.console.print(f"[dim]Recommended features are pre-selected[/dim]")
137
- self.console.print()
138
-
139
- # Show available features
140
- all_features = list(AppFeature)
141
- selected_features = set(recommended)
142
-
143
- table = Table(show_header=True, header_style="bold magenta")
144
- table.add_column("Feature", style="green")
145
- table.add_column("Selected", style="cyan", width=10)
146
- table.add_column("Description")
147
-
148
- for feature in all_features:
149
- selected = "✓" if feature in selected_features else " "
150
- description = self._get_feature_description(feature)
151
- style = "green" if feature in selected_features else "dim"
152
- table.add_row(feature.value, selected, description, style=style)
153
-
154
- self.console.print(table)
155
- self.console.print()
156
-
157
- # Allow customization
158
- if Confirm.ask("Customize feature selection?", default=False):
159
- selected_features = self._customize_features(all_features, selected_features)
160
-
161
- return list(selected_features)
162
-
163
- def _customize_features(self, all_features: List[AppFeature], current: set) -> set:
164
- """Allow user to customize feature selection."""
165
- selected = current.copy()
166
-
167
- self.console.print("[bold]Feature Customization:[/bold]")
168
- self.console.print("[dim]Type feature name to toggle, 'done' to finish[/dim]")
169
- self.console.print()
170
-
171
- while True:
172
- # Show current selection
173
- self.console.print("[bold]Current selection:[/bold]")
174
- for feature in all_features:
175
- status = "✓" if feature in selected else " "
176
- style = "green" if feature in selected else "dim"
177
- self.console.print(f" [{status}] {feature.value}", style=style)
178
-
179
- self.console.print()
180
-
181
- choice = Prompt.ask(
182
- "Feature to toggle (or 'done')",
183
- default="done"
184
- ).lower()
185
-
186
- if choice == "done":
187
- break
188
-
189
- # Find matching feature
190
- matching_feature = None
191
- for feature in all_features:
192
- if feature.value.lower() == choice or feature.value.lower().startswith(choice):
193
- matching_feature = feature
194
- break
195
-
196
- if matching_feature:
197
- if matching_feature in selected:
198
- selected.remove(matching_feature)
199
- self.console.print(f"[red]Removed {matching_feature.value}[/red]")
200
- else:
201
- selected.add(matching_feature)
202
- self.console.print(f"[green]Added {matching_feature.value}[/green]")
203
- else:
204
- self.console.print(f"[red]Feature '{choice}' not found[/red]")
205
-
206
- self.console.print()
207
-
208
- return selected
209
-
210
- def _get_feature_description(self, feature: AppFeature) -> str:
211
- """Get description for a feature."""
212
- descriptions = {
213
- AppFeature.MODELS: "Database models and ORM",
214
- AppFeature.VIEWS: "View functions and classes",
215
- AppFeature.URLS: "URL routing configuration",
216
- AppFeature.ADMIN: "Django admin interface",
217
- AppFeature.FORMS: "Form classes and validation",
218
- AppFeature.TEMPLATES: "HTML templates",
219
- AppFeature.API: "REST API with DRF",
220
- AppFeature.TESTS: "Unit and integration tests",
221
- AppFeature.TASKS: "Background tasks (Celery/Dramatiq)",
222
- AppFeature.DOCS: "Auto-generated documentation",
223
- AppFeature.CONFIG: "Configuration management",
224
- AppFeature.SECURITY: "Security and permissions",
225
- AppFeature.SIGNALS: "Django signals",
226
- AppFeature.MANAGEMENT_COMMANDS: "Custom management commands",
227
- AppFeature.MIDDLEWARE: "Custom middleware",
228
- AppFeature.CONTEXT_PROCESSORS: "Template context processors",
229
- }
230
- return descriptions.get(feature, "Additional feature")
231
-
232
- async def _run_generation(self, request: AppGenerationRequest) -> None:
233
- """Run application generation process."""
234
- config = self._load_config()
235
-
236
- # Initialize services
237
- generator_service = AppGeneratorService(config)
238
-
239
- # Create dependencies
240
- deps = create_service_dependencies(
241
- config=config,
242
- service_name="cli_generation",
243
- project_root=Path.cwd()
244
- )
245
-
246
- # Start progress tracking
247
- with self.progress_tracker.track_generation(request.app_name) as progress:
248
- try:
249
- # Run generation
250
- result = await generator_service.process(request, deps)
251
-
252
- # Show results
253
- if result.status == "success":
254
- self._show_success_result(result)
255
- else:
256
- self._show_error_result(result)
257
-
258
- except Exception as e:
259
- self.error_display.show_error(
260
- "Generation Failed",
261
- str(e),
262
- suggestions=["Check configuration", "Verify permissions", "Try again"]
263
- )
264
-
265
- def _show_success_result(self, result) -> None:
266
- """Show successful generation result."""
267
- self.console.print()
268
-
269
- success_panel = Panel(
270
- f"✅ Successfully generated application '[bold green]{result.app_name}[/bold green]'\n"
271
- f"📁 Files created: {len(result.generated_files)}\n"
272
- f"⏱️ Duration: {result.duration_seconds:.1f} seconds",
273
- title="Generation Complete",
274
- border_style="green",
275
- padding=(1, 2)
276
- )
277
- self.console.print(success_panel)
278
-
279
- # Show quality metrics if available
280
- if result.quality_metrics:
281
- metrics = result.quality_metrics
282
-
283
- metrics_table = Table(title="Quality Metrics", show_header=True)
284
- metrics_table.add_column("Metric", style="cyan")
285
- metrics_table.add_column("Score", style="green")
286
-
287
- metrics_table.add_row("Code Readability", f"{metrics.code_readability_score:.2f}/1.0")
288
- metrics_table.add_row("Maintainability", f"{metrics.maintainability_score:.2f}/1.0")
289
- metrics_table.add_row("Type Hints", f"{metrics.type_hint_completeness:.2f}/1.0")
290
- metrics_table.add_row("Pydantic Compliance", f"{metrics.pydantic_compliance_score:.2f}/1.0")
291
- metrics_table.add_row("Test Coverage", f"{metrics.test_coverage_percentage:.1f}%")
292
-
293
- self.console.print(metrics_table)
294
-
295
- # Show next steps
296
- self.console.print()
297
- self.console.print("[bold]Next Steps:[/bold]")
298
- self.console.print("1. Add the app to your INSTALLED_APPS")
299
- self.console.print("2. Run migrations: [cyan]python manage.py makemigrations && python manage.py migrate[/cyan]")
300
- self.console.print("3. Include URLs in your main urls.py")
301
- self.console.print("4. Start development!")
302
-
303
- def _show_error_result(self, result) -> None:
304
- """Show error generation result."""
305
- self.error_display.show_error(
306
- "Generation Failed",
307
- result.message,
308
- errors=result.errors,
309
- warnings=result.warnings
310
- )
311
-
312
-
313
- # Click CLI commands
314
- @click.group()
315
- @click.version_option(version="0.1.0", prog_name="Django App Agent")
316
- def cli():
317
- """🚀 Django App Agent - AI-Powered Django Application Generator"""
318
- pass
319
-
320
-
321
- @cli.command()
322
- @click.option('--app-name', prompt='Application name', help='Name of the Django application')
323
- @click.option('--description', prompt='Description', help='Brief description of the application')
324
- @click.option('--app-type', type=click.Choice(['django', 'django_cfg']), default='django_cfg', help='Application type')
325
- @click.option('--complexity', type=click.Choice(['basic', 'moderate', 'advanced', 'enterprise']), default='moderate', help='Complexity level')
326
- @click.option('--output-dir', type=click.Path(), help='Output directory')
327
- @click.option('--interactive/--no-interactive', default=True, help='Interactive mode')
328
- def generate(app_name: str, description: str, app_type: str, complexity: str, output_dir: Optional[str], interactive: bool):
329
- """Generate a new Django application with AI assistance."""
330
-
331
- cli_interface = DjangoAppAgentCLI()
332
-
333
- if interactive:
334
- cli_interface._show_welcome()
335
-
336
- # Interactive mode
337
- app_type_enum = cli_interface._show_app_types()
338
- complexity_enum = cli_interface._show_complexity_levels()
339
- features = cli_interface._select_features(complexity_enum)
340
-
341
- else:
342
- # Non-interactive mode
343
- app_type_enum = AppType.DJANGO_CFG if app_type == 'django_cfg' else AppType.DJANGO
344
- complexity_enum = AppComplexity(complexity)
345
- features = list(complexity_enum.get_recommended_features())
346
-
347
- # Create generation request
348
- request = AppGenerationRequest(
349
- app_name=app_name,
350
- description=description,
351
- app_type=app_type_enum,
352
- complexity=complexity_enum,
353
- features=features,
354
- output_directory=output_dir
355
- )
356
-
357
- # Run generation
358
- asyncio.run(cli_interface._run_generation(request))
359
-
360
-
361
- @cli.command()
362
- @click.option('--project-root', type=click.Path(exists=True), default='.', help='Project root directory')
363
- @click.option('--output-format', type=click.Choice(['table', 'json']), default='table', help='Output format')
364
- def scan(project_root: str, output_format: str):
365
- """Scan and analyze Django project structure."""
366
-
367
- cli_interface = DjangoAppAgentCLI()
368
- config = cli_interface._load_config()
369
-
370
- async def run_scan():
371
- scanner_service = ProjectScannerService(config)
372
-
373
- request = ProjectScanRequest(
374
- project_root=Path(project_root),
375
- scan_depth=3,
376
- analyze_dependencies=True,
377
- detect_patterns=True
378
- )
379
-
380
- deps = create_service_dependencies(
381
- config=config,
382
- service_name="cli_scan",
383
- project_root=Path(project_root)
384
- )
385
-
386
- with cli_interface.progress_tracker.track_scanning() as progress:
387
- result = await scanner_service.process(request, deps)
388
-
389
- # Display results
390
- if output_format == 'table':
391
- cli_interface._show_scan_table(result)
392
- else:
393
- cli_interface._show_scan_json(result)
394
-
395
- asyncio.run(run_scan())
396
-
397
-
398
- @cli.command()
399
- def config():
400
- """Show current configuration."""
401
-
402
- cli_interface = DjangoAppAgentCLI()
403
- config = cli_interface._load_config()
404
-
405
- # Show configuration in a nice table
406
- config_table = Table(title="Django App Agent Configuration", show_header=True)
407
- config_table.add_column("Setting", style="cyan")
408
- config_table.add_column("Value", style="green")
409
-
410
- # Add configuration rows (this would be populated from actual config)
411
- config_table.add_row("Version", "0.1.0")
412
- config_table.add_row("Default App Type", "django_cfg")
413
- config_table.add_row("AI Provider", "OpenRouter")
414
-
415
- cli_interface.console.print(config_table)
416
-
417
-
418
- if __name__ == '__main__':
419
- cli()