django-cfg 1.3.5__py3-none-any.whl → 1.3.9__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 (252) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/apps/accounts/admin/__init__.py +24 -8
  3. django_cfg/apps/accounts/admin/activity_admin.py +146 -0
  4. django_cfg/apps/accounts/admin/filters.py +98 -22
  5. django_cfg/apps/accounts/admin/group_admin.py +86 -0
  6. django_cfg/apps/accounts/admin/inlines.py +42 -13
  7. django_cfg/apps/accounts/admin/otp_admin.py +115 -0
  8. django_cfg/apps/accounts/admin/registration_admin.py +173 -0
  9. django_cfg/apps/accounts/admin/resources.py +123 -19
  10. django_cfg/apps/accounts/admin/twilio_admin.py +327 -0
  11. django_cfg/apps/accounts/admin/user_admin.py +362 -0
  12. django_cfg/apps/agents/admin/__init__.py +17 -4
  13. django_cfg/apps/agents/admin/execution_admin.py +204 -183
  14. django_cfg/apps/agents/admin/registry_admin.py +230 -255
  15. django_cfg/apps/agents/admin/toolsets_admin.py +274 -321
  16. django_cfg/apps/agents/core/__init__.py +1 -1
  17. django_cfg/apps/agents/core/django_agent.py +221 -0
  18. django_cfg/apps/agents/core/exceptions.py +14 -0
  19. django_cfg/apps/agents/core/orchestrator.py +18 -3
  20. django_cfg/apps/knowbase/admin/__init__.py +1 -1
  21. django_cfg/apps/knowbase/admin/archive_admin.py +352 -640
  22. django_cfg/apps/knowbase/admin/chat_admin.py +258 -192
  23. django_cfg/apps/knowbase/admin/document_admin.py +269 -262
  24. django_cfg/apps/knowbase/admin/external_data_admin.py +271 -489
  25. django_cfg/apps/knowbase/config/settings.py +21 -4
  26. django_cfg/apps/knowbase/views/chat_views.py +3 -0
  27. django_cfg/apps/leads/admin/__init__.py +3 -1
  28. django_cfg/apps/leads/admin/leads_admin.py +235 -35
  29. django_cfg/apps/maintenance/admin/__init__.py +2 -2
  30. django_cfg/apps/maintenance/admin/api_key_admin.py +125 -63
  31. django_cfg/apps/maintenance/admin/log_admin.py +143 -61
  32. django_cfg/apps/maintenance/admin/scheduled_admin.py +212 -301
  33. django_cfg/apps/maintenance/admin/site_admin.py +213 -352
  34. django_cfg/apps/newsletter/admin/__init__.py +29 -2
  35. django_cfg/apps/newsletter/admin/newsletter_admin.py +531 -193
  36. django_cfg/apps/payments/admin/__init__.py +18 -27
  37. django_cfg/apps/payments/admin/api_keys_admin.py +179 -546
  38. django_cfg/apps/payments/admin/balance_admin.py +166 -632
  39. django_cfg/apps/payments/admin/currencies_admin.py +235 -607
  40. django_cfg/apps/payments/admin/endpoint_groups_admin.py +127 -0
  41. django_cfg/apps/payments/admin/filters.py +83 -3
  42. django_cfg/apps/payments/admin/networks_admin.py +258 -0
  43. django_cfg/apps/payments/admin/payments_admin.py +171 -461
  44. django_cfg/apps/payments/admin/subscriptions_admin.py +119 -636
  45. django_cfg/apps/payments/admin/tariffs_admin.py +248 -0
  46. django_cfg/apps/payments/admin_interface/serializers/payment_serializers.py +105 -34
  47. django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +12 -16
  48. django_cfg/apps/payments/admin_interface/views/__init__.py +2 -0
  49. django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +13 -18
  50. django_cfg/apps/payments/management/commands/manage_currencies.py +236 -274
  51. django_cfg/apps/payments/management/commands/manage_providers.py +4 -1
  52. django_cfg/apps/payments/middleware/api_access.py +32 -6
  53. django_cfg/apps/payments/migrations/0002_currency_usd_rate_currency_usd_rate_updated_at.py +26 -0
  54. django_cfg/apps/payments/migrations/0003_remove_provider_currency_fields.py +28 -0
  55. django_cfg/apps/payments/migrations/0004_add_reserved_usd_field.py +30 -0
  56. django_cfg/apps/payments/models/balance.py +12 -0
  57. django_cfg/apps/payments/models/currencies.py +106 -32
  58. django_cfg/apps/payments/models/managers/currency_managers.py +65 -0
  59. django_cfg/apps/payments/services/core/currency_service.py +35 -28
  60. django_cfg/apps/payments/services/core/payment_service.py +1 -1
  61. django_cfg/apps/payments/services/providers/__init__.py +3 -0
  62. django_cfg/apps/payments/services/providers/base.py +95 -39
  63. django_cfg/apps/payments/services/providers/models/__init__.py +40 -0
  64. django_cfg/apps/payments/services/providers/models/base.py +122 -0
  65. django_cfg/apps/payments/services/providers/models/providers.py +87 -0
  66. django_cfg/apps/payments/services/providers/models/universal.py +48 -0
  67. django_cfg/apps/payments/services/providers/nowpayments/__init__.py +31 -0
  68. django_cfg/apps/payments/services/providers/nowpayments/config.py +70 -0
  69. django_cfg/apps/payments/services/providers/nowpayments/models.py +150 -0
  70. django_cfg/apps/payments/services/providers/nowpayments/parsers.py +879 -0
  71. django_cfg/apps/payments/services/providers/{nowpayments.py → nowpayments/provider.py} +240 -209
  72. django_cfg/apps/payments/services/providers/nowpayments/sync.py +196 -0
  73. django_cfg/apps/payments/services/providers/registry.py +4 -32
  74. django_cfg/apps/payments/services/providers/sync_service.py +277 -0
  75. django_cfg/apps/payments/static/payments/js/api-client.js +23 -5
  76. django_cfg/apps/payments/static/payments/js/payment-form.js +65 -8
  77. django_cfg/apps/payments/tasks/__init__.py +39 -0
  78. django_cfg/apps/payments/tasks/types.py +73 -0
  79. django_cfg/apps/payments/tasks/usage_tracking.py +308 -0
  80. django_cfg/apps/payments/templates/admin/payments/_components/dashboard_header.html +23 -0
  81. django_cfg/apps/payments/templates/admin/payments/_components/stats_card.html +25 -0
  82. django_cfg/apps/payments/templates/admin/payments/_components/stats_grid.html +16 -0
  83. django_cfg/apps/payments/templates/admin/payments/apikey/change_list.html +39 -0
  84. django_cfg/apps/payments/templates/admin/payments/balance/change_list.html +50 -0
  85. django_cfg/apps/payments/templates/admin/payments/currency/change_list.html +40 -0
  86. django_cfg/apps/payments/templates/admin/payments/payment/change_list.html +48 -0
  87. django_cfg/apps/payments/templates/admin/payments/subscription/change_list.html +48 -0
  88. django_cfg/apps/payments/urls_admin.py +1 -1
  89. django_cfg/apps/payments/views/api/currencies.py +5 -5
  90. django_cfg/apps/payments/views/overview/services.py +2 -2
  91. django_cfg/apps/payments/views/serializers/currencies.py +4 -3
  92. django_cfg/apps/support/admin/__init__.py +10 -1
  93. django_cfg/apps/support/admin/support_admin.py +338 -141
  94. django_cfg/apps/tasks/admin/__init__.py +11 -0
  95. django_cfg/apps/tasks/admin/tasks_admin.py +430 -0
  96. django_cfg/apps/urls.py +1 -2
  97. django_cfg/config.py +1 -1
  98. django_cfg/core/config.py +10 -5
  99. django_cfg/core/generation.py +1 -1
  100. django_cfg/management/commands/__init__.py +13 -1
  101. django_cfg/management/commands/app_agent_diagnose.py +470 -0
  102. django_cfg/management/commands/app_agent_generate.py +342 -0
  103. django_cfg/management/commands/app_agent_info.py +308 -0
  104. django_cfg/management/commands/migrate_all.py +9 -3
  105. django_cfg/management/commands/migrator.py +11 -6
  106. django_cfg/management/commands/rundramatiq.py +3 -2
  107. django_cfg/middleware/__init__.py +0 -2
  108. django_cfg/models/api_keys.py +115 -0
  109. django_cfg/modules/django_admin/__init__.py +64 -0
  110. django_cfg/modules/django_admin/decorators/__init__.py +13 -0
  111. django_cfg/modules/django_admin/decorators/actions.py +106 -0
  112. django_cfg/modules/django_admin/decorators/display.py +106 -0
  113. django_cfg/modules/django_admin/mixins/__init__.py +14 -0
  114. django_cfg/modules/django_admin/mixins/display_mixin.py +81 -0
  115. django_cfg/modules/django_admin/mixins/optimization_mixin.py +41 -0
  116. django_cfg/modules/django_admin/mixins/standalone_actions_mixin.py +202 -0
  117. django_cfg/modules/django_admin/models/__init__.py +20 -0
  118. django_cfg/modules/django_admin/models/action_models.py +33 -0
  119. django_cfg/modules/django_admin/models/badge_models.py +20 -0
  120. django_cfg/modules/django_admin/models/base.py +26 -0
  121. django_cfg/modules/django_admin/models/display_models.py +31 -0
  122. django_cfg/modules/django_admin/utils/badges.py +159 -0
  123. django_cfg/modules/django_admin/utils/displays.py +247 -0
  124. django_cfg/modules/django_app_agent/__init__.py +87 -0
  125. django_cfg/modules/django_app_agent/agents/__init__.py +40 -0
  126. django_cfg/modules/django_app_agent/agents/base/__init__.py +24 -0
  127. django_cfg/modules/django_app_agent/agents/base/agent.py +354 -0
  128. django_cfg/modules/django_app_agent/agents/base/context.py +236 -0
  129. django_cfg/modules/django_app_agent/agents/base/executor.py +430 -0
  130. django_cfg/modules/django_app_agent/agents/generation/__init__.py +12 -0
  131. django_cfg/modules/django_app_agent/agents/generation/app_generator/__init__.py +15 -0
  132. django_cfg/modules/django_app_agent/agents/generation/app_generator/config_validator.py +147 -0
  133. django_cfg/modules/django_app_agent/agents/generation/app_generator/main.py +99 -0
  134. django_cfg/modules/django_app_agent/agents/generation/app_generator/models.py +32 -0
  135. django_cfg/modules/django_app_agent/agents/generation/app_generator/prompt_manager.py +290 -0
  136. django_cfg/modules/django_app_agent/agents/interfaces.py +376 -0
  137. django_cfg/modules/django_app_agent/core/__init__.py +33 -0
  138. django_cfg/modules/django_app_agent/core/config.py +300 -0
  139. django_cfg/modules/django_app_agent/core/exceptions.py +359 -0
  140. django_cfg/modules/django_app_agent/models/__init__.py +71 -0
  141. django_cfg/modules/django_app_agent/models/base.py +283 -0
  142. django_cfg/modules/django_app_agent/models/context.py +496 -0
  143. django_cfg/modules/django_app_agent/models/enums.py +481 -0
  144. django_cfg/modules/django_app_agent/models/requests.py +500 -0
  145. django_cfg/modules/django_app_agent/models/responses.py +585 -0
  146. django_cfg/modules/django_app_agent/pytest.ini +6 -0
  147. django_cfg/modules/django_app_agent/services/__init__.py +42 -0
  148. django_cfg/modules/django_app_agent/services/app_generator/__init__.py +30 -0
  149. django_cfg/modules/django_app_agent/services/app_generator/ai_integration.py +133 -0
  150. django_cfg/modules/django_app_agent/services/app_generator/context.py +40 -0
  151. django_cfg/modules/django_app_agent/services/app_generator/main.py +202 -0
  152. django_cfg/modules/django_app_agent/services/app_generator/structure.py +316 -0
  153. django_cfg/modules/django_app_agent/services/app_generator/validation.py +125 -0
  154. django_cfg/modules/django_app_agent/services/base.py +437 -0
  155. django_cfg/modules/django_app_agent/services/context_builder/__init__.py +34 -0
  156. django_cfg/modules/django_app_agent/services/context_builder/code_extractor.py +141 -0
  157. django_cfg/modules/django_app_agent/services/context_builder/context_generator.py +276 -0
  158. django_cfg/modules/django_app_agent/services/context_builder/main.py +272 -0
  159. django_cfg/modules/django_app_agent/services/context_builder/models.py +40 -0
  160. django_cfg/modules/django_app_agent/services/context_builder/pattern_analyzer.py +85 -0
  161. django_cfg/modules/django_app_agent/services/project_scanner/__init__.py +31 -0
  162. django_cfg/modules/django_app_agent/services/project_scanner/app_discovery.py +311 -0
  163. django_cfg/modules/django_app_agent/services/project_scanner/main.py +221 -0
  164. django_cfg/modules/django_app_agent/services/project_scanner/models.py +59 -0
  165. django_cfg/modules/django_app_agent/services/project_scanner/pattern_detection.py +94 -0
  166. django_cfg/modules/django_app_agent/services/questioning_service/__init__.py +28 -0
  167. django_cfg/modules/django_app_agent/services/questioning_service/main.py +273 -0
  168. django_cfg/modules/django_app_agent/services/questioning_service/models.py +111 -0
  169. django_cfg/modules/django_app_agent/services/questioning_service/question_generator.py +251 -0
  170. django_cfg/modules/django_app_agent/services/questioning_service/response_processor.py +347 -0
  171. django_cfg/modules/django_app_agent/services/questioning_service/session_manager.py +356 -0
  172. django_cfg/modules/django_app_agent/services/report_service.py +332 -0
  173. django_cfg/modules/django_app_agent/services/template_manager/__init__.py +18 -0
  174. django_cfg/modules/django_app_agent/services/template_manager/jinja_engine.py +236 -0
  175. django_cfg/modules/django_app_agent/services/template_manager/main.py +159 -0
  176. django_cfg/modules/django_app_agent/services/template_manager/models.py +36 -0
  177. django_cfg/modules/django_app_agent/services/template_manager/template_loader.py +100 -0
  178. django_cfg/modules/django_app_agent/services/template_manager/templates/admin.py.j2 +105 -0
  179. django_cfg/modules/django_app_agent/services/template_manager/templates/apps.py.j2 +31 -0
  180. django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_config.py.j2 +44 -0
  181. django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_module.py.j2 +81 -0
  182. django_cfg/modules/django_app_agent/services/template_manager/templates/forms.py.j2 +107 -0
  183. django_cfg/modules/django_app_agent/services/template_manager/templates/models.py.j2 +139 -0
  184. django_cfg/modules/django_app_agent/services/template_manager/templates/serializers.py.j2 +91 -0
  185. django_cfg/modules/django_app_agent/services/template_manager/templates/tests.py.j2 +195 -0
  186. django_cfg/modules/django_app_agent/services/template_manager/templates/urls.py.j2 +35 -0
  187. django_cfg/modules/django_app_agent/services/template_manager/templates/views.py.j2 +211 -0
  188. django_cfg/modules/django_app_agent/services/template_manager/variable_processor.py +200 -0
  189. django_cfg/modules/django_app_agent/services/validation_service/__init__.py +25 -0
  190. django_cfg/modules/django_app_agent/services/validation_service/django_validator.py +333 -0
  191. django_cfg/modules/django_app_agent/services/validation_service/main.py +242 -0
  192. django_cfg/modules/django_app_agent/services/validation_service/models.py +66 -0
  193. django_cfg/modules/django_app_agent/services/validation_service/quality_validator.py +352 -0
  194. django_cfg/modules/django_app_agent/services/validation_service/security_validator.py +272 -0
  195. django_cfg/modules/django_app_agent/services/validation_service/syntax_validator.py +203 -0
  196. django_cfg/modules/django_app_agent/ui/__init__.py +25 -0
  197. django_cfg/modules/django_app_agent/ui/cli.py +419 -0
  198. django_cfg/modules/django_app_agent/ui/rich_components.py +622 -0
  199. django_cfg/modules/django_app_agent/utils/__init__.py +38 -0
  200. django_cfg/modules/django_app_agent/utils/logging.py +360 -0
  201. django_cfg/modules/django_app_agent/utils/validation.py +417 -0
  202. django_cfg/modules/django_currency/__init__.py +2 -2
  203. django_cfg/modules/django_currency/clients/__init__.py +2 -2
  204. django_cfg/modules/django_currency/clients/hybrid_client.py +587 -0
  205. django_cfg/modules/django_currency/core/converter.py +12 -12
  206. django_cfg/modules/django_currency/database/__init__.py +2 -2
  207. django_cfg/modules/django_currency/database/database_loader.py +93 -42
  208. django_cfg/modules/django_llm/llm/client.py +10 -2
  209. django_cfg/modules/django_unfold/callbacks/actions.py +1 -1
  210. django_cfg/modules/django_unfold/callbacks/statistics.py +1 -1
  211. django_cfg/modules/django_unfold/dashboard.py +14 -13
  212. django_cfg/modules/django_unfold/models/config.py +1 -1
  213. django_cfg/registry/core.py +3 -0
  214. django_cfg/registry/third_party.py +2 -2
  215. django_cfg/template_archive/django_sample.zip +0 -0
  216. {django_cfg-1.3.5.dist-info → django_cfg-1.3.9.dist-info}/METADATA +2 -1
  217. {django_cfg-1.3.5.dist-info → django_cfg-1.3.9.dist-info}/RECORD +224 -118
  218. django_cfg/apps/accounts/admin/activity.py +0 -96
  219. django_cfg/apps/accounts/admin/group.py +0 -17
  220. django_cfg/apps/accounts/admin/otp.py +0 -59
  221. django_cfg/apps/accounts/admin/registration_source.py +0 -97
  222. django_cfg/apps/accounts/admin/twilio_response.py +0 -227
  223. django_cfg/apps/accounts/admin/user.py +0 -300
  224. django_cfg/apps/agents/core/agent.py +0 -281
  225. django_cfg/apps/payments/admin_interface/old/payments/base.html +0 -175
  226. django_cfg/apps/payments/admin_interface/old/payments/components/dev_tool_card.html +0 -125
  227. django_cfg/apps/payments/admin_interface/old/payments/components/loading_spinner.html +0 -16
  228. django_cfg/apps/payments/admin_interface/old/payments/components/ngrok_status_card.html +0 -113
  229. django_cfg/apps/payments/admin_interface/old/payments/components/notification.html +0 -27
  230. django_cfg/apps/payments/admin_interface/old/payments/components/provider_card.html +0 -86
  231. django_cfg/apps/payments/admin_interface/old/payments/components/status_card.html +0 -35
  232. django_cfg/apps/payments/admin_interface/old/payments/currency_converter.html +0 -382
  233. django_cfg/apps/payments/admin_interface/old/payments/payment_dashboard.html +0 -309
  234. django_cfg/apps/payments/admin_interface/old/payments/payment_form.html +0 -303
  235. django_cfg/apps/payments/admin_interface/old/payments/payment_list.html +0 -382
  236. django_cfg/apps/payments/admin_interface/old/payments/payment_status.html +0 -500
  237. django_cfg/apps/payments/admin_interface/old/payments/webhook_dashboard.html +0 -518
  238. django_cfg/apps/payments/admin_interface/old/static/payments/css/components.css +0 -619
  239. django_cfg/apps/payments/admin_interface/old/static/payments/css/dashboard.css +0 -188
  240. django_cfg/apps/payments/admin_interface/old/static/payments/js/components.js +0 -545
  241. django_cfg/apps/payments/admin_interface/old/static/payments/js/ngrok-status.js +0 -163
  242. django_cfg/apps/payments/admin_interface/old/static/payments/js/utils.js +0 -412
  243. django_cfg/apps/tasks/admin.py +0 -320
  244. django_cfg/middleware/static_nocache.py +0 -55
  245. django_cfg/modules/django_currency/clients/yahoo_client.py +0 -157
  246. /django_cfg/modules/{django_unfold → django_admin}/icons/README.md +0 -0
  247. /django_cfg/modules/{django_unfold → django_admin}/icons/__init__.py +0 -0
  248. /django_cfg/modules/{django_unfold → django_admin}/icons/constants.py +0 -0
  249. /django_cfg/modules/{django_unfold → django_admin}/icons/generate_icons.py +0 -0
  250. {django_cfg-1.3.5.dist-info → django_cfg-1.3.9.dist-info}/WHEEL +0 -0
  251. {django_cfg-1.3.5.dist-info → django_cfg-1.3.9.dist-info}/entry_points.txt +0 -0
  252. {django_cfg-1.3.5.dist-info → django_cfg-1.3.9.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,203 @@
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
@@ -0,0 +1,25 @@
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
+ ]
@@ -0,0 +1,419 @@
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()