cmd.py 18.6 KB
Newer Older
1 2 3
"""distutils.cmd

Provides the Command class, the base class for the command classes
4 5
in the distutils.command package.
"""
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 13

class Command:
    """Abstract base class for defining command classes, the "worker bees"
14 15 16 17 18 19 20 21 22 23 24 25 26
    of the Distutils.  A useful analogy for command classes is to think of
    them as subroutines with local variables called "options".  The options
    are "declared" in 'initialize_options()' and "defined" (given their
    final values, aka "finalized") in 'finalize_options()', both of which
    must be defined by every command class.  The distinction between the
    two is necessary because option values might come from the outside
    world (command line, config file, ...), and any options dependent on
    other options must be computed *after* these outside influences have
    been processed -- hence 'finalize_options()'.  The "body" of the
    subroutine, where it does all its work based on the values of its
    options, is the 'run()' method, which must also be implemented by every
    command class.
    """
27

28 29 30 31 32 33 34 35 36 37
    # 'sub_commands' formalizes the notion of a "family" of commands,
    # eg. "install" as the parent with sub-commands "install_lib",
    # "install_headers", etc.  The parent of a family of commands
    # defines 'sub_commands' as a class attribute; it's a list of
    #    (command_name : string, predicate : unbound_method | string | None)
    # tuples, where 'predicate' is a method of the parent command that
    # determines whether the corresponding command is applicable in the
    # current situation.  (Eg. we "install_headers" is only applicable if
    # we have any C header files to install.)  If 'predicate' is None,
    # that command is always applicable.
Fred Drake's avatar
Fred Drake committed
38
    #
39 40 41 42 43 44
    # 'sub_commands' is usually defined at the *end* of a class, because
    # predicates can be unbound methods, so they must already have been
    # defined.  The canonical example is the "install" command.
    sub_commands = []


45 46
    # -- Creation/initialization methods -------------------------------

47
    def __init__(self, dist):
48
        """Create and initialize a new Command object.  Most importantly,
49 50 51 52
        invokes the 'initialize_options()' method, which is the real
        initializer and depends on the actual command being
        instantiated.
        """
53 54 55
        # late import because of mutual dependence between these classes
        from distutils.dist import Distribution

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 65

        # Per-command versions of the global flags, so that the user can
        # customize Distutils' behaviour command-by-command and let some
Fred Drake's avatar
Fred Drake committed
66
        # commands fall back on the Distribution's behaviour.  None means
67 68
        # "not defined, check self.distribution's copy", while 0 or 1 mean
        # false and true (duh).  Note that this means figuring out the real
69 70 71
        # value of each flag is a touch complicated -- hence "self._dry_run"
        # will be handled by __getattr__, below.
        # XXX This needs to be fixed.
72 73
        self._dry_run = None

74 75 76
        # verbose is largely ignored, but needs to be set for
        # backwards compatibility (I think)?
        self.verbose = dist.verbose
77

78 79 80 81 82 83
        # Some commands define a 'self.force' option to ignore file
        # timestamps, but methods defined *here* assume that
        # 'self.force' exists for all commands.  So define it here
        # just to be safe.
        self.force = None

84 85 86 87
        # The 'help' flag is just used for command-line parsing, so
        # none of that complicated bureaucracy is needed.
        self.help = 0

88
        # 'finalized' records whether or not 'finalize_options()' has been
89
        # called.  'finalize_options()' itself should not pay attention to
90 91 92
        # this flag: it is the business of 'ensure_finalized()', which
        # always calls 'finalize_options()', to respect/update it.
        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 101 102
            else:
                return myval
        else:
103
            raise AttributeError(attr)
104

105
    def ensure_finalized(self):
106
        if not self.finalized:
107
            self.finalize_options()
108
        self.finalized = 1
Fred Drake's avatar
Fred Drake committed
109

110 111
    # Subclasses must define:
    #   initialize_options()
112 113 114
    #     provide default values for all options; may be customized by
    #     setup script, by options from config file(s), or by command-line
    #     options
115 116 117 118 119 120 121 122
    #   finalize_options()
    #     decide on the final values for all options; this is called
    #     after all possible intervention from the outside world
    #     (command-line, option file, etc.) has been processed
    #   run()
    #     run the command: do whatever it is we're here to do,
    #     controlled by the command's various option values

