django-cfg 1.4.10__py3-none-any.whl → 1.4.13__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 (225) hide show
  1. django_cfg/apps/agents/management/commands/create_agent.py +1 -1
  2. django_cfg/apps/agents/management/commands/orchestrator_status.py +3 -3
  3. django_cfg/apps/newsletter/serializers.py +40 -3
  4. django_cfg/apps/newsletter/views/campaigns.py +12 -3
  5. django_cfg/apps/newsletter/views/emails.py +14 -3
  6. django_cfg/apps/newsletter/views/subscriptions.py +12 -2
  7. django_cfg/apps/payments/views/api/currencies.py +49 -6
  8. django_cfg/apps/payments/views/api/webhooks.py +72 -7
  9. django_cfg/apps/payments/views/overview/serializers.py +34 -1
  10. django_cfg/apps/payments/views/overview/views.py +2 -1
  11. django_cfg/apps/payments/views/serializers/payments.py +6 -6
  12. django_cfg/apps/urls.py +106 -45
  13. django_cfg/core/base/config_model.py +2 -2
  14. django_cfg/core/constants.py +1 -1
  15. django_cfg/core/generation/integration_generators/__init__.py +1 -1
  16. django_cfg/core/generation/integration_generators/api.py +73 -49
  17. django_cfg/core/integration/display/startup.py +30 -22
  18. django_cfg/core/integration/url_integration.py +15 -16
  19. django_cfg/management/commands/check_endpoints.py +11 -160
  20. django_cfg/management/commands/check_settings.py +13 -348
  21. django_cfg/management/commands/clear_constance.py +13 -201
  22. django_cfg/management/commands/create_token.py +13 -321
  23. django_cfg/management/commands/generate_clients.py +23 -0
  24. django_cfg/management/commands/list_urls.py +13 -306
  25. django_cfg/management/commands/migrate_all.py +13 -126
  26. django_cfg/management/commands/migrator.py +13 -396
  27. django_cfg/management/commands/rundramatiq.py +15 -247
  28. django_cfg/management/commands/rundramatiq_simulator.py +12 -429
  29. django_cfg/management/commands/runserver_ngrok.py +15 -160
  30. django_cfg/management/commands/script.py +12 -488
  31. django_cfg/management/commands/show_config.py +12 -215
  32. django_cfg/management/commands/show_urls.py +12 -342
  33. django_cfg/management/commands/superuser.py +15 -295
  34. django_cfg/management/commands/task_clear.py +14 -217
  35. django_cfg/management/commands/task_status.py +13 -248
  36. django_cfg/management/commands/test_email.py +15 -86
  37. django_cfg/management/commands/test_telegram.py +14 -61
  38. django_cfg/management/commands/test_twilio.py +15 -105
  39. django_cfg/management/commands/tree.py +13 -383
  40. django_cfg/management/commands/validate_openapi.py +10 -0
  41. django_cfg/middleware/README.md +1 -1
  42. django_cfg/middleware/user_activity.py +3 -3
  43. django_cfg/models/__init__.py +2 -2
  44. django_cfg/models/api/drf/spectacular.py +6 -6
  45. django_cfg/models/django/__init__.py +2 -2
  46. django_cfg/models/django/openapi.py +162 -0
  47. django_cfg/modules/django_admin/management/commands/check_endpoints.py +169 -0
  48. django_cfg/modules/django_admin/management/commands/check_settings.py +355 -0
  49. django_cfg/modules/django_admin/management/commands/clear_constance.py +208 -0
  50. django_cfg/modules/django_admin/management/commands/create_token.py +328 -0
  51. django_cfg/modules/django_admin/management/commands/list_urls.py +313 -0
  52. django_cfg/modules/django_admin/management/commands/migrate_all.py +133 -0
  53. django_cfg/modules/django_admin/management/commands/migrator.py +403 -0
  54. django_cfg/modules/django_admin/management/commands/script.py +496 -0
  55. django_cfg/modules/django_admin/management/commands/show_config.py +225 -0
  56. django_cfg/modules/django_admin/management/commands/show_urls.py +361 -0
  57. django_cfg/modules/django_admin/management/commands/superuser.py +302 -0
  58. django_cfg/modules/django_admin/management/commands/tree.py +390 -0
  59. django_cfg/modules/django_client/__init__.py +20 -0
  60. django_cfg/modules/django_client/apps.py +35 -0
  61. django_cfg/modules/django_client/core/__init__.py +56 -0
  62. django_cfg/modules/django_client/core/archive/__init__.py +11 -0
  63. django_cfg/modules/django_client/core/archive/manager.py +134 -0
  64. django_cfg/modules/django_client/core/cli/__init__.py +12 -0
  65. django_cfg/modules/django_client/core/cli/main.py +235 -0
  66. django_cfg/modules/django_client/core/config/__init__.py +18 -0
  67. django_cfg/modules/django_client/core/config/config.py +208 -0
  68. django_cfg/modules/django_client/core/config/group.py +101 -0
  69. django_cfg/modules/django_client/core/config/service.py +209 -0
  70. django_cfg/modules/django_client/core/generator/__init__.py +115 -0
  71. django_cfg/modules/django_client/core/generator/base.py +838 -0
  72. django_cfg/modules/django_client/core/generator/python/__init__.py +16 -0
  73. django_cfg/modules/django_client/core/generator/python/async_client_gen.py +174 -0
  74. django_cfg/modules/django_client/core/generator/python/files_generator.py +180 -0
  75. django_cfg/modules/django_client/core/generator/python/generator.py +182 -0
  76. django_cfg/modules/django_client/core/generator/python/models_generator.py +318 -0
  77. django_cfg/modules/django_client/core/generator/python/operations_generator.py +278 -0
  78. django_cfg/modules/django_client/core/generator/python/sync_client_gen.py +102 -0
  79. django_cfg/modules/django_client/core/generator/python/templates/__init__.py.jinja +9 -0
  80. django_cfg/modules/django_client/core/generator/python/templates/api_wrapper.py.jinja +153 -0
  81. django_cfg/modules/django_client/core/generator/python/templates/app_init.py.jinja +6 -0
  82. django_cfg/modules/django_client/core/generator/python/templates/client/app_client.py.jinja +18 -0
  83. django_cfg/modules/django_client/core/generator/python/templates/client/flat_client.py.jinja +38 -0
  84. django_cfg/modules/django_client/core/generator/python/templates/client/main_client.py.jinja +68 -0
  85. django_cfg/modules/django_client/core/generator/python/templates/client/main_client_file.py.jinja +14 -0
  86. django_cfg/modules/django_client/core/generator/python/templates/client/operation_method.py.jinja +9 -0
  87. django_cfg/modules/django_client/core/generator/python/templates/client/sub_client.py.jinja +18 -0
  88. django_cfg/modules/django_client/core/generator/python/templates/client/sync_main_client.py.jinja +50 -0
  89. django_cfg/modules/django_client/core/generator/python/templates/client/sync_operation_method.py.jinja +9 -0
  90. django_cfg/modules/django_client/core/generator/python/templates/client/sync_sub_client.py.jinja +18 -0
  91. django_cfg/modules/django_client/core/generator/python/templates/client_file.py.jinja +13 -0
  92. django_cfg/modules/django_client/core/generator/python/templates/main_init.py.jinja +52 -0
  93. django_cfg/modules/django_client/core/generator/python/templates/models/app_models.py.jinja +17 -0
  94. django_cfg/modules/django_client/core/generator/python/templates/models/enum_class.py.jinja +17 -0
  95. django_cfg/modules/django_client/core/generator/python/templates/models/enums.py.jinja +8 -0
  96. django_cfg/modules/django_client/core/generator/python/templates/models/models.py.jinja +17 -0
  97. django_cfg/modules/django_client/core/generator/python/templates/models/schema_class.py.jinja +21 -0
  98. django_cfg/modules/django_client/core/generator/python/templates/pyproject.toml.jinja +55 -0
  99. django_cfg/modules/django_client/core/generator/python/templates/utils/logger.py.jinja +255 -0
  100. django_cfg/modules/django_client/core/generator/python/templates/utils/retry.py.jinja +271 -0
  101. django_cfg/modules/django_client/core/generator/python/templates/utils/schema.py.jinja +12 -0
  102. django_cfg/modules/django_client/core/generator/typescript/__init__.py +14 -0
  103. django_cfg/modules/django_client/core/generator/typescript/client_generator.py +165 -0
  104. django_cfg/modules/django_client/core/generator/typescript/fetchers_generator.py +428 -0
  105. django_cfg/modules/django_client/core/generator/typescript/files_generator.py +207 -0
  106. django_cfg/modules/django_client/core/generator/typescript/generator.py +432 -0
  107. django_cfg/modules/django_client/core/generator/typescript/hooks_generator.py +536 -0
  108. django_cfg/modules/django_client/core/generator/typescript/models_generator.py +245 -0
  109. django_cfg/modules/django_client/core/generator/typescript/operations_generator.py +298 -0
  110. django_cfg/modules/django_client/core/generator/typescript/schemas_generator.py +329 -0
  111. django_cfg/modules/django_client/core/generator/typescript/templates/api_instance.ts.jinja +131 -0
  112. django_cfg/modules/django_client/core/generator/typescript/templates/app_index.ts.jinja +2 -0
  113. django_cfg/modules/django_client/core/generator/typescript/templates/client/app_client.ts.jinja +18 -0
  114. django_cfg/modules/django_client/core/generator/typescript/templates/client/client.ts.jinja +403 -0
  115. django_cfg/modules/django_client/core/generator/typescript/templates/client/flat_client.ts.jinja +109 -0
  116. django_cfg/modules/django_client/core/generator/typescript/templates/client/main_client_file.ts.jinja +10 -0
  117. django_cfg/modules/django_client/core/generator/typescript/templates/client/operation.ts.jinja +61 -0
  118. django_cfg/modules/django_client/core/generator/typescript/templates/client/sub_client.ts.jinja +15 -0
  119. django_cfg/modules/django_client/core/generator/typescript/templates/client_file.ts.jinja +9 -0
  120. django_cfg/modules/django_client/core/generator/typescript/templates/fetchers/fetchers.ts.jinja +45 -0
  121. django_cfg/modules/django_client/core/generator/typescript/templates/fetchers/index.ts.jinja +30 -0
  122. django_cfg/modules/django_client/core/generator/typescript/templates/index.ts.jinja +5 -0
  123. django_cfg/modules/django_client/core/generator/typescript/templates/main_index.ts.jinja +268 -0
  124. django_cfg/modules/django_client/core/generator/typescript/templates/models/app_models.ts.jinja +8 -0
  125. django_cfg/modules/django_client/core/generator/typescript/templates/models/enums.ts.jinja +4 -0
  126. django_cfg/modules/django_client/core/generator/typescript/templates/models/models.ts.jinja +8 -0
  127. django_cfg/modules/django_client/core/generator/typescript/templates/package.json.jinja +52 -0
  128. django_cfg/modules/django_client/core/generator/typescript/templates/schemas/index.ts.jinja +21 -0
  129. django_cfg/modules/django_client/core/generator/typescript/templates/schemas/schema.ts.jinja +24 -0
  130. django_cfg/modules/django_client/core/generator/typescript/templates/tsconfig.json.jinja +20 -0
  131. django_cfg/modules/django_client/core/generator/typescript/templates/utils/errors.ts.jinja +116 -0
  132. django_cfg/modules/django_client/core/generator/typescript/templates/utils/http.ts.jinja +98 -0
  133. django_cfg/modules/django_client/core/generator/typescript/templates/utils/logger.ts.jinja +259 -0
  134. django_cfg/modules/django_client/core/generator/typescript/templates/utils/retry.ts.jinja +175 -0
  135. django_cfg/modules/django_client/core/generator/typescript/templates/utils/schema.ts.jinja +7 -0
  136. django_cfg/modules/django_client/core/generator/typescript/templates/utils/storage.ts.jinja +158 -0
  137. django_cfg/modules/django_client/core/groups/__init__.py +13 -0
  138. django_cfg/modules/django_client/core/groups/detector.py +178 -0
  139. django_cfg/modules/django_client/core/groups/manager.py +314 -0
  140. django_cfg/modules/django_client/core/ir/__init__.py +57 -0
  141. django_cfg/modules/django_client/core/ir/context.py +387 -0
  142. django_cfg/modules/django_client/core/ir/operation.py +518 -0
  143. django_cfg/modules/django_client/core/ir/schema.py +353 -0
  144. django_cfg/modules/django_client/core/parser/__init__.py +74 -0
  145. django_cfg/modules/django_client/core/parser/base.py +648 -0
  146. django_cfg/modules/django_client/core/parser/models/__init__.py +74 -0
  147. django_cfg/modules/django_client/core/parser/models/base.py +212 -0
  148. django_cfg/modules/django_client/core/parser/models/components.py +160 -0
  149. django_cfg/modules/django_client/core/parser/models/openapi.py +203 -0
  150. django_cfg/modules/django_client/core/parser/models/operation.py +207 -0
  151. django_cfg/modules/django_client/core/parser/models/schema.py +266 -0
  152. django_cfg/modules/django_client/core/parser/openapi30.py +56 -0
  153. django_cfg/modules/django_client/core/parser/openapi31.py +64 -0
  154. django_cfg/modules/django_client/core/validation/__init__.py +22 -0
  155. django_cfg/modules/django_client/core/validation/checker.py +134 -0
  156. django_cfg/modules/django_client/core/validation/fixer.py +216 -0
  157. django_cfg/modules/django_client/core/validation/reporter.py +480 -0
  158. django_cfg/modules/django_client/core/validation/rules/__init__.py +11 -0
  159. django_cfg/modules/django_client/core/validation/rules/base.py +96 -0
  160. django_cfg/modules/django_client/core/validation/rules/type_hints.py +288 -0
  161. django_cfg/modules/django_client/core/validation/safety.py +266 -0
  162. django_cfg/modules/django_client/management/__init__.py +3 -0
  163. django_cfg/modules/django_client/management/commands/__init__.py +3 -0
  164. django_cfg/modules/django_client/management/commands/generate_client.py +427 -0
  165. django_cfg/modules/django_client/management/commands/validate_openapi.py +343 -0
  166. django_cfg/modules/django_client/pytest.ini +30 -0
  167. django_cfg/modules/django_client/spectacular/__init__.py +10 -0
  168. django_cfg/modules/django_client/spectacular/async_detection.py +187 -0
  169. django_cfg/modules/django_client/spectacular/enum_naming.py +192 -0
  170. django_cfg/modules/django_client/urls.py +72 -0
  171. django_cfg/{dashboard → modules/django_dashboard}/DEBUG_README.md +2 -2
  172. django_cfg/{dashboard → modules/django_dashboard}/REFACTORING_SUMMARY.md +1 -1
  173. django_cfg/modules/django_dashboard/management/__init__.py +0 -0
  174. django_cfg/modules/django_dashboard/management/commands/__init__.py +0 -0
  175. django_cfg/{dashboard → modules/django_dashboard}/management/commands/debug_dashboard.py +5 -5
  176. django_cfg/modules/django_dashboard/sections/documentation.py +391 -0
  177. django_cfg/modules/django_email/management/__init__.py +0 -0
  178. django_cfg/modules/django_email/management/commands/__init__.py +0 -0
  179. django_cfg/modules/django_email/management/commands/test_email.py +93 -0
  180. django_cfg/modules/django_logging/LOGGING_GUIDE.md +1 -1
  181. django_cfg/modules/django_logging/django_logger.py +6 -6
  182. django_cfg/modules/django_ngrok/management/__init__.py +0 -0
  183. django_cfg/modules/django_ngrok/management/commands/__init__.py +0 -0
  184. django_cfg/modules/django_ngrok/management/commands/runserver_ngrok.py +167 -0
  185. django_cfg/modules/django_tasks/management/__init__.py +0 -0
  186. django_cfg/modules/django_tasks/management/commands/__init__.py +0 -0
  187. django_cfg/modules/django_tasks/management/commands/rundramatiq.py +254 -0
  188. django_cfg/modules/django_tasks/management/commands/rundramatiq_simulator.py +437 -0
  189. django_cfg/modules/django_tasks/management/commands/task_clear.py +226 -0
  190. django_cfg/modules/django_tasks/management/commands/task_status.py +257 -0
  191. django_cfg/modules/django_telegram/management/__init__.py +0 -0
  192. django_cfg/modules/django_telegram/management/commands/__init__.py +0 -0
  193. django_cfg/modules/django_telegram/management/commands/test_telegram.py +68 -0
  194. django_cfg/modules/django_twilio/management/__init__.py +0 -0
  195. django_cfg/modules/django_twilio/management/commands/__init__.py +0 -0
  196. django_cfg/modules/django_twilio/management/commands/test_twilio.py +112 -0
  197. django_cfg/modules/django_unfold/callbacks/main.py +21 -10
  198. django_cfg/modules/django_unfold/callbacks/revolution.py +41 -36
  199. django_cfg/pyproject.toml +2 -6
  200. django_cfg/registry/third_party.py +5 -7
  201. django_cfg/routing/callbacks.py +1 -1
  202. django_cfg/static/admin/css/prose-unfold.css +666 -0
  203. django_cfg/templates/admin/index.html +8 -0
  204. django_cfg/templates/admin/index_new.html +13 -0
  205. django_cfg/templates/admin/layouts/dashboard_with_tabs.html +15 -3
  206. django_cfg/templates/admin/sections/documentation_section.html +172 -0
  207. django_cfg/templates/admin/snippets/tabs/documentation_tab.html +231 -0
  208. {django_cfg-1.4.10.dist-info → django_cfg-1.4.13.dist-info}/METADATA +2 -2
  209. {django_cfg-1.4.10.dist-info → django_cfg-1.4.13.dist-info}/RECORD +224 -74
  210. django_cfg/management/commands/generate.py +0 -107
  211. /django_cfg/models/django/{revolution.py → revolution_legacy.py} +0 -0
  212. /django_cfg/{dashboard → modules/django_admin}/management/__init__.py +0 -0
  213. /django_cfg/{dashboard → modules/django_admin}/management/commands/__init__.py +0 -0
  214. /django_cfg/{dashboard → modules/django_dashboard}/__init__.py +0 -0
  215. /django_cfg/{dashboard → modules/django_dashboard}/components.py +0 -0
  216. /django_cfg/{dashboard → modules/django_dashboard}/debug.py +0 -0
  217. /django_cfg/{dashboard → modules/django_dashboard}/sections/__init__.py +0 -0
  218. /django_cfg/{dashboard → modules/django_dashboard}/sections/base.py +0 -0
  219. /django_cfg/{dashboard → modules/django_dashboard}/sections/commands.py +0 -0
  220. /django_cfg/{dashboard → modules/django_dashboard}/sections/overview.py +0 -0
  221. /django_cfg/{dashboard → modules/django_dashboard}/sections/stats.py +0 -0
  222. /django_cfg/{dashboard → modules/django_dashboard}/sections/system.py +0 -0
  223. {django_cfg-1.4.10.dist-info → django_cfg-1.4.13.dist-info}/WHEEL +0 -0
  224. {django_cfg-1.4.10.dist-info → django_cfg-1.4.13.dist-info}/entry_points.txt +0 -0
  225. {django_cfg-1.4.10.dist-info → django_cfg-1.4.13.dist-info}/licenses/LICENSE +0 -0
