Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e3644e2

Browse files
committed
Added 'run_setup()' to allow outsiders to run a setup script under
fairly tight control, and the '_setup_stop_after' and '_setup_distribution' globals to provide the tight control. This isn't entirely reliable yet: it dies horribly with a NameError on the example PIL setup script in examples/pil_setup.py (at least with Python 1.5.2; untested with current Python). There's some strangeness going on with execfile(), but I don't understand it and don't have time to track it down right now.
1 parent 51de690 commit e3644e2

1 file changed

Lines changed: 89 additions & 1 deletion

File tree

Lib/distutils/core.py

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ def gen_usage (script_name):
4242
return USAGE % vars()
4343

4444

45+
# Some mild magic to control the behaviour of 'setup()' from 'run_setup()'.
46+
_setup_stop_after = None
47+
_setup_distribution = None
48+
49+
4550
def setup (**attrs):
4651
"""The gateway to the Distutils: do everything your setup script needs
4752
to do, in a highly flexible and user-driven way. Briefly: create a
@@ -75,6 +80,8 @@ class found in 'cmdclass' is used in place of the default, which is
7580
object.
7681
"""
7782

83+
global _setup_stop_after, _setup_distribution
84+
7885
# Determine the distribution class -- either caller-supplied or
7986
# our Distribution (see below).
8087
klass = attrs.get ('distclass')
@@ -91,10 +98,13 @@ class found in 'cmdclass' is used in place of the default, which is
9198
# Create the Distribution instance, using the remaining arguments
9299
# (ie. everything except distclass) to initialize it
93100
try:
94-
dist = klass (attrs)
101+
_setup_distribution = dist = klass (attrs)
95102
except DistutilsSetupError, msg:
96103
raise SystemExit, "error in setup script: %s" % msg
97104

105+
if _setup_stop_after == "init":
106+
return dist
107+
98108
# Find and parse the config file(s): they will override options from
99109
# the setup script, but be overridden by the command line.
100110
dist.parse_config_files()
@@ -103,6 +113,9 @@ class found in 'cmdclass' is used in place of the default, which is
103113
print "options (after parsing config files):"
104114
dist.dump_option_dicts()
105115

116+
if _setup_stop_after == "config":
117+
return dist
118+
106119
# Parse the command line; any command-line errors are the end user's
107120
# fault, so turn them into SystemExit to suppress tracebacks.
108121
try:
@@ -116,6 +129,9 @@ class found in 'cmdclass' is used in place of the default, which is
116129
print "options (after parsing command line):"
117130
dist.dump_option_dicts()
118131

132+
if _setup_stop_after == "commandline":
133+
return dist
134+
119135
# And finally, run all the commands found on the command line.
120136
if ok:
121137
try:
@@ -140,4 +156,76 @@ class found in 'cmdclass' is used in place of the default, which is
140156
else:
141157
raise SystemExit, "error: " + str(msg)
142158

159+
return dist
160+
143161
# setup ()
162+
163+
164+
def run_setup (script_name, script_args=None, stop_after="run"):
165+
"""Run a setup script in a somewhat controlled environment, and
166+
return the Distribution instance that drives things. This is useful
167+
if you need to find out the distribution meta-data (passed as
168+
keyword args from 'script' to 'setup()', or the contents of the
169+
config files or command-line.
170+
171+
'script_name' is a file that will be run with 'execfile()';
172+
'sys.argv[0]' will be replaced with 'script' for the duration of the
173+
call. 'script_args' is a list of strings; if supplied,
174+
'sys.argv[1:]' will be replaced by 'script_args' for the duration of
175+
the call.
176+
177+
'stop_after' tells 'setup()' when to stop processing; possible
178+
values:
179+
init
180+
stop after the Distribution instance has been created and
181+
populated with the keyword arguments to 'setup()'
182+
config
183+
stop after config files have been parsed (and their data
184+
stored in the Distribution instance)
185+
commandline
186+
stop after the command-line ('sys.argv[1:]' or 'script_args')
187+
have been parsed (and the data stored in the Distribution)
188+
run [default]
189+
stop after all commands have been run (the same as if 'setup()'
190+
had been called in the usual way
191+
192+
Returns the Distribution instance, which provides all information
193+
used to drive the Distutils.
194+
"""
195+
if stop_after not in ('init', 'config', 'commandline', 'run'):
196+
raise ValueError, "invalid value for 'stop_after': %s" % `stop_after`
197+
198+
global _setup_stop_after, _setup_distribution
199+
_setup_stop_after = stop_after
200+
201+
save_argv = sys.argv
202+
g = {}
203+
l = {}
204+
try:
205+
try:
206+
sys.argv[0] = script_name
207+
if script_args is not None:
208+
sys.argv[1:] = script_args
209+
execfile(script_name, g, l)
210+
finally:
211+
sys.argv = save_argv
212+
_setup_stop_after = None
213+
except SystemExit:
214+
# Hmm, should we do something if exiting with a non-zero code
215+
# (ie. error)?
216+
pass
217+
except:
218+
raise
219+
220+
if _setup_distribution is None:
221+
raise RuntimeError, \
222+
("'distutils.core.setup()' was never called -- "
223+
"perhaps '%s' is not a Distutils setup script?") % \
224+
script_name
225+
226+
# I wonder if the setup script's namespace -- g and l -- would be of
227+
# any interest to callers?
228+
#print "_setup_distribution:", _setup_distribution
229+
return _setup_distribution
230+
231+
# run_setup ()

0 commit comments

Comments
 (0)