[Python-checkins] CVS: distutils/distutils core.py,1.44,1.45

Greg Ward python-dev@python.org
Thu, 31 Aug 2000 17:52:48 -0700


Update of /cvsroot/python/distutils/distutils
In directory slayer.i.sourceforge.net:/tmp/cvs-serv12843

Modified Files:
	core.py 
Log Message:
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.


Index: core.py
===================================================================
RCS file: /cvsroot/python/distutils/distutils/core.py,v
retrieving revision 1.44
retrieving revision 1.45
diff -C2 -r1.44 -r1.45
*** core.py	2000/08/29 01:15:18	1.44
--- core.py	2000/09/01 00:52:45	1.45
***************
*** 43,46 ****
--- 43,51 ----
  
  
+ # 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
***************
*** 76,79 ****
--- 81,86 ----
      """
  
+     global _setup_stop_after, _setup_distribution
+ 
      # Determine the distribution class -- either caller-supplied or
      # our Distribution (see below).
***************
*** 92,99 ****
      # (ie. everything except distclass) to initialize it
      try:
!         dist = klass (attrs)
      except DistutilsSetupError, msg:
          raise SystemExit, "error in setup script: %s" % msg
  
      # Find and parse the config file(s): they will override options from
      # the setup script, but be overridden by the command line.
--- 99,109 ----
      # (ie. everything except distclass) to initialize it
      try:
!         _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.
***************
*** 104,107 ****
--- 114,120 ----
          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.
***************
*** 117,120 ****
--- 130,136 ----
          dist.dump_option_dicts()
  
+     if _setup_stop_after == "commandline":
+         return dist
+ 
      # And finally, run all the commands found on the command line.
      if ok:
***************
*** 141,143 ****
--- 157,231 ----
                  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 ()