@@ -1,390 +1,20 @@
1
1
  """
2
- 🌳 Django CFG Tree Command
2
+ Django-CFG wrapper for tree command.
3
3
 
4
- Display Django project structure in a tree format based on configuration.
5
- """
6
-
7
- import os
8
- import subprocess
9
- from pathlib import Path
10
- from typing import List, Optional
11
-
12
- from django.core.management.base import BaseCommand, CommandError
13
- from django.conf import settings
14
- from django_cfg.modules.django_logging import get_logger
15
-
16
-
17
- from django_cfg.core.state import get_current_config
18
- from django_cfg.utils.path_resolution import PathResolver
4
+ This is a simple alias for django_admin.management.commands.tree.
5
+ All logic is in django_admin module.
19
6
 
7
+ Usage:
8
+ python manage.py tree
9
+ """
20
10
 
21
- logger = get_logger('tree')
11
+ from django_cfg.modules.django_admin.management.commands.tree import Command as TreeCommand
22
12
 
23
- class Command(BaseCommand):
24
- """Display Django project structure in tree format."""
25
13
 
26
- # Web execution metadata
27
- web_executable = True
28
- requires_input = False
29
- is_destructive = False
14
+ class Command(TreeCommand):
15
+ """
16
+ Alias for tree command.
30
17
 
