django-cfg 1.4.10__py3-none-any.whl → 1.4.11__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- django_cfg/apps/agents/management/commands/create_agent.py +1 -1
- django_cfg/apps/agents/management/commands/orchestrator_status.py +3 -3
- django_cfg/apps/newsletter/serializers.py +40 -3
- django_cfg/apps/newsletter/views/campaigns.py +12 -3
- django_cfg/apps/newsletter/views/emails.py +14 -3
- django_cfg/apps/newsletter/views/subscriptions.py +12 -2
- django_cfg/apps/payments/views/api/currencies.py +49 -6
- django_cfg/apps/payments/views/api/webhooks.py +72 -7
- django_cfg/apps/payments/views/overview/serializers.py +34 -1
- django_cfg/apps/payments/views/overview/views.py +2 -1
- django_cfg/apps/payments/views/serializers/payments.py +6 -6
- django_cfg/apps/urls.py +106 -45
- django_cfg/core/base/config_model.py +2 -2
- django_cfg/core/constants.py +1 -1
- django_cfg/core/generation/integration_generators/__init__.py +1 -1
- django_cfg/core/generation/integration_generators/api.py +72 -49
- django_cfg/core/integration/display/startup.py +30 -22
- django_cfg/core/integration/url_integration.py +15 -16
- django_cfg/dashboard/sections/documentation.py +391 -0
- django_cfg/management/commands/check_endpoints.py +11 -160
- django_cfg/management/commands/check_settings.py +13 -348
- django_cfg/management/commands/clear_constance.py +13 -201
- django_cfg/management/commands/create_token.py +13 -321
- django_cfg/management/commands/generate_clients.py +23 -0
- django_cfg/management/commands/list_urls.py +13 -306
- django_cfg/management/commands/migrate_all.py +13 -126
- django_cfg/management/commands/migrator.py +13 -396
- django_cfg/management/commands/rundramatiq.py +15 -247
- django_cfg/management/commands/rundramatiq_simulator.py +12 -429
- django_cfg/management/commands/runserver_ngrok.py +15 -160
- django_cfg/management/commands/script.py +12 -488
- django_cfg/management/commands/show_config.py +12 -215
- django_cfg/management/commands/show_urls.py +12 -342
- django_cfg/management/commands/superuser.py +15 -295
- django_cfg/management/commands/task_clear.py +14 -217
- django_cfg/management/commands/task_status.py +13 -248
- django_cfg/management/commands/test_email.py +15 -86
- django_cfg/management/commands/test_telegram.py +14 -61
- django_cfg/management/commands/test_twilio.py +15 -105
- django_cfg/management/commands/tree.py +13 -383
- django_cfg/management/commands/validate_openapi.py +10 -0
- django_cfg/middleware/README.md +1 -1
- django_cfg/middleware/user_activity.py +3 -3
- django_cfg/models/__init__.py +2 -2
- django_cfg/models/api/drf/spectacular.py +6 -6
- django_cfg/models/django/__init__.py +2 -2
- django_cfg/models/django/openapi.py +238 -0
- django_cfg/modules/django_admin/management/__init__.py +0 -0
- django_cfg/modules/django_admin/management/commands/__init__.py +0 -0
- django_cfg/modules/django_admin/management/commands/check_endpoints.py +169 -0
- django_cfg/modules/django_admin/management/commands/check_settings.py +355 -0
- django_cfg/modules/django_admin/management/commands/clear_constance.py +208 -0
- django_cfg/modules/django_admin/management/commands/create_token.py +328 -0
- django_cfg/modules/django_admin/management/commands/list_urls.py +313 -0
- django_cfg/modules/django_admin/management/commands/migrate_all.py +133 -0
- django_cfg/modules/django_admin/management/commands/migrator.py +403 -0
- django_cfg/modules/django_admin/management/commands/script.py +496 -0
- django_cfg/modules/django_admin/management/commands/show_config.py +225 -0
- django_cfg/modules/django_admin/management/commands/show_urls.py +361 -0
- django_cfg/modules/django_admin/management/commands/superuser.py +302 -0
- django_cfg/modules/django_admin/management/commands/tree.py +390 -0
- django_cfg/modules/django_client/__init__.py +20 -0
- django_cfg/modules/django_client/apps.py +35 -0
- django_cfg/modules/django_client/core/__init__.py +56 -0
- django_cfg/modules/django_client/core/archive/__init__.py +11 -0
- django_cfg/modules/django_client/core/archive/manager.py +134 -0
- django_cfg/modules/django_client/core/cli/__init__.py +12 -0
- django_cfg/modules/django_client/core/cli/main.py +235 -0
- django_cfg/modules/django_client/core/config/__init__.py +18 -0
- django_cfg/modules/django_client/core/config/config.py +188 -0
- django_cfg/modules/django_client/core/config/group.py +101 -0
- django_cfg/modules/django_client/core/config/service.py +209 -0
- django_cfg/modules/django_client/core/generator/__init__.py +115 -0
- django_cfg/modules/django_client/core/generator/base.py +767 -0
- django_cfg/modules/django_client/core/generator/python.py +751 -0
- django_cfg/modules/django_client/core/generator/templates/python/__init__.py.jinja +9 -0
- django_cfg/modules/django_client/core/generator/templates/python/api_wrapper.py.jinja +130 -0
- django_cfg/modules/django_client/core/generator/templates/python/app_init.py.jinja +6 -0
- django_cfg/modules/django_client/core/generator/templates/python/client/app_client.py.jinja +18 -0
- django_cfg/modules/django_client/core/generator/templates/python/client/flat_client.py.jinja +38 -0
- django_cfg/modules/django_client/core/generator/templates/python/client/main_client.py.jinja +50 -0
- django_cfg/modules/django_client/core/generator/templates/python/client/main_client_file.py.jinja +13 -0
- django_cfg/modules/django_client/core/generator/templates/python/client/operation_method.py.jinja +7 -0
- django_cfg/modules/django_client/core/generator/templates/python/client/sub_client.py.jinja +11 -0
- django_cfg/modules/django_client/core/generator/templates/python/client_file.py.jinja +13 -0
- django_cfg/modules/django_client/core/generator/templates/python/main_init.py.jinja +50 -0
- django_cfg/modules/django_client/core/generator/templates/python/models/app_models.py.jinja +17 -0
- django_cfg/modules/django_client/core/generator/templates/python/models/enum_class.py.jinja +15 -0
- django_cfg/modules/django_client/core/generator/templates/python/models/enums.py.jinja +8 -0
- django_cfg/modules/django_client/core/generator/templates/python/models/models.py.jinja +17 -0
- django_cfg/modules/django_client/core/generator/templates/python/models/schema_class.py.jinja +19 -0
- django_cfg/modules/django_client/core/generator/templates/python/utils/logger.py.jinja +255 -0
- django_cfg/modules/django_client/core/generator/templates/python/utils/schema.py.jinja +12 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/app_index.ts.jinja +2 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/client/app_client.ts.jinja +18 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/client/client.ts.jinja +327 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/client/flat_client.ts.jinja +109 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/client/main_client_file.ts.jinja +9 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/client/operation.ts.jinja +61 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/client/sub_client.ts.jinja +15 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/client_file.ts.jinja +9 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/index.ts.jinja +5 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/main_index.ts.jinja +206 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/models/app_models.ts.jinja +8 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/models/enums.ts.jinja +4 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/models/models.ts.jinja +8 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/utils/errors.ts.jinja +114 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/utils/http.ts.jinja +98 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/utils/logger.ts.jinja +251 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/utils/schema.ts.jinja +7 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/utils/storage.ts.jinja +114 -0
- django_cfg/modules/django_client/core/generator/typescript.py +872 -0
- django_cfg/modules/django_client/core/groups/__init__.py +13 -0
- django_cfg/modules/django_client/core/groups/detector.py +178 -0
- django_cfg/modules/django_client/core/groups/manager.py +314 -0
- django_cfg/modules/django_client/core/ir/__init__.py +57 -0
- django_cfg/modules/django_client/core/ir/context.py +387 -0
- django_cfg/modules/django_client/core/ir/operation.py +518 -0
- django_cfg/modules/django_client/core/ir/schema.py +353 -0
- django_cfg/modules/django_client/core/parser/__init__.py +74 -0
- django_cfg/modules/django_client/core/parser/base.py +648 -0
- django_cfg/modules/django_client/core/parser/models/__init__.py +74 -0
- django_cfg/modules/django_client/core/parser/models/base.py +212 -0
- django_cfg/modules/django_client/core/parser/models/components.py +160 -0
- django_cfg/modules/django_client/core/parser/models/openapi.py +203 -0
- django_cfg/modules/django_client/core/parser/models/operation.py +207 -0
- django_cfg/modules/django_client/core/parser/models/schema.py +266 -0
- django_cfg/modules/django_client/core/parser/openapi30.py +56 -0
- django_cfg/modules/django_client/core/parser/openapi31.py +64 -0
- django_cfg/modules/django_client/core/validation/__init__.py +22 -0
- django_cfg/modules/django_client/core/validation/checker.py +134 -0
- django_cfg/modules/django_client/core/validation/fixer.py +216 -0
- django_cfg/modules/django_client/core/validation/reporter.py +480 -0
- django_cfg/modules/django_client/core/validation/rules/__init__.py +11 -0
- django_cfg/modules/django_client/core/validation/rules/base.py +96 -0
- django_cfg/modules/django_client/core/validation/rules/type_hints.py +288 -0
- django_cfg/modules/django_client/core/validation/safety.py +266 -0
- django_cfg/modules/django_client/management/__init__.py +3 -0
- django_cfg/modules/django_client/management/commands/__init__.py +3 -0
- django_cfg/modules/django_client/management/commands/generate_client.py +422 -0
- django_cfg/modules/django_client/management/commands/validate_openapi.py +343 -0
- django_cfg/modules/django_client/spectacular/__init__.py +9 -0
- django_cfg/modules/django_client/spectacular/enum_naming.py +192 -0
- django_cfg/modules/django_client/urls.py +72 -0
- django_cfg/modules/django_email/management/__init__.py +0 -0
- django_cfg/modules/django_email/management/commands/__init__.py +0 -0
- django_cfg/modules/django_email/management/commands/test_email.py +93 -0
- django_cfg/modules/django_logging/django_logger.py +6 -6
- django_cfg/modules/django_ngrok/management/__init__.py +0 -0
- django_cfg/modules/django_ngrok/management/commands/__init__.py +0 -0
- django_cfg/modules/django_ngrok/management/commands/runserver_ngrok.py +167 -0
- django_cfg/modules/django_tasks/management/__init__.py +0 -0
- django_cfg/modules/django_tasks/management/commands/__init__.py +0 -0
- django_cfg/modules/django_tasks/management/commands/rundramatiq.py +254 -0
- django_cfg/modules/django_tasks/management/commands/rundramatiq_simulator.py +437 -0
- django_cfg/modules/django_tasks/management/commands/task_clear.py +226 -0
- django_cfg/modules/django_tasks/management/commands/task_status.py +257 -0
- django_cfg/modules/django_telegram/management/__init__.py +0 -0
- django_cfg/modules/django_telegram/management/commands/__init__.py +0 -0
- django_cfg/modules/django_telegram/management/commands/test_telegram.py +68 -0
- django_cfg/modules/django_twilio/management/__init__.py +0 -0
- django_cfg/modules/django_twilio/management/commands/__init__.py +0 -0
- django_cfg/modules/django_twilio/management/commands/test_twilio.py +112 -0
- django_cfg/modules/django_unfold/callbacks/main.py +16 -5
- django_cfg/modules/django_unfold/callbacks/revolution.py +41 -36
- django_cfg/pyproject.toml +2 -6
- django_cfg/registry/third_party.py +5 -7
- django_cfg/routing/callbacks.py +1 -1
- django_cfg/static/admin/css/prose-unfold.css +666 -0
- django_cfg/templates/admin/index.html +8 -0
- django_cfg/templates/admin/index_new.html +13 -0
- django_cfg/templates/admin/layouts/dashboard_with_tabs.html +15 -3
- django_cfg/templates/admin/sections/documentation_section.html +172 -0
- django_cfg/templates/admin/snippets/tabs/documentation_tab.html +231 -0
- {django_cfg-1.4.10.dist-info → django_cfg-1.4.11.dist-info}/METADATA +2 -2
- {django_cfg-1.4.10.dist-info → django_cfg-1.4.11.dist-info}/RECORD +180 -59
- django_cfg/management/commands/generate.py +0 -107
- /django_cfg/models/django/{revolution.py → revolution_legacy.py} +0 -0
- {django_cfg-1.4.10.dist-info → django_cfg-1.4.11.dist-info}/WHEEL +0 -0
- {django_cfg-1.4.10.dist-info → django_cfg-1.4.11.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.4.10.dist-info → django_cfg-1.4.11.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,496 @@
|
|
1
|
+
"""
|
2
|
+
Script Command for Django Config Toolkit
|
3
|
+
Run custom scripts and manage Django applications.
|
4
|
+
"""
|
5
|
+
|
6
|
+
import os
|
7
|
+
import sys
|
8
|
+
import subprocess
|
9
|
+
import importlib
|
10
|
+
from pathlib import Path
|
11
|
+
from django.core.management.base import BaseCommand
|
12
|
+
from django.core.management import call_command
|
13
|
+
from django.conf import settings
|
14
|
+
import questionary
|
15
|
+
from datetime import datetime
|
16
|
+
from django_cfg.modules.django_logging import get_logger
|
17
|
+
|
18
|
+
|
19
|
+
logger = get_logger('script')
|
20
|
+
|
21
|
+
class Command(BaseCommand):
|
22
|
+
# Web execution metadata
|
23
|
+
web_executable = False
|
24
|
+
requires_input = True
|
25
|
+
is_destructive = False
|
26
|
+
|
27
|
+
help = 'Run custom scripts and manage Django applications'
|
28
|
+
|
29
|
+
def add_arguments(self, parser):
|
30
|
+
parser.add_argument(
|
31
|
+
'--script',
|
32
|
+
type=str,
|
33
|
+
help='Script name to run'
|
34
|
+
)
|
35
|
+
parser.add_argument(
|
36
|
+
'--list',
|
37
|
+
action='store_true',
|
38
|
+
help='List available scripts'
|
39
|
+
)
|
40
|
+
parser.add_argument(
|
41
|
+
'--create',
|
42
|
+
type=str,
|
43
|
+
help='Create new script template'
|
44
|
+
)
|
45
|
+
parser.add_argument(
|
46
|
+
'--shell',
|
47
|
+
action='store_true',
|
48
|
+
help='Open Django shell'
|
49
|
+
)
|
50
|
+
parser.add_argument(
|
51
|
+
'--check',
|
52
|
+
action='store_true',
|
53
|
+
help='Run Django system check'
|
54
|
+
)
|
55
|
+
|
56
|
+
def handle(self, *args, **options):
|
57
|
+
logger.info("Starting script command")
|
58
|
+
if options['list']:
|
59
|
+
self.list_scripts()
|
60
|
+
elif options['create']:
|
61
|
+
self.create_script_template(options['create'])
|
62
|
+
elif options['shell']:
|
63
|
+
self.open_django_shell()
|
64
|
+
elif options['check']:
|
65
|
+
self.run_django_check()
|
66
|
+
elif options['script']:
|
67
|
+
self.run_script(options['script'])
|
68
|
+
else:
|
69
|
+
self.show_interactive_menu()
|
70
|
+
|
71
|
+
def show_interactive_menu(self):
|
72
|
+
"""Show interactive menu with script options"""
|
73
|
+
self.stdout.write(self.style.SUCCESS('\n📜 Script Management Tool - Django Config Toolkit\n'))
|
74
|
+
|
75
|
+
choices = [
|
76
|
+
questionary.Choice('📋 List Available Scripts', value='list'),
|
77
|
+
questionary.Choice('➕ Create New Script', value='create'),
|
78
|
+
questionary.Choice('▶️ Run Script', value='run'),
|
79
|
+
questionary.Choice('🐚 Open Django Shell', value='shell'),
|
80
|
+
questionary.Choice('🔍 Run System Check', value='check'),
|
81
|
+
questionary.Choice('🧹 Clean Project', value='clean'),
|
82
|
+
questionary.Choice('📊 Show Project Info', value='info'),
|
83
|
+
questionary.Choice('❌ Exit', value='exit')
|
84
|
+
]
|
85
|
+
|
86
|
+
choice = questionary.select(
|
87
|
+
'Select option:',
|
88
|
+
choices=choices
|
89
|
+
).ask()
|
90
|
+
|
91
|
+
if choice == 'list':
|
92
|
+
self.list_scripts()
|
93
|
+
elif choice == 'create':
|
94
|
+
self.create_script_interactive()
|
95
|
+
elif choice == 'run':
|
96
|
+
self.run_script_interactive()
|
97
|
+
elif choice == 'shell':
|
98
|
+
self.open_django_shell()
|
99
|
+
elif choice == 'check':
|
100
|
+
self.run_django_check()
|
101
|
+
elif choice == 'clean':
|
102
|
+
self.clean_project()
|
103
|
+
elif choice == 'info':
|
104
|
+
self.show_project_info()
|
105
|
+
elif choice == 'exit':
|
106
|
+
self.stdout.write('Goodbye! 👋')
|
107
|
+
return
|
108
|
+
|
109
|
+
def list_scripts(self):
|
110
|
+
"""List available scripts"""
|
111
|
+
self.stdout.write(self.style.SUCCESS('📋 Available Scripts\n'))
|
112
|
+
|
113
|
+
# Check for scripts directory
|
114
|
+
scripts_dir = Path('scripts')
|
115
|
+
if not scripts_dir.exists():
|
116
|
+
self.stdout.write(' 📁 No scripts directory found')
|
117
|
+
self.stdout.write(' 💡 Use --create to create your first script')
|
118
|
+
return
|
119
|
+
|
120
|
+
# List Python scripts
|
121
|
+
python_scripts = list(scripts_dir.glob('*.py'))
|
122
|
+
if python_scripts:
|
123
|
+
self.stdout.write(' 🐍 Python Scripts:')
|
124
|
+
for script in python_scripts:
|
125
|
+
if script.name != '__init__.py':
|
126
|
+
self.stdout.write(f' - {script.stem}')
|
127
|
+
else:
|
128
|
+
self.stdout.write(' 🐍 No Python scripts found')
|
129
|
+
|
130
|
+
# List shell scripts
|
131
|
+
shell_scripts = list(scripts_dir.glob('*.sh'))
|
132
|
+
if shell_scripts:
|
133
|
+
self.stdout.write(' 🐚 Shell Scripts:')
|
134
|
+
for script in shell_scripts:
|
135
|
+
self.stdout.write(f' - {script.stem}')
|
136
|
+
|
137
|
+
# List other scripts
|
138
|
+
other_scripts = [s for s in scripts_dir.iterdir() if s.is_file() and s.suffix not in ['.py', '.sh']]
|
139
|
+
if other_scripts:
|
140
|
+
self.stdout.write(' 📄 Other Scripts:')
|
141
|
+
for script in other_scripts:
|
142
|
+
self.stdout.write(f' - {script.name}')
|
143
|
+
|
144
|
+
def create_script_interactive(self):
|
145
|
+
"""Create script interactively"""
|
146
|
+
self.stdout.write(self.style.SUCCESS('➕ Create New Script\n'))
|
147
|
+
|
148
|
+
# Get script name
|
149
|
+
script_name = questionary.text('Script name:').ask()
|
150
|
+
if not script_name:
|
151
|
+
self.stdout.write(self.style.ERROR('❌ Script name is required'))
|
152
|
+
return
|
153
|
+
|
154
|
+
# Get script type
|
155
|
+
script_type = questionary.select(
|
156
|
+
'Script type:',
|
157
|
+
choices=['Python Script', 'Shell Script', 'Django Management Command']
|
158
|
+
).ask()
|
159
|
+
|
160
|
+
# Create script
|
161
|
+
if script_type == 'Python Script':
|
162
|
+
self.create_python_script(script_name)
|
163
|
+
elif script_type == 'Shell Script':
|
164
|
+
self.create_shell_script(script_name)
|
165
|
+
elif script_type == 'Django Management Command':
|
166
|
+
self.create_django_command(script_name)
|
167
|
+
|
168
|
+
def create_script_template(self, script_name):
|
169
|
+
"""Create script template"""
|
170
|
+
self.create_python_script(script_name)
|
171
|
+
|
172
|
+
def create_python_script(self, script_name):
|
173
|
+
"""Create Python script template"""
|
174
|
+
# Create scripts directory
|
175
|
+
scripts_dir = Path('scripts')
|
176
|
+
scripts_dir.mkdir(exist_ok=True)
|
177
|
+
|
178
|
+
# Create __init__.py if it doesn't exist
|
179
|
+
init_file = scripts_dir / '__init__.py'
|
180
|
+
if not init_file.exists():
|
181
|
+
init_file.touch()
|
182
|
+
|
183
|
+
# Create script file
|
184
|
+
script_path = scripts_dir / f'{script_name}.py'
|
185
|
+
|
186
|
+
script_content = f'''"""
|
187
|
+
{script_name.title()} Script
|
188
|
+
Auto-generated script for Django Config Toolkit.
|
189
|
+
"""
|
190
|
+
|
191
|
+
import os
|
192
|
+
import sys
|
193
|
+
from pathlib import Path
|
194
|
+
from django.core.management import execute_from_command_line
|
195
|
+
from django.conf import settings
|
196
|
+
|
197
|
+
# Add project root to Python path
|
198
|
+
project_root = Path(__file__).resolve().parent.parent
|
199
|
+
sys.path.insert(0, str(project_root))
|
200
|
+
|
201
|
+
# Setup Django environment
|
202
|
+
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings')
|
203
|
+
|
204
|
+
# Import Django
|
205
|
+
import django
|
206
|
+
django.setup()
|
207
|
+
|
208
|
+
|
209
|
+
def main():
|
210
|
+
"""Main function for {script_name} script."""
|
211
|
+
print(f"🚀 Running {script_name} script...")
|
212
|
+
|
213
|
+
# Your script logic here
|
214
|
+
# You can use Django settings: from django.conf import settings
|
215
|
+
# Or DjangoConfig: from django_cfg.core.state import get_current_config
|
216
|
+
|
217
|
+
print("✅ Script completed successfully!")
|
218
|
+
|
219
|
+
|
220
|
+
if __name__ == '__main__':
|
221
|
+
main()
|
222
|
+
'''
|
223
|
+
|
224
|
+
with open(script_path, 'w') as f:
|
225
|
+
f.write(script_content)
|
226
|
+
|
227
|
+
self.stdout.write(f' 📄 Python script created: {script_path}')
|
228
|
+
self.stdout.write(' 💡 Edit the script to add your custom logic')
|
229
|
+
|
230
|
+
def create_shell_script(self, script_name):
|
231
|
+
"""Create shell script template"""
|
232
|
+
# Create scripts directory
|
233
|
+
scripts_dir = Path('scripts')
|
234
|
+
scripts_dir.mkdir(exist_ok=True)
|
235
|
+
|
236
|
+
# Create script file
|
237
|
+
script_path = scripts_dir / f'{script_name}.sh'
|
238
|
+
|
239
|
+
script_content = f'''#!/bin/bash
|
240
|
+
|
241
|
+
# {script_name.title()} Script
|
242
|
+
# Auto-generated shell script for Django Config Toolkit.
|
243
|
+
|
244
|
+
set -e # Exit on error
|
245
|
+
|
246
|
+
echo "🚀 Running {script_name} script..."
|
247
|
+
|
248
|
+
# Your shell script logic here
|
249
|
+
echo "✅ Script completed successfully!"
|
250
|
+
'''
|
251
|
+
|
252
|
+
with open(script_path, 'w') as f:
|
253
|
+
f.write(script_content)
|
254
|
+
|
255
|
+
# Make executable
|
256
|
+
script_path.chmod(0o755)
|
257
|
+
|
258
|
+
self.stdout.write(f' 📄 Shell script created: {script_path}')
|
259
|
+
self.stdout.write(' 💡 Edit the script to add your custom logic')
|
260
|
+
|
261
|
+
def create_django_command(self, command_name):
|
262
|
+
"""Create Django management command template"""
|
263
|
+
# Create management commands directory
|
264
|
+
commands_dir = Path('management/commands')
|
265
|
+
commands_dir.mkdir(parents=True, exist_ok=True)
|
266
|
+
|
267
|
+
# Create __init__.py files
|
268
|
+
(commands_dir.parent / '__init__.py').touch()
|
269
|
+
(commands_dir / '__init__.py').touch()
|
270
|
+
|
271
|
+
# Create command file
|
272
|
+
command_path = commands_dir / f'{command_name}.py'
|
273
|
+
|
274
|
+
command_content = f'''"""
|
275
|
+
{command_name.title()} Command
|
276
|
+
Auto-generated Django management command.
|
277
|
+
"""
|
278
|
+
|
279
|
+
from django.core.management.base import BaseCommand
|
280
|
+
from django.conf import settings
|
281
|
+
|
282
|
+
|
283
|
+
class Command(BaseCommand):
|
284
|
+
help = '{command_name.title()} command description'
|
285
|
+
|
286
|
+
def add_arguments(self, parser):
|
287
|
+
# Add command arguments here
|
288
|
+
pass
|
289
|
+
|
290
|
+
def handle(self, *args, **options):
|
291
|
+
"""Handle the command."""
|
292
|
+
self.stdout.write(self.style.SUCCESS(f'🚀 Running {command_name} command...'))
|
293
|
+
|
294
|
+
# Your command logic here
|
295
|
+
# You can use Django settings: settings.DEBUG, etc.
|
296
|
+
# Or DjangoConfig: from django_cfg.core.state import get_current_config
|
297
|
+
|
298
|
+
self.stdout.write(self.style.SUCCESS('✅ Command completed successfully!'))
|
299
|
+
'''
|
300
|
+
|
301
|
+
with open(command_path, 'w') as f:
|
302
|
+
f.write(command_content)
|
303
|
+
|
304
|
+
self.stdout.write(f' 📄 Django command created: {command_path}')
|
305
|
+
self.stdout.write(' 💡 Run with: python manage.py {command_name}')
|
306
|
+
|
307
|
+
def run_script_interactive(self):
|
308
|
+
"""Run script interactively"""
|
309
|
+
self.stdout.write(self.style.SUCCESS('▶️ Run Script\n'))
|
310
|
+
|
311
|
+
# List available scripts
|
312
|
+
scripts_dir = Path('scripts')
|
313
|
+
if not scripts_dir.exists():
|
314
|
+
self.stdout.write('❌ No scripts directory found')
|
315
|
+
return
|
316
|
+
|
317
|
+
# Get available scripts
|
318
|
+
python_scripts = [s.stem for s in scripts_dir.glob('*.py') if s.name != '__init__.py']
|
319
|
+
shell_scripts = [s.stem for s in scripts_dir.glob('*.sh')]
|
320
|
+
|
321
|
+
if not python_scripts and not shell_scripts:
|
322
|
+
self.stdout.write('❌ No scripts found')
|
323
|
+
return
|
324
|
+
|
325
|
+
# Create choices
|
326
|
+
choices = []
|
327
|
+
if python_scripts:
|
328
|
+
choices.append(questionary.Choice('🐍 Python Scripts', value='python'))
|
329
|
+
if shell_scripts:
|
330
|
+
choices.append(questionary.Choice('🐚 Shell Scripts', value='shell'))
|
331
|
+
|
332
|
+
script_type = questionary.select('Script type:', choices=choices).ask()
|
333
|
+
|
334
|
+
if script_type == 'python':
|
335
|
+
script_name = questionary.select('Select script:', choices=python_scripts).ask()
|
336
|
+
self.run_python_script(script_name)
|
337
|
+
elif script_type == 'shell':
|
338
|
+
script_name = questionary.select('Select script:', choices=shell_scripts).ask()
|
339
|
+
self.run_shell_script(script_name)
|
340
|
+
|
341
|
+
def run_script(self, script_name):
|
342
|
+
"""Run specific script"""
|
343
|
+
script_path = Path('scripts') / f'{script_name}.py'
|
344
|
+
shell_script_path = Path('scripts') / f'{script_name}.sh'
|
345
|
+
|
346
|
+
if script_path.exists():
|
347
|
+
self.run_python_script(script_name)
|
348
|
+
elif shell_script_path.exists():
|
349
|
+
self.run_shell_script(script_name)
|
350
|
+
else:
|
351
|
+
self.stdout.write(self.style.ERROR(f'❌ Script {script_name} not found'))
|
352
|
+
|
353
|
+
def run_python_script(self, script_name):
|
354
|
+
"""Run Python script"""
|
355
|
+
script_path = Path('scripts') / f'{script_name}.py'
|
356
|
+
|
357
|
+
if not script_path.exists():
|
358
|
+
self.stdout.write(self.style.ERROR(f'❌ Script {script_name} not found'))
|
359
|
+
return
|
360
|
+
|
361
|
+
self.stdout.write(self.style.SUCCESS(f'🚀 Running Python script: {script_name}'))
|
362
|
+
|
363
|
+
try:
|
364
|
+
# Run script in Django context
|
365
|
+
result = subprocess.run([
|
366
|
+
sys.executable, str(script_path)
|
367
|
+
], capture_output=True, text=True, cwd=Path.cwd())
|
368
|
+
|
369
|
+
if result.stdout:
|
370
|
+
self.stdout.write(result.stdout)
|
371
|
+
if result.stderr:
|
372
|
+
self.stdout.write(self.style.WARNING(result.stderr))
|
373
|
+
|
374
|
+
if result.returncode == 0:
|
375
|
+
self.stdout.write(self.style.SUCCESS('✅ Script completed successfully!'))
|
376
|
+
else:
|
377
|
+
self.stdout.write(self.style.ERROR('❌ Script failed'))
|
378
|
+
|
379
|
+
except Exception as e:
|
380
|
+
self.stdout.write(self.style.ERROR(f'❌ Error running script: {e}'))
|
381
|
+
|
382
|
+
def run_shell_script(self, script_name):
|
383
|
+
"""Run shell script"""
|
384
|
+
script_path = Path('scripts') / f'{script_name}.sh'
|
385
|
+
|
386
|
+
if not script_path.exists():
|
387
|
+
self.stdout.write(self.style.ERROR(f'❌ Script {script_name} not found'))
|
388
|
+
return
|
389
|
+
|
390
|
+
self.stdout.write(self.style.SUCCESS(f'🚀 Running shell script: {script_name}'))
|
391
|
+
|
392
|
+
try:
|
393
|
+
result = subprocess.run([
|
394
|
+
'bash', str(script_path)
|
395
|
+
], capture_output=True, text=True, cwd=Path.cwd())
|
396
|
+
|
397
|
+
if result.stdout:
|
398
|
+
self.stdout.write(result.stdout)
|
399
|
+
if result.stderr:
|
400
|
+
self.stdout.write(self.style.WARNING(result.stderr))
|
401
|
+
|
402
|
+
if result.returncode == 0:
|
403
|
+
self.stdout.write(self.style.SUCCESS('✅ Script completed successfully!'))
|
404
|
+
else:
|
405
|
+
self.stdout.write(self.style.ERROR('❌ Script failed'))
|
406
|
+
|
407
|
+
except Exception as e:
|
408
|
+
self.stdout.write(self.style.ERROR(f'❌ Error running script: {e}'))
|
409
|
+
|
410
|
+
def open_django_shell(self):
|
411
|
+
"""Open Django shell"""
|
412
|
+
self.stdout.write(self.style.SUCCESS('🐚 Opening Django Shell...'))
|
413
|
+
|
414
|
+
try:
|
415
|
+
call_command('shell')
|
416
|
+
except Exception as e:
|
417
|
+
self.stdout.write(self.style.ERROR(f'❌ Error opening Django shell: {e}'))
|
418
|
+
|
419
|
+
def run_django_check(self):
|
420
|
+
"""Run Django system check"""
|
421
|
+
self.stdout.write(self.style.SUCCESS('🔍 Running Django System Check...'))
|
422
|
+
|
423
|
+
try:
|
424
|
+
call_command('check', verbosity=2)
|
425
|
+
self.stdout.write(self.style.SUCCESS('✅ System check completed'))
|
426
|
+
except Exception as e:
|
427
|
+
self.stdout.write(self.style.ERROR(f'❌ System check failed: {e}'))
|
428
|
+
|
429
|
+
def clean_project(self):
|
430
|
+
"""Clean project files"""
|
431
|
+
self.stdout.write(self.style.SUCCESS('🧹 Cleaning Project...'))
|
432
|
+
|
433
|
+
# Files to clean
|
434
|
+
files_to_clean = [
|
435
|
+
'*.pyc',
|
436
|
+
'__pycache__',
|
437
|
+
'.pytest_cache',
|
438
|
+
'*.log',
|
439
|
+
'*.sqlite3',
|
440
|
+
'media/',
|
441
|
+
'staticfiles/',
|
442
|
+
]
|
443
|
+
|
444
|
+
for pattern in files_to_clean:
|
445
|
+
if '*' in pattern:
|
446
|
+
# Handle glob patterns
|
447
|
+
for file_path in Path('.').glob(pattern):
|
448
|
+
if file_path.is_file():
|
449
|
+
file_path.unlink()
|
450
|
+
self.stdout.write(f' 🗑️ Deleted: {file_path}')
|
451
|
+
else:
|
452
|
+
# Handle directories
|
453
|
+
dir_path = Path(pattern)
|
454
|
+
if dir_path.exists() and dir_path.is_dir():
|
455
|
+
import shutil
|
456
|
+
shutil.rmtree(dir_path)
|
457
|
+
self.stdout.write(f' 🗑️ Deleted directory: {dir_path}')
|
458
|
+
|
459
|
+
self.stdout.write(self.style.SUCCESS('✅ Project cleaned'))
|
460
|
+
|
461
|
+
def show_project_info(self):
|
462
|
+
"""Show project information"""
|
463
|
+
self.stdout.write(self.style.SUCCESS('📊 Project Information\n'))
|
464
|
+
|
465
|
+
# Django version
|
466
|
+
import django
|
467
|
+
self.stdout.write(f'🐍 Python: {sys.version}')
|
468
|
+
self.stdout.write(f'🎯 Django: {django.get_version()}')
|
469
|
+
|
470
|
+
# Project settings
|
471
|
+
self.stdout.write(f'📁 Project: {settings.SETTINGS_MODULE}')
|
472
|
+
self.stdout.write(f'🔧 Debug: {settings.DEBUG}')
|
473
|
+
self.stdout.write(f'🌐 Allowed Hosts: {settings.ALLOWED_HOSTS}')
|
474
|
+
|
475
|
+
# Installed apps count
|
476
|
+
self.stdout.write(f'📦 Installed Apps: {len(settings.INSTALLED_APPS)}')
|
477
|
+
|
478
|
+
# Database info
|
479
|
+
if hasattr(settings, 'DATABASES'):
|
480
|
+
self.stdout.write(f'🗄️ Databases: {len(settings.DATABASES)}')
|
481
|
+
for db_name in settings.DATABASES:
|
482
|
+
engine = settings.DATABASES[db_name].get('ENGINE', 'Unknown')
|
483
|
+
self.stdout.write(f' - {db_name}: {engine}')
|
484
|
+
|
485
|
+
# Django-CFG info
|
486
|
+
try:
|
487
|
+
from django_cfg.core.state import get_current_config
|
488
|
+
config = get_current_config()
|
489
|
+
if config:
|
490
|
+
self.stdout.write(f'⚙️ Django-CFG: Loaded')
|
491
|
+
if hasattr(config, 'project_name'):
|
492
|
+
self.stdout.write(f' - Project: {config.project_name}')
|
493
|
+
else:
|
494
|
+
self.stdout.write(f'⚠️ Django-CFG: No config loaded')
|
495
|
+
except Exception as e:
|
496
|
+
self.stdout.write(f'❌ Django-CFG: Error - {e}')
|