Home | History | Annotate | Download | only in distutils
      1 """distutils.cmd
      2 
      3 Provides the Command class, the base class for the command classes
      4 in the distutils.command package.
      5 """
      6 
      7 import sys, os, re
      8 from distutils.errors import DistutilsOptionError
      9 from distutils import util, dir_util, file_util, archive_util, dep_util
     10 from distutils import log
     11 
     12 class Command:
     13     """Abstract base class for defining command classes, the "worker bees"
     14     of the Distutils.  A useful analogy for command classes is to think of
     15     them as subroutines with local variables called "options".  The options
     16     are "declared" in 'initialize_options()' and "defined" (given their
     17     final values, aka "finalized") in 'finalize_options()', both of which
     18     must be defined by every command class.  The distinction between the
     19     two is necessary because option values might come from the outside
     20     world (command line, config file, ...), and any options dependent on
     21     other options must be computed *after* these outside influences have
     22     been processed -- hence 'finalize_options()'.  The "body" of the
     23     subroutine, where it does all its work based on the values of its
     24     options, is the 'run()' method, which must also be implemented by every
     25     command class.
     26     """
     27 
     28     # 'sub_commands' formalizes the notion of a "family" of commands,
     29     # eg. "install" as the parent with sub-commands "install_lib",
     30     # "install_headers", etc.  The parent of a family of commands
     31     # defines 'sub_commands' as a class attribute; it's a list of
     32     #    (command_name : string, predicate : unbound_method | string | None)
     33     # tuples, where 'predicate' is a method of the parent command that
     34     # determines whether the corresponding command is applicable in the
     35     # current situation.  (Eg. we "install_headers" is only applicable if
     36     # we have any C header files to install.)  If 'predicate' is None,
     37     # that command is always applicable.
     38     #
     39     # 'sub_commands' is usually defined at the *end* of a class, because
     40     # predicates can be unbound methods, so they must already have been
     41     # defined.  The canonical example is the "install" command.
     42     sub_commands = []
     43 
     44 
     45     # -- Creation/initialization methods -------------------------------
     46 
     47     def __init__(self, dist):
     48         """Create and initialize a new Command object.  Most importantly,
     49         invokes the 'initialize_options()' method, which is the real
     50         initializer and depends on the actual command being
     51         instantiated.
     52         """
     53         # late import because of mutual dependence between these classes
     54         from distutils.dist import Distribution
     55 
     56         if not isinstance(dist, Distribution):
     57             raise TypeError("dist must be a Distribution instance")
     58         if self.__class__ is Command:
     59             raise RuntimeError("Command is an abstract class")
     60 
     61         self.distribution = dist
     62         self.initialize_options()
     63 
     64         # Per-command versions of the global flags, so that the user can
     65         # customize Distutils' behaviour command-by-command and let some
     66         # commands fall back on the Distribution's behaviour.  None means
     67         # "not defined, check self.distribution's copy", while 0 or 1 mean
     68         # false and true (duh).  Note that this means figuring out the real
     69         # value of each flag is a touch complicated -- hence "self._dry_run"
     70         # will be handled by __getattr__, below.
     71         # XXX This needs to be fixed.
     72         self._dry_run = None
     73 
     74         # verbose is largely ignored, but needs to be set for
     75         # backwards compatibility (I think)?
     76         self.verbose = dist.verbose
     77 
     78         # Some commands define a 'self.force' option to ignore file
     79         # timestamps, but methods defined *here* assume that
     80         # 'self.force' exists for all commands.  So define it here
     81         # just to be safe.
     82         self.force = None
     83 
     84         # The 'help' flag is just used for command-line parsing, so
     85         # none of that complicated bureaucracy is needed.
     86         self.help = 0
     87 
     88         # 'finalized' records whether or not 'finalize_options()' has been
     89         # called.  'finalize_options()' itself should not pay attention to
     90         # this flag: it is the business of 'ensure_finalized()', which
     91         # always calls 'finalize_options()', to respect/update it.
     92         self.finalized = 0
     93 
     94     # XXX A more explicit way to customize dry_run would be better.
     95     def __getattr__(self, attr):
     96         if attr == 'dry_run':
     97             myval = getattr(self, "_" + attr)
     98             if myval is None:
     99                 return getattr(self.distribution, attr)
    100             else:
    101                 return myval
    102         else:
    103             raise AttributeError(attr)
    104 
    105     def ensure_finalized(self):
    106         if not self.finalized:
    107             self.finalize_options()
    108         self.finalized = 1
    109 
    110     # Subclasses must define:
    111     #   initialize_options()
    112     #     provide default values for all options; may be customized by
    113     #     setup script, by options from config file(s), or by command-line
    114     #     options
    115     #   finalize_options()
    116     #     decide on the final values for all options; this is called
    117     #     after all possible intervention from the outside world
    118     #     (command-line, option file, etc.) has been processed
    119     #   run()
    120     #     run the command: do whatever it is we're here to do,
    121     #     controlled by the command's various option values
    122 
    123     def initialize_options(self):
    124         """Set default values for all the options that this command
    125         supports.  Note that these defaults may be overridden by other
    126         commands, by the setup script, by config files, or by the
    127         command-line.  Thus, this is not the place to code dependencies
    128         between options; generally, 'initialize_options()' implementations
    129         are just a bunch of "self.foo = None" assignments.
    130 
    131         This method must be implemented by all command classes.
    132         """
    133         raise RuntimeError("abstract method -- subclass %s must override"
    134                            % self.__class__)
    135 
    136     def finalize_options(self):
    137         """Set final values for all the options that this command supports.
    138         This is always called as late as possible, ie.  after any option
    139         assignments from the command-line or from other commands have been
    140         done.  Thus, this is the place to code option dependencies: if
    141         'foo' depends on 'bar', then it is safe to set 'foo' from 'bar' as
    142         long as 'foo' still has the same value it was assigned in
    143         'initialize_options()'.
    144 
    145         This method must be implemented by all command classes.
    146         """
    147         raise RuntimeError("abstract method -- subclass %s must override"
    148                            % self.__class__)
    149 
    150 
    151     def dump_options(self, header=None, indent=""):
    152         from distutils.fancy_getopt import longopt_xlate
    153         if header is None:
    154             header = "command options for '%s':" % self.get_command_name()
    155         self.announce(indent + header, level=log.INFO)
    156         indent = indent + "  "
    157         for (option, _, _) in self.user_options:
    158             option = option.translate(longopt_xlate)
    159             if option[-1] == "=":
    160                 option = option[:-1]
    161             value = getattr(self, option)
    162             self.announce(indent + "%s = %s" % (option, value),
    163                           level=log.INFO)
    164 
    165     def run(self):
    166         """A command's raison d'etre: carry out the action it exists to
    167         perform, controlled by the options initialized in
    168         'initialize_options()', customized by other commands, the setup
    169         script, the command-line, and config files, and finalized in
    170         'finalize_options()'.  All terminal output and filesystem
    171         interaction should be done by 'run()'.
    172 
    173         This method must be implemented by all command classes.
    174         """
    175         raise RuntimeError("abstract method -- subclass %s must override"
    176                            % self.__class__)
    177 
    178     def announce(self, msg, level=1):
    179         """If the current verbosity level is of greater than or equal to
    180         'level' print 'msg' to stdout.
    181         """
    182         log.log(level, msg)
    183 
    184     def debug_print(self, msg):
    185         """Print 'msg' to stdout if the global DEBUG (taken from the
    186         DISTUTILS_DEBUG environment variable) flag is true.
    187         """
    188         from distutils.debug import DEBUG
    189         if DEBUG:
    190             print(msg)
    191             sys.stdout.flush()
    192 
    193 
    194     # -- Option validation methods -------------------------------------
    195     # (these are very handy in writing the 'finalize_options()' method)
    196     #
    197     # NB. the general philosophy here is to ensure that a particular option
    198     # value meets certain type and value constraints.  If not, we try to
    199     # force it into conformance (eg. if we expect a list but have a string,
    200     # split the string on comma and/or whitespace).  If we can't force the
    201     # option into conformance, raise DistutilsOptionError.  Thus, command
    202     # classes need do nothing more than (eg.)
    203     #   self.ensure_string_list('foo')
    204     # and they can be guaranteed that thereafter, self.foo will be
    205     # a list of strings.
    206 
    207     def _ensure_stringlike(self, option, what, default=None):
    208         val = getattr(self, option)
    209         if val is None:
    210             setattr(self, option, default)
    211             return default
    212         elif not isinstance(val, str):
    213             raise DistutilsOptionError("'%s' must be a %s (got `%s`)"
    214                                        % (option, what, val))
    215         return val
    216 
    217     def ensure_string(self, option, default=None):
    218         """Ensure that 'option' is a string; if not defined, set it to
    219         'default'.
    220         """
    221         self._ensure_stringlike(option, "string", default)
    222 
    223     def ensure_string_list(self, option):
    224         r"""Ensure that 'option' is a list of strings.  If 'option' is
    225         currently a string, we split it either on /,\s*/ or /\s+/, so
    226         "foo bar baz", "foo,bar,baz", and "foo,   bar baz" all become
    227         ["foo", "bar", "baz"].
    228         """
    229         val = getattr(self, option)
    230         if val is None:
    231             return
    232         elif isinstance(val, str):
    233             setattr(self, option, re.split(r',\s*|\s+', val))
    234         else:
    235             if isinstance(val, list):
    236                 ok = all(isinstance(v, str) for v in val)
    237             else:
    238                 ok = False
    239             if not ok:
    240                 raise DistutilsOptionError(
    241                       "'%s' must be a list of strings (got %r)"
    242                       % (option, val))
    243 
    244     def _ensure_tested_string(self, option, tester, what, error_fmt,
    245                               default=None):
    246         val = self._ensure_stringlike(option, what, default)
    247         if val is not None and not tester(val):
    248             raise DistutilsOptionError(("error in '%s' option: " + error_fmt)
    249                                        % (option, val))
    250 
    251     def ensure_filename(self, option):
    252         """Ensure that 'option' is the name of an existing file."""
    253         self._ensure_tested_string(option, os.path.isfile,
    254                                    "filename",
    255                                    "'%s' does not exist or is not a file")
    256 
    257     def ensure_dirname(self, option):
    258         self._ensure_tested_string(option, os.path.isdir,
    259                                    "directory name",
    260                                    "'%s' does not exist or is not a directory")
    261 
    262 
    263     # -- Convenience methods for commands ------------------------------
    264 
    265     def get_command_name(self):
    266         if hasattr(self, 'command_name'):
    267             return self.command_name
    268         else:
    269             return self.__class__.__name__
    270 
    271     def set_undefined_options(self, src_cmd, *option_pairs):
    272         """Set the values of any "undefined" options from corresponding
    273         option values in some other command object.  "Undefined" here means
    274         "is None", which is the convention used to indicate that an option
    275         has not been changed between 'initialize_options()' and
    276         'finalize_options()'.  Usually called from 'finalize_options()' for
    277         options that depend on some other command rather than another
    278         option of the same command.  'src_cmd' is the other command from
    279         which option values will be taken (a command object will be created
    280         for it if necessary); the remaining arguments are
    281         '(src_option,dst_option)' tuples which mean "take the value of
    282         'src_option' in the 'src_cmd' command object, and copy it to
    283         'dst_option' in the current command object".
    284         """
    285         # Option_pairs: list of (src_option, dst_option) tuples
    286         src_cmd_obj = self.distribution.get_command_obj(src_cmd)
    287         src_cmd_obj.ensure_finalized()
    288         for (src_option, dst_option) in option_pairs:
    289             if getattr(self, dst_option) is None:
    290                 setattr(self, dst_option, getattr(src_cmd_obj, src_option))
    291 
    292     def get_finalized_command(self, command, create=1):
    293         """Wrapper around Distribution's 'get_command_obj()' method: find
    294         (create if necessary and 'create' is true) the command object for
    295         'command', call its 'ensure_finalized()' method, and return the
    296         finalized command object.
    297         """
    298         cmd_obj = self.distribution.get_command_obj(command, create)
    299         cmd_obj.ensure_finalized()
    300         return cmd_obj
    301 
    302     # XXX rename to 'get_reinitialized_command()'? (should do the
    303     # same in dist.py, if so)
    304     def reinitialize_command(self, command, reinit_subcommands=0):
    305         return self.distribution.reinitialize_command(command,
    306                                                       reinit_subcommands)
    307 
    308     def run_command(self, command):
    309         """Run some other command: uses the 'run_command()' method of
    310         Distribution, which creates and finalizes the command object if
    311         necessary and then invokes its 'run()' method.
    312         """
    313         self.distribution.run_command(command)
    314 
    315     def get_sub_commands(self):
    316         """Determine the sub-commands that are relevant in the current
    317         distribution (ie., that need to be run).  This is based on the
    318         'sub_commands' class attribute: each tuple in that list may include
    319         a method that we call to determine if the subcommand needs to be
    320         run for the current distribution.  Return a list of command names.
    321         """
    322         commands = []
    323         for (cmd_name, method) in self.sub_commands:
    324             if method is None or method(self):
    325                 commands.append(cmd_name)
    326         return commands
    327 
    328 
    329     # -- External world manipulation -----------------------------------
    330 
    331     def warn(self, msg):
    332         log.warn("warning: %s: %s\n", self.get_command_name(), msg)
    333 
    334     def execute(self, func, args, msg=None, level=1):
    335         util.execute(func, args, msg, dry_run=self.dry_run)
    336 
    337     def mkpath(self, name, mode=0o777):
    338         dir_util.mkpath(name, mode, dry_run=self.dry_run)
    339 
    340     def copy_file(self, infile, outfile, preserve_mode=1, preserve_times=1,
    341                   link=None, level=1):
    342         """Copy a file respecting verbose, dry-run and force flags.  (The
    343         former two default to whatever is in the Distribution object, and
    344         the latter defaults to false for commands that don't define it.)"""
    345         return file_util.copy_file(infile, outfile, preserve_mode,
    346                                    preserve_times, not self.force, link,
    347                                    dry_run=self.dry_run)
    348 
    349     def copy_tree(self, infile, outfile, preserve_mode=1, preserve_times=1,
    350                    preserve_symlinks=0, level=1):
    351         """Copy an entire directory tree respecting verbose, dry-run,
    352         and force flags.
    353         """
    354         return dir_util.copy_tree(infile, outfile, preserve_mode,
    355                                   preserve_times, preserve_symlinks,
    356                                   not self.force, dry_run=self.dry_run)
    357 
    358     def move_file (self, src, dst, level=1):
    359         """Move a file respecting dry-run flag."""
    360         return file_util.move_file(src, dst, dry_run=self.dry_run)
    361 
    362     def spawn(self, cmd, search_path=1, level=1):
    363         """Spawn an external command respecting dry-run flag."""
    364         from distutils.spawn import spawn
    365         spawn(cmd, search_path, dry_run=self.dry_run)
    366 
    367     def make_archive(self, base_name, format, root_dir=None, base_dir=None,
    368                      owner=None, group=None):
    369         return archive_util.make_archive(base_name, format, root_dir, base_dir,
    370                                          dry_run=self.dry_run,
    371                                          owner=owner, group=group)
    372 
    373     def make_file(self, infiles, outfile, func, args,
    374                   exec_msg=None, skip_msg=None, level=1):
    375         """Special case of 'execute()' for operations that process one or
    376         more input files and generate one output file.  Works just like
    377         'execute()', except the operation is skipped and a different
    378         message printed if 'outfile' already exists and is newer than all
    379         files listed in 'infiles'.  If the command defined 'self.force',
    380         and it is true, then the command is unconditionally run -- does no
    381         timestamp checks.
    382         """
    383         if skip_msg is None:
    384             skip_msg = "skipping %s (inputs unchanged)" % outfile
    385 
    386         # Allow 'infiles' to be a single string
    387         if isinstance(infiles, str):
    388             infiles = (infiles,)
    389         elif not isinstance(infiles, (list, tuple)):
    390             raise TypeError(
    391                   "'infiles' must be a string, or a list or tuple of strings")
    392 
    393         if exec_msg is None:
    394             exec_msg = "generating %s from %s" % (outfile, ', '.join(infiles))
    395 
    396         # If 'outfile' must be regenerated (either because it doesn't
    397         # exist, is out-of-date, or the 'force' flag is true) then
    398         # perform the action that presumably regenerates it
    399         if self.force or dep_util.newer_group(infiles, outfile):
    400             self.execute(func, args, exec_msg, level)
    401         # Otherwise, print the "skip" message
    402         else:
    403             log.debug(skip_msg)
    404 
    405 # XXX 'install_misc' class not currently used -- it was the base class for
    406 # both 'install_scripts' and 'install_data', but they outgrew it.  It might
    407 # still be useful for 'install_headers', though, so I'm keeping it around
    408 # for the time being.
    409 
    410 class install_misc(Command):
    411     """Common base class for installing some files in a subdirectory.
    412     Currently used by install_data and install_scripts.
    413     """
    414 
    415     user_options = [('install-dir=', 'd', "directory to install the files to")]
    416 
    417     def initialize_options (self):
    418         self.install_dir = None
    419         self.outfiles = []
    420 
    421     def _install_dir_from(self, dirname):
    422         self.set_undefined_options('install', (dirname, 'install_dir'))
    423 
    424     def _copy_files(self, filelist):
    425         self.outfiles = []
    426         if not filelist:
    427             return
    428         self.mkpath(self.install_dir)
    429         for f in filelist:
    430             self.copy_file(f, self.install_dir)
    431             self.outfiles.append(os.path.join(self.install_dir, f))
    432 
    433     def get_outputs(self):
    434         return self.outfiles
    435