123
    def initialize_options(self):
124
        """Set default values for all the options that this command
125 126 127 128 129
        supports.  Note that these defaults may be overridden by other
        commands, by the setup script, by config files, or by the
        command-line.  Thus, this is not the place to code dependencies
        between options; generally, 'initialize_options()' implementations
        are just a bunch of "self.foo = None" assignments.
Fred Drake's avatar
Fred Drake committed
130

131 132
        This method must be implemented by all command classes.
        """
133 134
        raise RuntimeError("abstract method -- subclass %s must override"
                           % self.__class__)
Fred Drake's avatar
Fred Drake committed
135

136
    def finalize_options(self):
137 138 139
        """Set final values for all the options that this command supports.
        This is always called as late as possible, ie.  after any option
        assignments from the command-line or from other commands have been
140
        done.  Thus, this is the place to code option dependencies: if
141 142 143 144 145 146
        'foo' depends on 'bar', then it is safe to set 'foo' from 'bar' as
        long as 'foo' still has the same value it was assigned in
        'initialize_options()'.

        This method must be implemented by all command classes.
        """
147 148
        raise RuntimeError("abstract method -- subclass %s must override"
                           % self.__class__)
149

150

151
    def dump_options(self, header=None, indent=""):
152 153 154
        from distutils.fancy_getopt import longopt_xlate
        if header is None:
            header = "command options for '%s':" % self.get_command_name()
155
        self.announce(indent + header, level=log.INFO)
156 157
        indent = indent + "  "
        for (option, _, _) in self.user_options:
158
            option = option.translate(longopt_xlate)
159 160 161
            if option[-1] == "=":
                option = option[:-1]
            value = getattr(self, option)
162 163
            self.announce(indent + "%s = %s" % (option, value),
                          level=log.INFO)
164

165
    def run(self):
166 167 168 169 170 171
        """A command's raison d'etre: carry out the action it exists to
        perform, controlled by the options initialized in
        'initialize_options()', customized by other commands, the setup
        script, the command-line, and config files, and finalized in
        'finalize_options()'.  All terminal output and filesystem
        interaction should be done by 'run()'.
172

173 174
        This method must be implemented by all command classes.
        """
175 176
        raise RuntimeError("abstract method -- subclass %s must override"
                           % self.__class__)
177

178
    def announce(self, msg, level=1):
179 180 181
        """If the current verbosity level is of greater than or equal to
        'level' print 'msg' to stdout.
        """
182
        log.log(level, msg)
183

184
    def debug_print(self, msg):
185 186 187
        """Print 'msg' to stdout if the global DEBUG (taken from the
        DISTUTILS_DEBUG environment variable) flag is true.
        """
188
        from distutils.debug import DEBUG
189
        if DEBUG:
190
            print(msg)
191
            sys.stdout.flush()
Fred Drake's avatar
Fred Drake committed
192

193

194 195
    # -- Option validation methods -------------------------------------
    # (these are very handy in writing the 'finalize_options()' method)
Fred Drake's avatar
Fred Drake committed
196
    #
197 198 199 200 201 202 203 204 205 206
    # NB. the general philosophy here is to ensure that a particular option
    # value meets certain type and value constraints.  If not, we try to
    # force it into conformance (eg. if we expect a list but have a string,
    # split the string on comma and/or whitespace).  If we can't force the
    # option into conformance, raise DistutilsOptionError.  Thus, command
    # classes need do nothing more than (eg.)
    #   self.ensure_string_list('foo')
    # and they can be guaranteed that thereafter, self.foo will be
    # a list of strings.

207
    def _ensure_stringlike(self, option, what, default=None):
208 209 210 211
        val = getattr(self, option)
        if val is None:
            setattr(self, option, default)
            return default
212
        elif not isinstance(val, str):
213 214
            raise DistutilsOptionError("'%s' must be a %s (got `%s`)"
                                       % (option, what, val))
215 216
        return val

217
    def ensure_string(self, option, default=None):
218 219 220 221 222
        """Ensure that 'option' is a string; if not defined, set it to
        'default'.
        """
        self._ensure_stringlike(option, "string", default)

223
    def ensure_string_list(self, option):
