diff options
author | Greg Ward <gward@python.net> | 2000-09-01 00:52:45 (GMT) |
---|---|---|
committer | Greg Ward <gward@python.net> | 2000-09-01 00:52:45 (GMT) |
commit | e3644e245ee38bfc145de7e75dac58f57236e694 (patch) | |
tree | e718c6f8f4b868fed6199175528224c629658806 /Lib/distutils/core.py | |
parent | 51de6906be81dda5ff7af6cf65691b76afd42ec7 (diff) | |
download | cpython-e3644e245ee38bfc145de7e75dac58f57236e694.zip cpython-e3644e245ee38bfc145de7e75dac58f57236e694.tar.gz cpython-e3644e245ee38bfc145de7e75dac58f57236e694.tar.bz2 |
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.
Diffstat (limited to 'Lib/distutils/core.py')
-rw-r--r-- | Lib/distutils/core.py | 90 |
1 files changed, 89 insertions, 1 deletions
diff --git a/Lib/distutils/core.py b/Lib/distutils/core.py index 39f1f54..5dfe2db 100644 --- a/Lib/distutils/core.py +++ b/Lib/distutils/core.py @@ -42,6 +42,11 @@ def gen_usage (script_name): return USAGE % vars() +# Some mild magic to control the behaviour of 'setup()' from 'run_setup()'. +_setup_stop_after = None +_setup_distribution = None + + def setup (**attrs): """The gateway to the Distutils: do everything your setup script needs to do, in a highly flexible and user-driven way. Briefly: create a @@ -75,6 +80,8 @@ def setup (**attrs): object. """ + global _setup_stop_after, _setup_distribution + # Determine the distribution class -- either caller-supplied or # our Distribution (see below). klass = attrs.get ('distclass') @@ -91,10 +98,13 @@ def setup (**attrs): # Create the Distribution instance, using the remaining arguments # (ie. everything except distclass) to initialize it try: - dist = klass (attrs) + _setup_distribution = dist = klass (attrs) except DistutilsSetupError, msg: raise SystemExit, "error in setup script: %s" % msg + if _setup_stop_after == "init": + return dist + # Find and parse the config file(s): they will override options from # the setup script, but be overridden by the command line. dist.parse_config_files() @@ -103,6 +113,9 @@ def setup (**attrs): print "options (after parsing config files):" dist.dump_option_dicts() + if _setup_stop_after == "config": + return dist + # Parse the command line; any command-line errors are the end user's # fault, so turn them into SystemExit to suppress tracebacks. try: @@ -116,6 +129,9 @@ def setup (**attrs): print "options (after parsing command line):" dist.dump_option_dicts() + if _setup_stop_after == "commandline": + return dist + # And finally, run all the commands found on the command line. if ok: try: @@ -140,4 +156,76 @@ def setup (**attrs): else: raise SystemExit, "error: " + str(msg) + return dist + # setup () + + +def run_setup (script_name, script_args=None, stop_after="run"): + """Run a setup script in a somewhat controlled environment, and + return the Distribution instance that drives things. This is useful + if you need to find out the distribution meta-data (passed as + keyword args from 'script' to 'setup()', or the contents of the + config files or command-line. + + 'script_name' is a file that will be run with 'execfile()'; + 'sys.argv[0]' will be replaced with 'script' for the duration of the + call. 'script_args' is a list of strings; if supplied, + 'sys.argv[1:]' will be replaced by 'script_args' for the duration of + the call. + + 'stop_after' tells 'setup()' when to stop processing; possible + values: + init + stop after the Distribution instance has been created and + populated with the keyword arguments to 'setup()' + config + stop after config files have been parsed (and their data + stored in the Distribution instance) + commandline + stop after the command-line ('sys.argv[1:]' or 'script_args') + have been parsed (and the data stored in the Distribution) + run [default] + stop after all commands have been run (the same as if 'setup()' + had been called in the usual way + + Returns the Distribution instance, which provides all information + used to drive the Distutils. + """ + if stop_after not in ('init', 'config', 'commandline', 'run'): + raise ValueError, "invalid value for 'stop_after': %s" % `stop_after` + + global _setup_stop_after, _setup_distribution + _setup_stop_after = stop_after + + save_argv = sys.argv + g = {} + l = {} + try: + try: + sys.argv[0] = script_name + if script_args is not None: + sys.argv[1:] = script_args + execfile(script_name, g, l) + finally: + sys.argv = save_argv + _setup_stop_after = None + except SystemExit: + # Hmm, should we do something if exiting with a non-zero code + # (ie. error)? + pass + except: + raise + + if _setup_distribution is None: + raise RuntimeError, \ + ("'distutils.core.setup()' was never called -- " + "perhaps '%s' is not a Distutils setup script?") % \ + script_name + + # I wonder if the setup script's namespace -- g and l -- would be of + # any interest to callers? + #print "_setup_distribution:", _setup_distribution + return _setup_distribution + +# run_setup () |