@@ -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+
4550def 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