224 225 226 227 228 229 230 231
        """Ensure that 'option' is a list of strings.  If 'option' is
        currently a string, we split it either on /,\s*/ or /\s+/, so
        "foo bar baz", "foo,bar,baz", and "foo,   bar baz" all become
        ["foo", "bar", "baz"].
        """
        val = getattr(self, option)
        if val is None:
            return
232
        elif isinstance(val, str):
233 234
            setattr(self, option, re.split(r',\s*|\s+', val))
        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 241 242
                raise DistutilsOptionError(
                      "'%s' must be a list of strings (got %r)"
                      % (option, val))
Fred Drake's avatar
Fred Drake committed
243

244 245
    def _ensure_tested_string(self, option, tester, what, error_fmt,
                              default=None):
246 247
        val = self._ensure_stringlike(option, what, default)
        if val is not None and not tester(val):
248 249
            raise DistutilsOptionError(("error in '%s' option: " + error_fmt)
                                       % (option, val))
250

251
    def ensure_filename(self, option):
252 253 254 255 256
        """Ensure that 'option' is the name of an existing file."""
        self._ensure_tested_string(option, os.path.isfile,
                                   "filename",
                                   "'%s' does not exist or is not a file")

257
    def ensure_dirname(self, option):
258 259 260 261 262
        self._ensure_tested_string(option, os.path.isdir,
                                   "directory name",
                                   "'%s' does not exist or is not a directory")


263 264
    # -- Convenience methods for commands ------------------------------

265
    def get_command_name(self):
266
        if hasattr(self, 'command_name'):
267 268 269 270
            return self.command_name
        else:
            return self.__class__.__name__

271
    def set_undefined_options(self, src_cmd, *option_pairs):
272
        """Set the values of any "undefined" options from corresponding
273 274 275 276 277 278 279 280 281 282 283 284
        option values in some other command object.  "Undefined" here means
        "is None", which is the convention used to indicate that an option
        has not been changed between 'initialize_options()' and
        'finalize_options()'.  Usually called from 'finalize_options()' for
        options that depend on some other command rather than another
        option of the same command.  'src_cmd' is the other command from
        which option values will be taken (a command object will be created
        for it if necessary); the remaining arguments are
        '(src_option,dst_option)' tuples which mean "take the value of
        'src_option' in the 'src_cmd' command object, and copy it to
        'dst_option' in the current command object".
        """
285
        # Option_pairs: list of (src_option, dst_option) tuples
286 287
        src_cmd_obj = self.distribution.get_command_obj(src_cmd)
        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 294 295 296 297
        """Wrapper around Distribution's 'get_command_obj()' method: find
        (create if necessary and 'create' is true) the command object for
        'command', call its 'ensure_finalized()' method, and return the
        finalized command object.
        """
298 299
        cmd_obj = self.distribution.get_command_obj(command, create)
        cmd_obj.ensure_finalized()
300 301
        return cmd_obj

302 303
    # XXX rename to 'get_reinitialized_command()'? (should do the
    # same in dist.py, if so)
304 305 306
    def reinitialize_command(self, command, reinit_subcommands=0):
        return self.distribution.reinitialize_command(command,
                                                      reinit_subcommands)
307

308
    def run_command(self, command):
309
        """Run some other command: uses the 'run_command()' method of
310 311 312
        Distribution, which creates and finalizes the command object if
        necessary and then invokes its 'run()' method.
        """
313
        self.distribution.run_command(command)
314

315
    def get_sub_commands(self):
316 317 318 319 320 321 322 323 324 325 326 327 328
        """Determine the sub-commands that are relevant in the current
        distribution (ie., that need to be run).  This is based on the
        'sub_commands' class attribute: each tuple in that list may include
        a method that we call to determine if the subcommand needs to be
        run for the current distribution.  Return a list of command names.
        """
        commands = []
        for (cmd_name, method) in self.sub_commands:
            if method is None or method(self):
                commands.append(cmd_name)
        return commands


329 330
    # -- External world manipulation -----------------------------------

331
    def warn(self, msg):
Benjamin Peterson's avatar
Benjamin Peterson committed
332 333
        log.warn("warning: %s: %s\n" %
                (self.get_command_name(), msg))
334

