summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorGreg Ward <gward@python.net>1999-10-03 21:02:48 (GMT)
committerGreg Ward <gward@python.net>1999-10-03 21:02:48 (GMT)
commit0c35ac62d8e4e40bef4e1687be51bf0fe619c01d (patch)
tree16db010cceda0eaa97f881b18f1b07fc298d1c23 /Lib
parentf3b997a7f0040c6eeade614cc1b1e003d3e31818 (diff)
downloadcpython-0c35ac62d8e4e40bef4e1687be51bf0fe619c01d.zip
cpython-0c35ac62d8e4e40bef4e1687be51bf0fe619c01d.tar.gz
cpython-0c35ac62d8e4e40bef4e1687be51bf0fe619c01d.tar.bz2
Added 'force' and 'quiet' (negative alias for 'verbose') to the
global options table. Every Command instance now has its own copies of the global options, which automatically fallback to the Distribution instance. Changes: - initialize them in constructor - added '__getattr__()' to handle the fallback logic - changed every 'self.distribution.{verbose,dry_run}' in Command to 'self.{verbose,dry_run}'. - filesystem utility methods ('copy_file()' et al) don't take 'update' parameter anymore -- instead we pass 'not force' to the underlying function as 'update' Changed parsing of command line so that global options apply to all commands as well -- that's how (eg.) Command.verbose will be initialized. Simplified 'make_file()' to use 'newer_group()' (from util module). Deleted some cruft. Some docstring tweaks.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/distutils/core.py167
1 files changed, 84 insertions, 83 deletions
diff --git a/Lib/distutils/core.py b/Lib/distutils/core.py
index f0c97aa..c9ccd79 100644
--- a/Lib/distutils/core.py
+++ b/Lib/distutils/core.py
@@ -106,12 +106,21 @@ class Distribution:
those described below."""
- # 'global_options' describes the command-line options that may
- # be supplied to the client (setup.py) prior to any actual
- # commands. Eg. "./setup.py -nv" or "./setup.py --verbose"
- # both take advantage of these global options.
- global_options = [('verbose', 'v', "run verbosely"),
- ('dry-run', 'n', "don't actually do anything"),
+ # 'global_options' describes the command-line options that may be
+ # supplied to the client (setup.py) prior to any actual commands.
+ # Eg. "./setup.py -nv" or "./setup.py --verbose" both take advantage of
+ # these global options. This list should be kept to a bare minimum,
+ # since every global option is also valid as a command option -- and we
+ # don't want to pollute the commands with too many options that they
+ # have minimal control over.
+ global_options = [('verbose', 'v',
+ "run verbosely"),
+ ('quiet=!verbose', 'q',
+ "run quietly (turns verbosity off)"),
+ ('dry-run', 'n',
+ "don't actually do anything"),
+ ('force', 'f',
+ "skip dependency checking between files"),
]
@@ -131,6 +140,7 @@ class Distribution:
# Default values for our command-line options
self.verbose = 0
self.dry_run = 0
+ self.force = 0
# And the "distribution meta-data" options -- these can only
# come from setup.py (the caller), not the command line
@@ -211,23 +221,22 @@ class Distribution:
def parse_command_line (self, args):
- """Parse the client's command line: set any Distribution
+ """Parse the setup script's command line: set any Distribution
attributes tied to command-line options, create all command
objects, and set their options from the command-line. 'args'
must be a list of command-line arguments, most likely
- 'sys.argv[1:]' (see the 'setup()' function). This list is
- first processed for "global options" -- options that set
- attributes of the Distribution instance. Then, it is
- alternately scanned for Distutils command and options for
- that command. Each new command terminates the options for
- the previous command. The allowed options for a command are
- determined by the 'options' attribute of the command object
- -- thus, we instantiate (and cache) every command object
- here, in order to access its 'options' attribute. Any error
- in that 'options' attribute raises DistutilsGetoptError; any
- error on the command-line raises DistutilsArgError. If no
- Distutils commands were found on the command line, raises
- DistutilsArgError."""
+ 'sys.argv[1:]' (see the 'setup()' function). This list is first
+ processed for "global options" -- options that set attributes of
+ the Distribution instance. Then, it is alternately scanned for
+ Distutils command and options for that command. Each new
+ command terminates the options for the previous command. The
+ allowed options for a command are determined by the 'options'
+ attribute of the command object -- thus, we instantiate (and
+ cache) every command object here, in order to access its
+ 'options' attribute. Any error in that 'options' attribute
+ raises DistutilsGetoptError; any error on the command-line
+ raises DistutilsArgError. If no Distutils commands were found
+ on the command line, raises DistutilsArgError."""
# We have to parse the command line a bit at a time -- global
# options, then the first command, then its options, and so on --
@@ -268,7 +277,10 @@ class Distribution:
"(a list of tuples)") % \
cmd_obj.__class__
- args = fancy_getopt (cmd_obj.options, cmd_obj, args[1:])
+ # Poof! like magic, all commands support the global
+ # options too, just by adding in 'global_options'.
+ args = fancy_getopt (self.global_options + cmd_obj.options,
+ cmd_obj, args[1:])
self.command_obj[command] = cmd_obj
self.have_run[command] = 0
@@ -497,6 +509,17 @@ class Command:
self.distribution = dist
self.set_default_options ()
+ # Per-command versions of the global flags, so that the user can
+ # customize Distutils' behaviour command-by-command and let some
+ # commands fallback on the Distribution's behaviour. None means
+ # "not defined, check self.distribution's copy", while 0 or 1 mean
+ # false and true (duh). Note that this means figuring out the real
+ # value of each flag is a touch complicatd -- hence "self.verbose"
+ # (etc.) will be handled by __getattr__, below.
+ self._verbose = None
+ self._dry_run = None
+ self._force = None
+
# 'ready' records whether or not 'set_final_options()' has been
# called. 'set_final_options()' itself should not pay attention to
# this flag: it is the business of 'ensure_ready()', which always
@@ -506,6 +529,17 @@ class Command:
# end __init__ ()
+ def __getattr__ (self, attr):
+ if attr in ('verbose', 'dry_run', 'force'):
+ myval = getattr (self, "_" + attr)
+ if myval is None:
+ return getattr (self.distribution, attr)
+ else:
+ return myval
+ else:
+ raise AttributeError, attr
+
+
def ensure_ready (self):
if not self.ready:
self.set_final_options ()
@@ -569,7 +603,8 @@ class Command:
"""If the Distribution instance to which this command belongs
has a verbosity level of greater than or equal to 'level'
print 'msg' to stdout."""
- if self.distribution.verbose >= level:
+
+ if self.verbose >= level:
print msg
@@ -720,15 +755,13 @@ class Command:
def execute (self, func, args, msg=None, level=1):
"""Perform some action that affects the outside world (eg.
by writing to the filesystem). Such actions are special because
- they should be disabled by the "dry run" flag (carried around by
- the Command's Distribution), and should announce themselves if
- the current verbosity level is high enough. This method takes
- care of all that bureaucracy for you; all you have to do is
- supply the funtion to call and an argument tuple for it (to
- embody the "external action" being performed), a message to
- print if the verbosity level is high enough, and an optional
- verbosity threshold."""
-
+ they should be disabled by the "dry run" flag, and should
+ announce themselves if the current verbosity level is high
+ enough. This method takes care of all that bureaucracy for you;
+ all you have to do is supply the funtion to call and an argument
+ tuple for it (to embody the "external action" being performed),
+ a message to print if the verbosity level is high enough, and an
+ optional verbosity threshold."""
# Generate a message if we weren't passed one
if msg is None:
@@ -740,7 +773,7 @@ class Command:
self.announce (msg, level)
# And do it, as long as we're not in dry-run mode
- if not self.distribution.dry_run:
+ if not self.dry_run:
apply (func, args)
# execute()
@@ -748,43 +781,45 @@ class Command:
def mkpath (self, name, mode=0777):
util.mkpath (name, mode,
- self.distribution.verbose, self.distribution.dry_run)
+ self.verbose, self.dry_run)
def copy_file (self, infile, outfile,
- preserve_mode=1, preserve_times=1, update=1, level=1):
- """Copy a file respecting verbose and dry-run flags."""
+ preserve_mode=1, preserve_times=1, level=1):
+ """Copy a file respecting verbose, dry-run and force flags."""
return util.copy_file (infile, outfile,
preserve_mode, preserve_times,
- update, self.distribution.verbose >= level,
- self.distribution.dry_run)
+ not self.force,
+ self.verbose >= level,
+ self.dry_run)
def copy_tree (self, infile, outfile,
preserve_mode=1, preserve_times=1, preserve_symlinks=0,
- update=1, level=1):
- """Copy an entire directory tree respecting verbose and dry-run
- flags."""
+ level=1):
+ """Copy an entire directory tree respecting verbose, dry-run,
+ and force flags."""
return util.copy_tree (infile, outfile,
preserve_mode,preserve_times,preserve_symlinks,
- update, self.distribution.verbose >= level,
- self.distribution.dry_run)
+ not self.force,
+ self.verbose >= level,
+ self.dry_run)
def move_file (self, src, dst, level=1):
"""Move a file respecting verbose and dry-run flags."""
return util.move_file (src, dst,
- self.distribution.verbose >= level,
- self.distribution.dry_run)
+ self.verbose >= level,
+ self.dry_run)
def spawn (self, cmd, search_path=1, level=1):
from distutils.spawn import spawn
spawn (cmd, search_path,
- self.distribution.verbose >= level,
- self.distribution.dry_run)
+ self.verbose >= level,
+ self.dry_run)
def make_file (self, infiles, outfile, func, args,
@@ -811,29 +846,10 @@ class Command:
raise TypeError, \
"'infiles' must be a string, or a list or tuple of strings"
- # XXX this stuff should probably be moved off to a function
- # in 'distutils.util'
- from stat import *
-
- if os.path.exists (outfile):
- out_mtime = os.stat (outfile)[ST_MTIME]
-
- # Loop over all infiles. If any infile is newer than outfile,
- # then we'll have to regenerate outfile
- for f in infiles:
- in_mtime = os.stat (f)[ST_MTIME]
- if in_mtime > out_mtime:
- runit = 1
- break
- else:
- runit = 0
-
- else:
- runit = 1
-
- # If we determined that 'outfile' must be regenerated, then
+ # If 'outfile' must be regenerated (either because it doesn't
+ # exist, is out-of-date, or the 'force' flag is true) then
# perform the action that presumably regenerates it
- if runit:
+ if self.force or newer_group (infiles, outfile):
self.execute (func, args, exec_msg, level)
# Otherwise, print the "skip" message
@@ -842,19 +858,4 @@ class Command:
# make_file ()
-
-# def make_files (self, infiles, outfiles, func, args,
-# exec_msg=None, skip_msg=None, level=1):
-
-# """Special case of 'execute()' for operations that process one or
-# more input files and generate one or more output files. Works
-# just like 'execute()', except the operation is skipped and a
-# different message printed if all files listed in 'outfiles'
-# already exist and are newer than all files listed in
-# 'infiles'."""
-
-# pass
-
-
-
# end class Command