31
- help = "Display Django project structure based on django-cfg configuration"
32
-
33
- def add_arguments(self, parser):
34
- """Add command arguments."""
35
- parser.add_argument(
36
- '--depth', '-L',
37
- type=int,
38
- default=5,
39
- help='Maximum depth to display (default: 5)'
40
- )
41
- parser.add_argument(
42
- '--all', '-a',
43
- action='store_true',
44
- help='Show all files including hidden ones'
45
- )
46
- parser.add_argument(
47
- '--dirs-only', '-d',
48
- action='store_true',
49
- help='Show directories only'
50
- )
51
- parser.add_argument(
52
- '--no-ignore', '-n',
53
- action='store_true',
54
- help='Do not ignore common directories (node_modules, .git, etc.)'
55
- )
56
- parser.add_argument(
57
- '--custom-ignore',
58
- type=str,
59
- help='Custom ignore pattern (pipe-separated, e.g., "*.pyc|temp|logs")'
60
- )
61
- parser.add_argument(
62
- '--include-docs',
63
- action='store_true',
64
- help='Legacy option - @docs directories are now included by default'
65
- )
66
- parser.add_argument(
67
- '--include-docker',
68
- action='store_true',
69
- help='Include Docker configuration and volumes'
70
- )
71
- parser.add_argument(
72
- '--include-logs',
73
- action='store_true',
74
- help='Include log files and directories'
75
- )
76
- parser.add_argument(
77
- '--output', '-o',
78
- type=str,
79
- help='Output to file instead of stdout'
80
- )
81
- parser.add_argument(
82
- '--format',
83
- choices=['tree', 'json', 'xml'],
84
- default='tree',
85
- help='Output format (default: tree)'
86
- )
87
-
88
- def handle(self, *args, **options):
89
- """Execute the command."""
90
- logger.info("Starting tree command")
91
- try:
92
- # Get django-cfg configuration
93
- config = get_current_config()
94
-
95
- # Determine base directory
96
- base_dir = self.get_base_directory(config)
97
-
98
- self.stdout.write(
99
- self.style.SUCCESS(f"📁 Django Project Structure: {base_dir}")
100
- )
101
-
102
- # Try to get environment info
103
- try:
104
- env_info = getattr(config, 'env_mode', 'unknown')
105
- self.stdout.write(
106
- self.style.HTTP_INFO(f"🔧 Environment: {env_info}")
107
- )
108
- except Exception:
109
- pass
110
-
111
- self.stdout.write("")
112
-
113
- # Check if tree command is available
114
- if not self.is_tree_available():
115
- self.stdout.write(
116
- self.style.WARNING("⚠️ 'tree' command not found. Using fallback implementation.")
117
- )
118
- self.display_fallback_tree(base_dir, options)
119
- else:
120
- self.display_tree(base_dir, options)
121
-
122
- except Exception as e:
123
- raise CommandError(f"Failed to display project tree: {e}")
124
-
125
- def get_base_directory(self, config) -> Path:
126
- """Get the base directory for the Django project tree."""
127
- try:
128
- # First try to use PathResolver to find the actual Django project root
129
- return PathResolver.find_project_root()
130
- except Exception:
131
- try:
132
- # Try to get from config
133
- if hasattr(config, 'base_dir') and config.base_dir:
134
- return Path(config.base_dir)
135
-
136
- # Fallback to Django BASE_DIR
137
- if hasattr(settings, 'BASE_DIR'):
138
- return Path(settings.BASE_DIR)
139
-
140
- # Last resort: current working directory
141
- return Path.cwd()
142
-
143
- except Exception as e:
144
- self.stdout.write(
145
- self.style.WARNING(f"Could not determine base directory: {e}")
146
- )
147
- return Path.cwd()
148
-
149
- def is_tree_available(self) -> bool:
150
- """Check if tree command is available."""
151
- try:
152
- subprocess.run(['tree', '--version'],
153
- capture_output=True,
154
- check=True)
155
- return True
156
- except (subprocess.CalledProcessError, FileNotFoundError):
157
- return False
158
-
159
- def build_ignore_pattern(self, options) -> str:
160
- """Build ignore pattern for tree command."""
161
- if options['no_ignore']:
162
- return ""
163
-
164
- # Default ignore patterns
165
- default_ignores = [
166
- 'node_modules',
167
- '.git',
168
- '.venv',
169
- 'venv',
170
- '.env',
171
- '.DS_Store',
172
- '__pycache__',
173
- '*.pyc',
174
- '*.pyo',
175
- '*.pyd',
176
- '.pytest_cache',
177
- '.coverage',
178
- 'htmlcov',
179
- 'coverage',
180
- '.tox',
181
- 'dist',
182
- 'build',
183
- '*.egg-info',
184
- 'staticfiles',
185
- 'media',
186
- '@old*',
187
- 'parsers',
188
- 'openapi',
189
- 'modules',
190
- 'django_cfg',
191
- # Package manager files
192
- 'package-lock.json',
193
- 'pnpm-lock.yaml',
194
- 'poetry.lock',
195
- 'yarn.lock',
196
- # Empty/system directories
197
- 'db',
198
- 'static'
199
- ]
200
-
201
- # Conditionally add patterns based on options
202
- # Note: @docs folders are now included by default to show documentation
203
-
204
- if not options.get('include_docker'):
205
- default_ignores.extend([
206
- 'docker',
207
- 'devops'
208
- ])
209
-
210
- if not options.get('include_logs'):
211
- default_ignores.extend([
212
- 'logs',
213
- '*.log',
214
- 'log'
215
- ])
216
-
217
- # Add custom ignores
218
- if options['custom_ignore']:
219
- custom_ignores = options['custom_ignore'].split('|')
220
- default_ignores.extend(custom_ignores)
221
-
222
- return '|'.join(default_ignores)
223
-
224
- def display_tree(self, base_dir: Path, options):
225
- """Display tree using system tree command."""
226
- try:
227
- # Build tree command
228
- cmd = ['tree']
229
-
230
- # Add ignore pattern
231
- ignore_pattern = self.build_ignore_pattern(options)
232
- if ignore_pattern:
233
- cmd.extend(['-I', ignore_pattern])
234
-
235
- # Add options
236
- cmd.append('--dirsfirst') # Directories first
237
-
238
- if options['depth']:
239
- cmd.extend(['-L', str(options['depth'])])
240
-
241
- if options['dirs_only']:
242
- cmd.append('-d')
243
-
244
- if options['all']:
245
- cmd.append('-a')
246
-
247
- # Add format options
248
- if options['format'] == 'json':
249
- cmd.append('-J')
250
- elif options['format'] == 'xml':
251
- cmd.append('-X')
252
-
253
- # Add base directory
254
- cmd.append(str(base_dir))
255
-
256
- # Execute command
257
- if options['output']:
258
- with open(options['output'], 'w') as f:
259
- result = subprocess.run(cmd, stdout=f, stderr=subprocess.PIPE, text=True)
260
- if result.returncode == 0:
261
- self.stdout.write(
262
- self.style.SUCCESS(f"✅ Tree output saved to: {options['output']}")
263
- )
264
- else:
265
- self.stdout.write(
266
- self.style.ERROR(f"❌ Tree command failed: {result.stderr}")
267
- )
268
- else:
269
- result = subprocess.run(cmd, text=True)
270
- if result.returncode != 0:
271
- self.stdout.write(
272
- self.style.ERROR("❌ Tree command failed")
273
- )
274
-
275
- except Exception as e:
276
- self.stdout.write(
277
- self.style.ERROR(f"❌ Failed to execute tree command: {e}")
278
- )
279
- self.display_fallback_tree(base_dir, options)
280
-
281
- def display_fallback_tree(self, base_dir: Path, options):
282
- """Fallback tree implementation using Python."""
283
- self.stdout.write("🐍 Using Python fallback implementation:")
284
- self.stdout.write("")
285
-
286
- ignore_patterns = self.build_ignore_pattern(options).split('|') if not options['no_ignore'] else []
287
-
288
- def should_ignore(path: Path) -> bool:
289
- """Check if path should be ignored."""
290
- name = path.name
291
- for pattern in ignore_patterns:
292
- if pattern.startswith('*'):
293
- if name.endswith(pattern[1:]):
294
- return True
295
- elif pattern.endswith('*'):
296
- if name.startswith(pattern[:-1]):
297
- return True
298
- elif pattern == name:
299
- return True
300
- return False
301
-
302
- def print_tree(directory: Path, prefix: str = "", depth: int = 0):
303
- """Recursively print directory tree."""
304
- if options['depth'] and depth >= options['depth']:
305
- return
306
-
307
- try:
308
- items = []
309
- for item in directory.iterdir():
310
- if not options['all'] and item.name.startswith('.'):
311
- continue
312
- if should_ignore(item):
313
- continue
314
- items.append(item)
315
-
316
- # Sort: directories first, then files
317
- items.sort(key=lambda x: (not x.is_dir(), x.name.lower()))
318
-
319
- for i, item in enumerate(items):
320
- is_last = i == len(items) - 1
321
- current_prefix = "└── " if is_last else "├── "
322
-
323
- if item.is_dir():
324
- self.stdout.write(f"{prefix}{current_prefix}📁 {item.name}/")
325
- if not options['dirs_only']:
326
- next_prefix = prefix + (" " if is_last else "│ ")
327
- print_tree(item, next_prefix, depth + 1)
328
- elif not options['dirs_only']:
329
- # Add file type emoji
330
- emoji = self.get_file_emoji(item)
331
- self.stdout.write(f"{prefix}{current_prefix}{emoji} {item.name}")
332
-
333
- except PermissionError:
334
- self.stdout.write(f"{prefix}❌ Permission denied")
335
-
336
- print_tree(base_dir)
337
-
338
- def get_file_emoji(self, file_path: Path) -> str:
339
- """Get emoji for file type."""
340
- suffix = file_path.suffix.lower()
341
-
342
- emoji_map = {
343
- '.py': '🐍',
344
- '.js': '📜',
345
- '.ts': '📘',
346
- '.html': '🌐',
347
- '.css': '🎨',
348
- '.scss': '🎨',
349
- '.json': '📋',
350
- '.yaml': '📄',
351
- '.yml': '📄',
352
- '.toml': '⚙️',
353
- '.ini': '⚙️',
354
- '.cfg': '⚙️',
355
- '.conf': '⚙️',
356
- '.md': '📝',
357
- '.txt': '📄',
358
- '.log': '📊',
359
- '.sql': '🗄️',
360
- '.db': '🗄️',
361
- '.sqlite': '🗄️',
362
- '.sqlite3': '🗄️',
363
- '.png': '🖼️',
364
- '.jpg': '🖼️',
365
- '.jpeg': '🖼️',
366
- '.gif': '🖼️',
367
- '.svg': '🖼️',
368
- '.ico': '🖼️',
369
- '.pdf': '📕',
370
- '.zip': '📦',
371
- '.tar': '📦',
372
- '.gz': '📦',
373
- '.requirements': '📋',
374
- 'requirements.txt': '📋',
375
- 'Dockerfile': '🐳',
376
- 'docker-compose.yml': '🐳',
377
- 'manage.py': '⚙️',
378
- 'setup.py': '⚙️',
379
- 'pyproject.toml': '📦',
380
- 'poetry.lock': '🔒',
381
- 'Pipfile': '📦',
382
- 'Pipfile.lock': '🔒',
383
- }
384
-
385
- # Check full filename first
386
- if file_path.name in emoji_map:
387
- return emoji_map[file_path.name]
388
-
389
- # Then check extension
390
- return emoji_map.get(suffix, '📄')
18
+ Simply inherits from TreeCommand without any changes.
19
+ """
20
+ pass
@@ -0,0 +1,10 @@
1
+ """
2
+ Alias for validate_openapi command.
3
+
4
+ This is an alias that delegates to the actual implementation in
5
+ django_cfg.modules.django_client.management.commands.validate_openapi
6
+
7
+ For backward compatibility and discoverability.
8
+ """
9
+
10
+ from django_cfg.modules.django_client.management.commands.validate_openapi import Command # noqa: F401
@@ -47,7 +47,7 @@ The middleware intelligently detects API requests using:
47
47
  3. **REST methods** (POST, PUT, PATCH, DELETE) on non-admin paths
48
48
 
49
49
  4. **Configured API prefixes**
50
- - Django Revolution API: `/{api_prefix}/` (from config)
50
+ - Django Client API: `/{api_prefix}/` (from config)
51
51
  - Django CFG API: `/cfg/` (always)
52
52
 
53
53
  ### 📊 Statistics
@@ -103,9 +103,9 @@ class UserActivityMiddleware(MiddlewareMixin, BaseCfgModule):
103
103
  try:
104
104
  config = self.get_config()
105
105
  if config:
106
- # Check Django Revolution API prefix
107
- if hasattr(config, 'revolution') and config.revolution:
108
- api_prefix = f"/{getattr(config.revolution, 'api_prefix', 'api')}/"
106
+ # Check Django Client (OpenAPI) API prefix
107
+ if hasattr(config, 'openapi_client') and config.openapi_client:
108
+ api_prefix = f"/{getattr(config.openapi_client, 'api_prefix', 'api')}/"
109
109
  if path.startswith(api_prefix):
110
110
  return True
111
111
 
@@ -38,7 +38,7 @@ from .api.drf.redoc import RedocUISettings
38
38
  # Django-specific
39
39
  from .django.environment import EnvironmentConfig
40
40
  from .django.constance import ConstanceConfig, ConstanceField
41
- from .django.revolution import RevolutionConfig
41
+ from .django.openapi import OpenAPIClientConfig
42
42
 
43
43
  # Services
44
44
  from .services.email import EmailConfig
@@ -80,7 +80,7 @@ __all__ = [
80
80
  "EnvironmentConfig",
81
81
  "ConstanceConfig",
82
82
  "ConstanceField",
83
- "RevolutionConfig",
83
+ "OpenAPIClientConfig",
84
84
  "UnfoldConfig",
85
85
  # Services
86
86
  "EmailConfig",
@@ -54,8 +54,8 @@ class SpectacularConfig(BaseModel):
54
54
  description="Post-processing hooks"
55
55
  )
56
56
 
57
- # NOTE: Enum generation settings are handled by django-revolution
58
- # Only override if you need different values than Revolution defaults
57
+ # NOTE: Enum generation settings are handled by django-client (OpenAPI)
58
+ # Only override if you need different values than django-client defaults
59
59
 
60
60
  # Enum overrides
61
61
  enum_name_overrides: Dict[str, str] = Field(
@@ -69,7 +69,7 @@ class SpectacularConfig(BaseModel):
69
69
  """