335
    def execute(self, func, args, msg=None, level=1):
336
        util.execute(func, args, msg, dry_run=self.dry_run)
337

338
    def mkpath(self, name, mode=0o777):
339
        dir_util.mkpath(name, mode, dry_run=self.dry_run)
340

341 342
    def copy_file(self, infile, outfile, preserve_mode=1, preserve_times=1,
                  link=None, level=1):
343 344 345
        """Copy a file respecting verbose, dry-run and force flags.  (The
        former two default to whatever is in the Distribution object, and
        the latter defaults to false for commands that don't define it.)"""
346 347 348
        return file_util.copy_file(infile, outfile, preserve_mode,
                                   preserve_times, not self.force, link,
                                   dry_run=self.dry_run)
349

350
    def copy_tree(self, infile, outfile, preserve_mode=1, preserve_times=1,
351
                   preserve_symlinks=0, level=1):
352
        """Copy an entire directory tree respecting verbose, dry-run,
353 354
        and force flags.
        """
355 356 357
        return dir_util.copy_tree(infile, outfile, preserve_mode,
                                  preserve_times, preserve_symlinks,
                                  not self.force, dry_run=self.dry_run)
358 359

    def move_file (self, src, dst, level=1):
360
        """Move a file respecting dry-run flag."""
361
        return file_util.move_file(src, dst, dry_run=self.dry_run)
362

363
    def spawn(self, cmd, search_path=1, level=1):
364
        """Spawn an external command respecting dry-run flag."""
365
        from distutils.spawn import spawn
366
        spawn(cmd, search_path, dry_run=self.dry_run)
367

368 369 370
    def make_archive(self, base_name, format, root_dir=None, base_dir=None):
        return archive_util.make_archive(base_name, format, root_dir, base_dir,
                                         dry_run=self.dry_run)
371

372 373
    def make_file(self, infiles, outfile, func, args,
                  exec_msg=None, skip_msg=None, level=1):
374
        """Special case of 'execute()' for operations that process one or
375 376 377 378 379
        more input files and generate one output file.  Works just like
        'execute()', except the operation is skipped and a different
        message printed if 'outfile' already exists and is newer than all
        files listed in 'infiles'.  If the command defined 'self.force',
        and it is true, then the command is unconditionally run -- does no
380 381
        timestamp checks.
        """
382 383
        if skip_msg is None:
            skip_msg = "skipping %s (inputs unchanged)" % outfile
Fred Drake's avatar
Fred Drake committed
384

385
        # Allow 'infiles' to be a single string
386
        if isinstance(infiles, str):
387
            infiles = (infiles,)
388
        elif not isinstance(infiles, (list, tuple)):
389 390
            raise TypeError(
                  "'infiles' must be a string, or a list or tuple of strings")
391

392 393 394
        if exec_msg is None:
            exec_msg = "generating %s from %s" % (outfile, ', '.join(infiles))

395 396 397
        # 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
398
        if self.force or dep_util.newer_group(infiles, outfile):
399
            self.execute(func, args, exec_msg, level)
400 401
        # Otherwise, print the "skip" message
        else:
402
            log.debug(skip_msg)
403

404 405 406 407 408
# XXX 'install_misc' class not currently used -- it was the base class for
# both 'install_scripts' and 'install_data', but they outgrew it.  It might
# still be useful for 'install_headers', though, so I'm keeping it around
# for the time being.

409
class install_misc(Command):
410 411 412
    """Common base class for installing some files in a subdirectory.
    Currently used by install_data and install_scripts.
    """
Fred Drake's avatar
Fred Drake committed
413

414 415 416 417
    user_options = [('install-dir=', 'd', "directory to install the files to")]

    def initialize_options (self):
        self.install_dir = None
418
        self.outfiles = []
419

420
    def _install_dir_from(self, dirname):
421 422
        self.set_undefined_options('install', (dirname, 'install_dir'))

423
    def _copy_files(self, filelist):
424 425 426 427 428
        self.outfiles = []
        if not filelist:
            return
        self.mkpath(self.install_dir)
        for f in filelist:
429 430
            self.copy_file(f, self.install_dir)
            self.outfiles.append(os.path.join(self.install_dir, f))
431

432
    def get_outputs(self):
433
        return self.outfiles