33import os
44import sys
55import yaml
6+ import subprocess
7+ import json
68from pathlib import Path
79import click
810
@@ -64,60 +66,83 @@ def capture_env(output, format):
6466 default = 'yaml' ,
6567 help = 'Output format (default: yaml)' ,
6668)
69+ @click .option (
70+ '--manage-py' ,
71+ '-m' ,
72+ default = 'manage.py' ,
73+ help = 'Path to manage.py (default: manage.py)' ,
74+ type = click .Path (exists = True ),
75+ )
6776@click .option (
6877 '--settings' ,
6978 '-s' ,
7079 help = 'Django settings module (e.g., myproject.settings)' ,
7180 envvar = 'DJANGO_SETTINGS_MODULE' ,
7281)
73- def capture_django_settings (output , format , settings ):
82+ def capture_django_settings (output , format , manage_py , settings ):
7483 """Capture Django settings and store them in YAML format.
7584
76- Requires Django to be installed and DJANGO_SETTINGS_MODULE to be set,
77- or pass it via --settings option .
85+ Uses 'python manage.py shell' to access Django settings.
86+ Requires manage.py to be present in the current directory or specify path with --manage-py .
7887 """
7988 try :
80- # Set Django settings module if provided
81- if settings :
82- os .environ ['DJANGO_SETTINGS_MODULE' ] = settings
83-
84- # Check if DJANGO_SETTINGS_MODULE is set
85- if 'DJANGO_SETTINGS_MODULE' not in os .environ :
89+ # Check if manage.py exists
90+ manage_path = Path (manage_py )
91+ if not manage_path .exists ():
8692 click .echo (
87- "✗ Error: DJANGO_SETTINGS_MODULE not set . "
88- "Use --settings option or set the environment variable ." ,
93+ f "✗ Error: manage.py not found at { manage_path } . "
94+ "Run this command from your Django project root or use --manage-py to specify the path ." ,
8995 err = True
9096 )
9197 sys .exit (1 )
9298
93- # Import Django
99+ # Python script to run in Django shell
100+ django_script = """
101+ import json
102+ from django.conf import settings
103+
104+ settings_dict = {}
105+ for setting in dir(settings):
106+ if setting.isupper():
94107 try:
95- import django
96- from django .conf import settings as django_settings
97- except ImportError :
98- click .echo (
99- "✗ Error: Django is not installed. "
100- "Install it with: pip install django" ,
101- err = True
102- )
108+ value = getattr(settings, setting)
109+ # Convert non-serializable types to strings
110+ if not isinstance(value, (str, int, float, bool, list, dict, type(None))):
111+ value = str(value)
112+ settings_dict[setting] = value
113+ except Exception as e:
114+ settings_dict[setting] = f"<Error retrieving value: {str(e)}>"
115+
116+ print(json.dumps(settings_dict))
117+ """
118+
119+ # Prepare environment variables
120+ env = os .environ .copy ()
121+ if settings :
122+ env ['DJANGO_SETTINGS_MODULE' ] = settings
123+
124+ # Run manage.py shell with the script
125+ result = subprocess .run (
126+ ['python' , str (manage_path ), 'shell' ],
127+ input = django_script ,
128+ capture_output = True ,
129+ text = True ,
130+ env = env ,
131+ timeout = 30
132+ )
133+
134+ if result .returncode != 0 :
135+ click .echo (f"✗ Error running Django shell:" , err = True )
136+ click .echo (result .stderr , err = True )
103137 sys .exit (1 )
104138
105- # Setup Django
106- django .setup ()
107-
108- # Get all Django settings
109- settings_dict = {}
110- for setting in dir (django_settings ):
111- # Skip private/magic attributes
112- if setting .isupper ():
113- try :
114- value = getattr (django_settings , setting )
115- # Convert non-serializable types to strings
116- if not isinstance (value , (str , int , float , bool , list , dict , type (None ))):
117- value = str (value )
118- settings_dict [setting ] = value
119- except Exception as e :
120- settings_dict [setting ] = f"<Error retrieving value: { str (e )} >"
139+ # Parse JSON output
140+ try :
141+ settings_dict = json .loads (result .stdout .strip ())
142+ except json .JSONDecodeError :
143+ click .echo (f"✗ Error: Could not parse Django settings output" , err = True )
144+ click .echo (f"Output: { result .stdout } " , err = True )
145+ sys .exit (1 )
121146
122147 # Ensure output path is Path object
123148 output_path = Path (output )
@@ -128,6 +153,9 @@ def capture_django_settings(output, format, settings):
128153
129154 click .echo (f"✓ Captured { len (settings_dict )} Django settings to { output_path } " )
130155
156+ except subprocess .TimeoutExpired :
157+ click .echo ("✗ Error: Django shell command timed out" , err = True )
158+ sys .exit (1 )
131159 except Exception as e :
132160 click .echo (f"✗ Error: { str (e )} " , err = True )
133161 sys .exit (1 )
0 commit comments