70
70
  Get django-cfg Spectacular extensions.
71
71
 
72
- NOTE: This extends Revolution's base settings, not replaces them.
72
+ NOTE: This extends django-client's base settings, not replaces them.
73
73
  Only include settings that are unique to django-cfg or critical fixes.
74
74
 
75
75
  Args:
@@ -77,13 +77,13 @@ class SpectacularConfig(BaseModel):
77
77
  """
78
78
  settings = {
79
79
  # django-cfg specific UI enhancements
80
- "REDOC_UI_SETTINGS": self.redoc_ui_settings.to_dict(), # Revolution doesn't have custom Redoc settings
80
+ "REDOC_UI_SETTINGS": self.redoc_ui_settings.to_dict(), # django-client doesn't have custom Redoc settings
81
81
 
82
82
  # django-cfg specific processing extensions
83
83
  "ENUM_NAME_OVERRIDES": self.enum_name_overrides, # Custom enum overrides
84
84
 
85
- # CRITICAL: Ensure enum generation is always enabled (fix Revolution gaps)
86
- # These settings ensure proper enum generation even if Revolution config changes
85
+ # CRITICAL: Ensure enum generation is always enabled (fix django-client gaps)
86
+ # These settings ensure proper enum generation even if django-client config changes
87
87
  "GENERATE_ENUM_FROM_CHOICES": True,
88
88
  "ENUM_GENERATE_CHOICE_FROM_PATH": True,
89
89
  "ENUM_NAME_SUFFIX": "Enum",
@@ -6,11 +6,11 @@ Django integrations and extensions.
6
6
 
7
7
  from .environment import EnvironmentConfig
8
8
  from .constance import ConstanceConfig, ConstanceField
9
- from .revolution import RevolutionConfig
9
+ from .openapi import OpenAPIClientConfig
10
10
 
11
11
  __all__ = [
12
12
  "EnvironmentConfig",
13
13
  "ConstanceConfig",
14
14
  "ConstanceField",
15
- "RevolutionConfig",
15
+ "OpenAPIClientConfig",
16
16
  ]
@@ -0,0 +1,162 @@
1
+ """
2
+ Django Client (OpenAPI) Configuration with DRF Integration
3
+
4
+ Extended configuration model that integrates openapi_client for automatic
5
+ TypeScript and Python client generation from Django REST Framework endpoints.
6
+
7
+ This replaces django-revolution with a cleaner, faster, type-safe implementation.
8
+ """
9
+
10
+ from typing import Dict, Any, Optional
11
+ from pydantic import Field
12
+ from django_cfg.modules.django_client.core.config import OpenAPIConfig, OpenAPIGroupConfig
13
+
14
+
15
+ class OpenAPIClientConfig(OpenAPIConfig):
16
+ """
17
+ Extended OpenAPI configuration with DRF parameters for django-cfg integration.
18
+
19
+ This extends the base OpenAPIConfig to include DRF-specific
20
+ parameters and django-cfg integration helpers.
21
+
22
+ Example:
23
+ ```python
24
+ from django_cfg import OpenAPIClientConfig, OpenAPIGroupConfig
25
+
26
+ config = OpenAPIClientConfig(
27
+ enabled=True,
28
+ groups=[
29
+ OpenAPIGroupConfig(
30
+ name='api',
31
+ apps=['users', 'posts'],
32
+ title='Main API',
33
+ version='v1',
34
+ ),
35
+ ],
36
+ drf_title='My API',
37
+ drf_description='REST API for my project',
38
+ )
39
+ ```
40
+ """
41
+
42
+ # DRF Configuration parameters for automatic DRF setup
43
+ drf_title: str = Field(
44
+ default="API",
45
+ description="API title for DRF Spectacular"
46
+ )
47
+ drf_description: str = Field(
48
+ default="RESTful API",
49
+ description="API description for DRF Spectacular"
50
+ )
51
+ drf_version: str = Field(
52
+ default="1.0.0",
53
+ description="API version for DRF Spectacular"
54
+ )
55
+ drf_schema_path_prefix: Optional[str] = Field(
56
+ default=None, # Will default to "/api/" if None
57
+ description="Schema path prefix for DRF Spectacular"
58
+ )
59
+ drf_enable_browsable_api: bool = Field(
60
+ default=False,
61
+ description="Enable DRF browsable API"
62
+ )
63
+ drf_enable_throttling: bool = Field(
64
+ default=False,
65
+ description="Enable DRF throttling"
66
+ )
67
+ drf_serve_include_schema: bool = Field(
68
+ default=False,
69
+ description="Include schema in Spectacular UI"
70
+ )
71
+
72
+ # Django-cfg specific integration
73
+ api_prefix: str = Field(
74
+ default="api",
75
+ description="API prefix for URL routing (e.g., 'api' -> /api/...)"
76
+ )
77
+
78
+ def get_drf_schema_path_prefix(self) -> str:
79
+ """Get the schema path prefix, defaulting to api_prefix if not set."""
80
+ if self.drf_schema_path_prefix:
81
+ return self.drf_schema_path_prefix
82
+ return f"/{self.api_prefix}/"
83
+
84
+ def get_drf_config_kwargs(self) -> Dict[str, Any]:
85
+ """
86
+ Get kwargs for DRF configuration from this config.
87
+
88
+ Returns:
89
+ Dict of parameters for DRF + Spectacular setup
90
+ """
91
+ return {
92
+ "title": self.drf_title,
93
+ "description": self.drf_description,
94
+ "version": self.drf_version,
95
+ "schema_path_prefix": self.get_drf_schema_path_prefix(),
96
+ "enable_browsable_api": self.drf_enable_browsable_api,
97
+ "enable_throttling": self.drf_enable_throttling,
98
+ "serve_include_schema": self.drf_serve_include_schema,
99
+ # REQUIRED by django-client for correct Request/Response split
100
+ "component_split_request": True,
101
+ "component_split_patch": True,
102
+ }
103
+
104
+ def get_groups_with_defaults(self) -> Dict[str, OpenAPIGroupConfig]:
105
+ """
106
+ Get groups with django-cfg default groups automatically added.
107
+
108
+ Returns:
109
+ Dict of groups including default django-cfg groups
110
+ """
111
+ # Convert list to dict for compatibility
112
+ groups_dict = {group.name: group for group in self.groups}
113
+
114
+ # Add default django-cfg groups if enabled
115
+ try:
116
+ from django_cfg.modules.base import BaseCfgModule
117
+ base_module = BaseCfgModule()
118
+
119
+ support_enabled = base_module.is_support_enabled()
120
+ accounts_enabled = base_module.is_accounts_enabled()
121
+ newsletter_enabled = base_module.is_newsletter_enabled()
122
+ leads_enabled = base_module.is_leads_enabled()
123
+ knowbase_enabled = base_module.is_knowbase_enabled()
124
+ agents_enabled = base_module.is_agents_enabled()
125
+ tasks_enabled = base_module.should_enable_tasks()
126
+ payments_enabled = base_module.is_payments_enabled()
127
+
128
+ # Collect all enabled django-cfg apps for unified group
129
+ enabled_cfg_apps = []
130
+ if support_enabled:
131
+ enabled_cfg_apps.append("django_cfg.apps.support")
132
+ if accounts_enabled:
133
+ enabled_cfg_apps.append("django_cfg.apps.accounts")
134
+ if newsletter_enabled:
135
+ enabled_cfg_apps.append("django_cfg.apps.newsletter")
136
+ if leads_enabled:
137
+ enabled_cfg_apps.append("django_cfg.apps.leads")
138
+ if knowbase_enabled:
139
+ enabled_cfg_apps.append("django_cfg.apps.knowbase")
140
+ if agents_enabled:
141
+ enabled_cfg_apps.append("django_cfg.apps.agents")
142
+ if tasks_enabled:
143
+ enabled_cfg_apps.append("django_cfg.apps.tasks")
144
+ if payments_enabled:
145
+ enabled_cfg_apps.append("django_cfg.apps.payments")
146
+
147
+ # Add unified 'cfg' group with all enabled apps
148
+ if enabled_cfg_apps and 'cfg' not in groups_dict:
149
+ groups_dict['cfg'] = OpenAPIGroupConfig(
150
+ name="cfg",
151
+ apps=enabled_cfg_apps,
152
+ title="Django-CFG API",
153
+ description="All django-cfg built-in applications",
154
+ )
155
+
156
+ return groups_dict
157
+
158
+ except Exception:
159
+ pass
160
+
161
+ return groups_dict
162
+