xref: /aosp_15_r20/prebuilts/build-tools/common/py3-stdlib/distutils/dist.py (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
1*cda5da8dSAndroid Build Coastguard Worker"""distutils.dist
2*cda5da8dSAndroid Build Coastguard Worker
3*cda5da8dSAndroid Build Coastguard WorkerProvides the Distribution class, which represents the module distribution
4*cda5da8dSAndroid Build Coastguard Workerbeing built/installed/distributed.
5*cda5da8dSAndroid Build Coastguard Worker"""
6*cda5da8dSAndroid Build Coastguard Worker
7*cda5da8dSAndroid Build Coastguard Workerimport sys
8*cda5da8dSAndroid Build Coastguard Workerimport os
9*cda5da8dSAndroid Build Coastguard Workerimport re
10*cda5da8dSAndroid Build Coastguard Workerfrom email import message_from_file
11*cda5da8dSAndroid Build Coastguard Worker
12*cda5da8dSAndroid Build Coastguard Workertry:
13*cda5da8dSAndroid Build Coastguard Worker    import warnings
14*cda5da8dSAndroid Build Coastguard Workerexcept ImportError:
15*cda5da8dSAndroid Build Coastguard Worker    warnings = None
16*cda5da8dSAndroid Build Coastguard Worker
17*cda5da8dSAndroid Build Coastguard Workerfrom distutils.errors import *
18*cda5da8dSAndroid Build Coastguard Workerfrom distutils.fancy_getopt import FancyGetopt, translate_longopt
19*cda5da8dSAndroid Build Coastguard Workerfrom distutils.util import check_environ, strtobool, rfc822_escape
20*cda5da8dSAndroid Build Coastguard Workerfrom distutils import log
21*cda5da8dSAndroid Build Coastguard Workerfrom distutils.debug import DEBUG
22*cda5da8dSAndroid Build Coastguard Worker
23*cda5da8dSAndroid Build Coastguard Worker# Regex to define acceptable Distutils command names.  This is not *quite*
24*cda5da8dSAndroid Build Coastguard Worker# the same as a Python NAME -- I don't allow leading underscores.  The fact
25*cda5da8dSAndroid Build Coastguard Worker# that they're very similar is no coincidence; the default naming scheme is
26*cda5da8dSAndroid Build Coastguard Worker# to look for a Python module named after the command.
27*cda5da8dSAndroid Build Coastguard Workercommand_re = re.compile(r'^[a-zA-Z]([a-zA-Z0-9_]*)$')
28*cda5da8dSAndroid Build Coastguard Worker
29*cda5da8dSAndroid Build Coastguard Worker
30*cda5da8dSAndroid Build Coastguard Workerdef _ensure_list(value, fieldname):
31*cda5da8dSAndroid Build Coastguard Worker    if isinstance(value, str):
32*cda5da8dSAndroid Build Coastguard Worker        # a string containing comma separated values is okay.  It will
33*cda5da8dSAndroid Build Coastguard Worker        # be converted to a list by Distribution.finalize_options().
34*cda5da8dSAndroid Build Coastguard Worker        pass
35*cda5da8dSAndroid Build Coastguard Worker    elif not isinstance(value, list):
36*cda5da8dSAndroid Build Coastguard Worker        # passing a tuple or an iterator perhaps, warn and convert
37*cda5da8dSAndroid Build Coastguard Worker        typename = type(value).__name__
38*cda5da8dSAndroid Build Coastguard Worker        msg = f"Warning: '{fieldname}' should be a list, got type '{typename}'"
39*cda5da8dSAndroid Build Coastguard Worker        log.log(log.WARN, msg)
40*cda5da8dSAndroid Build Coastguard Worker        value = list(value)
41*cda5da8dSAndroid Build Coastguard Worker    return value
42*cda5da8dSAndroid Build Coastguard Worker
43*cda5da8dSAndroid Build Coastguard Worker
44*cda5da8dSAndroid Build Coastguard Workerclass Distribution:
45*cda5da8dSAndroid Build Coastguard Worker    """The core of the Distutils.  Most of the work hiding behind 'setup'
46*cda5da8dSAndroid Build Coastguard Worker    is really done within a Distribution instance, which farms the work out
47*cda5da8dSAndroid Build Coastguard Worker    to the Distutils commands specified on the command line.
48*cda5da8dSAndroid Build Coastguard Worker
49*cda5da8dSAndroid Build Coastguard Worker    Setup scripts will almost never instantiate Distribution directly,
50*cda5da8dSAndroid Build Coastguard Worker    unless the 'setup()' function is totally inadequate to their needs.
51*cda5da8dSAndroid Build Coastguard Worker    However, it is conceivable that a setup script might wish to subclass
52*cda5da8dSAndroid Build Coastguard Worker    Distribution for some specialized purpose, and then pass the subclass
53*cda5da8dSAndroid Build Coastguard Worker    to 'setup()' as the 'distclass' keyword argument.  If so, it is
54*cda5da8dSAndroid Build Coastguard Worker    necessary to respect the expectations that 'setup' has of Distribution.
55*cda5da8dSAndroid Build Coastguard Worker    See the code for 'setup()', in core.py, for details.
56*cda5da8dSAndroid Build Coastguard Worker    """
57*cda5da8dSAndroid Build Coastguard Worker
58*cda5da8dSAndroid Build Coastguard Worker    # 'global_options' describes the command-line options that may be
59*cda5da8dSAndroid Build Coastguard Worker    # supplied to the setup script prior to any actual commands.
60*cda5da8dSAndroid Build Coastguard Worker    # Eg. "./setup.py -n" or "./setup.py --quiet" both take advantage of
61*cda5da8dSAndroid Build Coastguard Worker    # these global options.  This list should be kept to a bare minimum,
62*cda5da8dSAndroid Build Coastguard Worker    # since every global option is also valid as a command option -- and we
63*cda5da8dSAndroid Build Coastguard Worker    # don't want to pollute the commands with too many options that they
64*cda5da8dSAndroid Build Coastguard Worker    # have minimal control over.
65*cda5da8dSAndroid Build Coastguard Worker    # The fourth entry for verbose means that it can be repeated.
66*cda5da8dSAndroid Build Coastguard Worker    global_options = [
67*cda5da8dSAndroid Build Coastguard Worker        ('verbose', 'v', "run verbosely (default)", 1),
68*cda5da8dSAndroid Build Coastguard Worker        ('quiet', 'q', "run quietly (turns verbosity off)"),
69*cda5da8dSAndroid Build Coastguard Worker        ('dry-run', 'n', "don't actually do anything"),
70*cda5da8dSAndroid Build Coastguard Worker        ('help', 'h', "show detailed help message"),
71*cda5da8dSAndroid Build Coastguard Worker        ('no-user-cfg', None,
72*cda5da8dSAndroid Build Coastguard Worker            'ignore pydistutils.cfg in your home directory'),
73*cda5da8dSAndroid Build Coastguard Worker    ]
74*cda5da8dSAndroid Build Coastguard Worker
75*cda5da8dSAndroid Build Coastguard Worker    # 'common_usage' is a short (2-3 line) string describing the common
76*cda5da8dSAndroid Build Coastguard Worker    # usage of the setup script.
77*cda5da8dSAndroid Build Coastguard Worker    common_usage = """\
78*cda5da8dSAndroid Build Coastguard WorkerCommon commands: (see '--help-commands' for more)
79*cda5da8dSAndroid Build Coastguard Worker
80*cda5da8dSAndroid Build Coastguard Worker  setup.py build      will build the package underneath 'build/'
81*cda5da8dSAndroid Build Coastguard Worker  setup.py install    will install the package
82*cda5da8dSAndroid Build Coastguard Worker"""
83*cda5da8dSAndroid Build Coastguard Worker
84*cda5da8dSAndroid Build Coastguard Worker    # options that are not propagated to the commands
85*cda5da8dSAndroid Build Coastguard Worker    display_options = [
86*cda5da8dSAndroid Build Coastguard Worker        ('help-commands', None,
87*cda5da8dSAndroid Build Coastguard Worker         "list all available commands"),
88*cda5da8dSAndroid Build Coastguard Worker        ('name', None,
89*cda5da8dSAndroid Build Coastguard Worker         "print package name"),
90*cda5da8dSAndroid Build Coastguard Worker        ('version', 'V',
91*cda5da8dSAndroid Build Coastguard Worker         "print package version"),
92*cda5da8dSAndroid Build Coastguard Worker        ('fullname', None,
93*cda5da8dSAndroid Build Coastguard Worker         "print <package name>-<version>"),
94*cda5da8dSAndroid Build Coastguard Worker        ('author', None,
95*cda5da8dSAndroid Build Coastguard Worker         "print the author's name"),
96*cda5da8dSAndroid Build Coastguard Worker        ('author-email', None,
97*cda5da8dSAndroid Build Coastguard Worker         "print the author's email address"),
98*cda5da8dSAndroid Build Coastguard Worker        ('maintainer', None,
99*cda5da8dSAndroid Build Coastguard Worker         "print the maintainer's name"),
100*cda5da8dSAndroid Build Coastguard Worker        ('maintainer-email', None,
101*cda5da8dSAndroid Build Coastguard Worker         "print the maintainer's email address"),
102*cda5da8dSAndroid Build Coastguard Worker        ('contact', None,
103*cda5da8dSAndroid Build Coastguard Worker         "print the maintainer's name if known, else the author's"),
104*cda5da8dSAndroid Build Coastguard Worker        ('contact-email', None,
105*cda5da8dSAndroid Build Coastguard Worker         "print the maintainer's email address if known, else the author's"),
106*cda5da8dSAndroid Build Coastguard Worker        ('url', None,
107*cda5da8dSAndroid Build Coastguard Worker         "print the URL for this package"),
108*cda5da8dSAndroid Build Coastguard Worker        ('license', None,
109*cda5da8dSAndroid Build Coastguard Worker         "print the license of the package"),
110*cda5da8dSAndroid Build Coastguard Worker        ('licence', None,
111*cda5da8dSAndroid Build Coastguard Worker         "alias for --license"),
112*cda5da8dSAndroid Build Coastguard Worker        ('description', None,
113*cda5da8dSAndroid Build Coastguard Worker         "print the package description"),
114*cda5da8dSAndroid Build Coastguard Worker        ('long-description', None,
115*cda5da8dSAndroid Build Coastguard Worker         "print the long package description"),
116*cda5da8dSAndroid Build Coastguard Worker        ('platforms', None,
117*cda5da8dSAndroid Build Coastguard Worker         "print the list of platforms"),
118*cda5da8dSAndroid Build Coastguard Worker        ('classifiers', None,
119*cda5da8dSAndroid Build Coastguard Worker         "print the list of classifiers"),
120*cda5da8dSAndroid Build Coastguard Worker        ('keywords', None,
121*cda5da8dSAndroid Build Coastguard Worker         "print the list of keywords"),
122*cda5da8dSAndroid Build Coastguard Worker        ('provides', None,
123*cda5da8dSAndroid Build Coastguard Worker         "print the list of packages/modules provided"),
124*cda5da8dSAndroid Build Coastguard Worker        ('requires', None,
125*cda5da8dSAndroid Build Coastguard Worker         "print the list of packages/modules required"),
126*cda5da8dSAndroid Build Coastguard Worker        ('obsoletes', None,
127*cda5da8dSAndroid Build Coastguard Worker         "print the list of packages/modules made obsolete")
128*cda5da8dSAndroid Build Coastguard Worker        ]
129*cda5da8dSAndroid Build Coastguard Worker    display_option_names = [translate_longopt(x[0]) for x in display_options]
130*cda5da8dSAndroid Build Coastguard Worker
131*cda5da8dSAndroid Build Coastguard Worker    # negative options are options that exclude other options
132*cda5da8dSAndroid Build Coastguard Worker    negative_opt = {'quiet': 'verbose'}
133*cda5da8dSAndroid Build Coastguard Worker
134*cda5da8dSAndroid Build Coastguard Worker    # -- Creation/initialization methods -------------------------------
135*cda5da8dSAndroid Build Coastguard Worker
136*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, attrs=None):
137*cda5da8dSAndroid Build Coastguard Worker        """Construct a new Distribution instance: initialize all the
138*cda5da8dSAndroid Build Coastguard Worker        attributes of a Distribution, and then use 'attrs' (a dictionary
139*cda5da8dSAndroid Build Coastguard Worker        mapping attribute names to values) to assign some of those
140*cda5da8dSAndroid Build Coastguard Worker        attributes their "real" values.  (Any attributes not mentioned in
141*cda5da8dSAndroid Build Coastguard Worker        'attrs' will be assigned to some null value: 0, None, an empty list
142*cda5da8dSAndroid Build Coastguard Worker        or dictionary, etc.)  Most importantly, initialize the
143*cda5da8dSAndroid Build Coastguard Worker        'command_obj' attribute to the empty dictionary; this will be
144*cda5da8dSAndroid Build Coastguard Worker        filled in with real command objects by 'parse_command_line()'.
145*cda5da8dSAndroid Build Coastguard Worker        """
146*cda5da8dSAndroid Build Coastguard Worker
147*cda5da8dSAndroid Build Coastguard Worker        # Default values for our command-line options
148*cda5da8dSAndroid Build Coastguard Worker        self.verbose = 1
149*cda5da8dSAndroid Build Coastguard Worker        self.dry_run = 0
150*cda5da8dSAndroid Build Coastguard Worker        self.help = 0
151*cda5da8dSAndroid Build Coastguard Worker        for attr in self.display_option_names:
152*cda5da8dSAndroid Build Coastguard Worker            setattr(self, attr, 0)
153*cda5da8dSAndroid Build Coastguard Worker
154*cda5da8dSAndroid Build Coastguard Worker        # Store the distribution meta-data (name, version, author, and so
155*cda5da8dSAndroid Build Coastguard Worker        # forth) in a separate object -- we're getting to have enough
156*cda5da8dSAndroid Build Coastguard Worker        # information here (and enough command-line options) that it's
157*cda5da8dSAndroid Build Coastguard Worker        # worth it.  Also delegate 'get_XXX()' methods to the 'metadata'
158*cda5da8dSAndroid Build Coastguard Worker        # object in a sneaky and underhanded (but efficient!) way.
159*cda5da8dSAndroid Build Coastguard Worker        self.metadata = DistributionMetadata()
160*cda5da8dSAndroid Build Coastguard Worker        for basename in self.metadata._METHOD_BASENAMES:
161*cda5da8dSAndroid Build Coastguard Worker            method_name = "get_" + basename
162*cda5da8dSAndroid Build Coastguard Worker            setattr(self, method_name, getattr(self.metadata, method_name))
163*cda5da8dSAndroid Build Coastguard Worker
164*cda5da8dSAndroid Build Coastguard Worker        # 'cmdclass' maps command names to class objects, so we
165*cda5da8dSAndroid Build Coastguard Worker        # can 1) quickly figure out which class to instantiate when
166*cda5da8dSAndroid Build Coastguard Worker        # we need to create a new command object, and 2) have a way
167*cda5da8dSAndroid Build Coastguard Worker        # for the setup script to override command classes
168*cda5da8dSAndroid Build Coastguard Worker        self.cmdclass = {}
169*cda5da8dSAndroid Build Coastguard Worker
170*cda5da8dSAndroid Build Coastguard Worker        # 'command_packages' is a list of packages in which commands
171*cda5da8dSAndroid Build Coastguard Worker        # are searched for.  The factory for command 'foo' is expected
172*cda5da8dSAndroid Build Coastguard Worker        # to be named 'foo' in the module 'foo' in one of the packages
173*cda5da8dSAndroid Build Coastguard Worker        # named here.  This list is searched from the left; an error
174*cda5da8dSAndroid Build Coastguard Worker        # is raised if no named package provides the command being
175*cda5da8dSAndroid Build Coastguard Worker        # searched for.  (Always access using get_command_packages().)
176*cda5da8dSAndroid Build Coastguard Worker        self.command_packages = None
177*cda5da8dSAndroid Build Coastguard Worker
178*cda5da8dSAndroid Build Coastguard Worker        # 'script_name' and 'script_args' are usually set to sys.argv[0]
179*cda5da8dSAndroid Build Coastguard Worker        # and sys.argv[1:], but they can be overridden when the caller is
180*cda5da8dSAndroid Build Coastguard Worker        # not necessarily a setup script run from the command-line.
181*cda5da8dSAndroid Build Coastguard Worker        self.script_name = None
182*cda5da8dSAndroid Build Coastguard Worker        self.script_args = None
183*cda5da8dSAndroid Build Coastguard Worker
184*cda5da8dSAndroid Build Coastguard Worker        # 'command_options' is where we store command options between
185*cda5da8dSAndroid Build Coastguard Worker        # parsing them (from config files, the command-line, etc.) and when
186*cda5da8dSAndroid Build Coastguard Worker        # they are actually needed -- ie. when the command in question is
187*cda5da8dSAndroid Build Coastguard Worker        # instantiated.  It is a dictionary of dictionaries of 2-tuples:
188*cda5da8dSAndroid Build Coastguard Worker        #   command_options = { command_name : { option : (source, value) } }
189*cda5da8dSAndroid Build Coastguard Worker        self.command_options = {}
190*cda5da8dSAndroid Build Coastguard Worker
191*cda5da8dSAndroid Build Coastguard Worker        # 'dist_files' is the list of (command, pyversion, file) that
192*cda5da8dSAndroid Build Coastguard Worker        # have been created by any dist commands run so far. This is
193*cda5da8dSAndroid Build Coastguard Worker        # filled regardless of whether the run is dry or not. pyversion
194*cda5da8dSAndroid Build Coastguard Worker        # gives sysconfig.get_python_version() if the dist file is
195*cda5da8dSAndroid Build Coastguard Worker        # specific to a Python version, 'any' if it is good for all
196*cda5da8dSAndroid Build Coastguard Worker        # Python versions on the target platform, and '' for a source
197*cda5da8dSAndroid Build Coastguard Worker        # file. pyversion should not be used to specify minimum or
198*cda5da8dSAndroid Build Coastguard Worker        # maximum required Python versions; use the metainfo for that
199*cda5da8dSAndroid Build Coastguard Worker        # instead.
200*cda5da8dSAndroid Build Coastguard Worker        self.dist_files = []
201*cda5da8dSAndroid Build Coastguard Worker
202*cda5da8dSAndroid Build Coastguard Worker        # These options are really the business of various commands, rather
203*cda5da8dSAndroid Build Coastguard Worker        # than of the Distribution itself.  We provide aliases for them in
204*cda5da8dSAndroid Build Coastguard Worker        # Distribution as a convenience to the developer.
205*cda5da8dSAndroid Build Coastguard Worker        self.packages = None
206*cda5da8dSAndroid Build Coastguard Worker        self.package_data = {}
207*cda5da8dSAndroid Build Coastguard Worker        self.package_dir = None
208*cda5da8dSAndroid Build Coastguard Worker        self.py_modules = None
209*cda5da8dSAndroid Build Coastguard Worker        self.libraries = None
210*cda5da8dSAndroid Build Coastguard Worker        self.headers = None
211*cda5da8dSAndroid Build Coastguard Worker        self.ext_modules = None
212*cda5da8dSAndroid Build Coastguard Worker        self.ext_package = None
213*cda5da8dSAndroid Build Coastguard Worker        self.include_dirs = None
214*cda5da8dSAndroid Build Coastguard Worker        self.extra_path = None
215*cda5da8dSAndroid Build Coastguard Worker        self.scripts = None
216*cda5da8dSAndroid Build Coastguard Worker        self.data_files = None
217*cda5da8dSAndroid Build Coastguard Worker        self.password = ''
218*cda5da8dSAndroid Build Coastguard Worker
219*cda5da8dSAndroid Build Coastguard Worker        # And now initialize bookkeeping stuff that can't be supplied by
220*cda5da8dSAndroid Build Coastguard Worker        # the caller at all.  'command_obj' maps command names to
221*cda5da8dSAndroid Build Coastguard Worker        # Command instances -- that's how we enforce that every command
222*cda5da8dSAndroid Build Coastguard Worker        # class is a singleton.
223*cda5da8dSAndroid Build Coastguard Worker        self.command_obj = {}
224*cda5da8dSAndroid Build Coastguard Worker
225*cda5da8dSAndroid Build Coastguard Worker        # 'have_run' maps command names to boolean values; it keeps track
226*cda5da8dSAndroid Build Coastguard Worker        # of whether we have actually run a particular command, to make it
227*cda5da8dSAndroid Build Coastguard Worker        # cheap to "run" a command whenever we think we might need to -- if
228*cda5da8dSAndroid Build Coastguard Worker        # it's already been done, no need for expensive filesystem
229*cda5da8dSAndroid Build Coastguard Worker        # operations, we just check the 'have_run' dictionary and carry on.
230*cda5da8dSAndroid Build Coastguard Worker        # It's only safe to query 'have_run' for a command class that has
231*cda5da8dSAndroid Build Coastguard Worker        # been instantiated -- a false value will be inserted when the
232*cda5da8dSAndroid Build Coastguard Worker        # command object is created, and replaced with a true value when
233*cda5da8dSAndroid Build Coastguard Worker        # the command is successfully run.  Thus it's probably best to use
234*cda5da8dSAndroid Build Coastguard Worker        # '.get()' rather than a straight lookup.
235*cda5da8dSAndroid Build Coastguard Worker        self.have_run = {}
236*cda5da8dSAndroid Build Coastguard Worker
237*cda5da8dSAndroid Build Coastguard Worker        # Now we'll use the attrs dictionary (ultimately, keyword args from
238*cda5da8dSAndroid Build Coastguard Worker        # the setup script) to possibly override any or all of these
239*cda5da8dSAndroid Build Coastguard Worker        # distribution options.
240*cda5da8dSAndroid Build Coastguard Worker
241*cda5da8dSAndroid Build Coastguard Worker        if attrs:
242*cda5da8dSAndroid Build Coastguard Worker            # Pull out the set of command options and work on them
243*cda5da8dSAndroid Build Coastguard Worker            # specifically.  Note that this order guarantees that aliased
244*cda5da8dSAndroid Build Coastguard Worker            # command options will override any supplied redundantly
245*cda5da8dSAndroid Build Coastguard Worker            # through the general options dictionary.
246*cda5da8dSAndroid Build Coastguard Worker            options = attrs.get('options')
247*cda5da8dSAndroid Build Coastguard Worker            if options is not None:
248*cda5da8dSAndroid Build Coastguard Worker                del attrs['options']
249*cda5da8dSAndroid Build Coastguard Worker                for (command, cmd_options) in options.items():
250*cda5da8dSAndroid Build Coastguard Worker                    opt_dict = self.get_option_dict(command)
251*cda5da8dSAndroid Build Coastguard Worker                    for (opt, val) in cmd_options.items():
252*cda5da8dSAndroid Build Coastguard Worker                        opt_dict[opt] = ("setup script", val)
253*cda5da8dSAndroid Build Coastguard Worker
254*cda5da8dSAndroid Build Coastguard Worker            if 'licence' in attrs:
255*cda5da8dSAndroid Build Coastguard Worker                attrs['license'] = attrs['licence']
256*cda5da8dSAndroid Build Coastguard Worker                del attrs['licence']
257*cda5da8dSAndroid Build Coastguard Worker                msg = "'licence' distribution option is deprecated; use 'license'"
258*cda5da8dSAndroid Build Coastguard Worker                if warnings is not None:
259*cda5da8dSAndroid Build Coastguard Worker                    warnings.warn(msg)
260*cda5da8dSAndroid Build Coastguard Worker                else:
261*cda5da8dSAndroid Build Coastguard Worker                    sys.stderr.write(msg + "\n")
262*cda5da8dSAndroid Build Coastguard Worker
263*cda5da8dSAndroid Build Coastguard Worker            # Now work on the rest of the attributes.  Any attribute that's
264*cda5da8dSAndroid Build Coastguard Worker            # not already defined is invalid!
265*cda5da8dSAndroid Build Coastguard Worker            for (key, val) in attrs.items():
266*cda5da8dSAndroid Build Coastguard Worker                if hasattr(self.metadata, "set_" + key):
267*cda5da8dSAndroid Build Coastguard Worker                    getattr(self.metadata, "set_" + key)(val)
268*cda5da8dSAndroid Build Coastguard Worker                elif hasattr(self.metadata, key):
269*cda5da8dSAndroid Build Coastguard Worker                    setattr(self.metadata, key, val)
270*cda5da8dSAndroid Build Coastguard Worker                elif hasattr(self, key):
271*cda5da8dSAndroid Build Coastguard Worker                    setattr(self, key, val)
272*cda5da8dSAndroid Build Coastguard Worker                else:
273*cda5da8dSAndroid Build Coastguard Worker                    msg = "Unknown distribution option: %s" % repr(key)
274*cda5da8dSAndroid Build Coastguard Worker                    warnings.warn(msg)
275*cda5da8dSAndroid Build Coastguard Worker
276*cda5da8dSAndroid Build Coastguard Worker        # no-user-cfg is handled before other command line args
277*cda5da8dSAndroid Build Coastguard Worker        # because other args override the config files, and this
278*cda5da8dSAndroid Build Coastguard Worker        # one is needed before we can load the config files.
279*cda5da8dSAndroid Build Coastguard Worker        # If attrs['script_args'] wasn't passed, assume false.
280*cda5da8dSAndroid Build Coastguard Worker        #
281*cda5da8dSAndroid Build Coastguard Worker        # This also make sure we just look at the global options
282*cda5da8dSAndroid Build Coastguard Worker        self.want_user_cfg = True
283*cda5da8dSAndroid Build Coastguard Worker
284*cda5da8dSAndroid Build Coastguard Worker        if self.script_args is not None:
285*cda5da8dSAndroid Build Coastguard Worker            for arg in self.script_args:
286*cda5da8dSAndroid Build Coastguard Worker                if not arg.startswith('-'):
287*cda5da8dSAndroid Build Coastguard Worker                    break
288*cda5da8dSAndroid Build Coastguard Worker                if arg == '--no-user-cfg':
289*cda5da8dSAndroid Build Coastguard Worker                    self.want_user_cfg = False
290*cda5da8dSAndroid Build Coastguard Worker                    break
291*cda5da8dSAndroid Build Coastguard Worker
292*cda5da8dSAndroid Build Coastguard Worker        self.finalize_options()
293*cda5da8dSAndroid Build Coastguard Worker
294*cda5da8dSAndroid Build Coastguard Worker    def get_option_dict(self, command):
295*cda5da8dSAndroid Build Coastguard Worker        """Get the option dictionary for a given command.  If that
296*cda5da8dSAndroid Build Coastguard Worker        command's option dictionary hasn't been created yet, then create it
297*cda5da8dSAndroid Build Coastguard Worker        and return the new dictionary; otherwise, return the existing
298*cda5da8dSAndroid Build Coastguard Worker        option dictionary.
299*cda5da8dSAndroid Build Coastguard Worker        """
300*cda5da8dSAndroid Build Coastguard Worker        dict = self.command_options.get(command)
301*cda5da8dSAndroid Build Coastguard Worker        if dict is None:
302*cda5da8dSAndroid Build Coastguard Worker            dict = self.command_options[command] = {}
303*cda5da8dSAndroid Build Coastguard Worker        return dict
304*cda5da8dSAndroid Build Coastguard Worker
305*cda5da8dSAndroid Build Coastguard Worker    def dump_option_dicts(self, header=None, commands=None, indent=""):
306*cda5da8dSAndroid Build Coastguard Worker        from pprint import pformat
307*cda5da8dSAndroid Build Coastguard Worker
308*cda5da8dSAndroid Build Coastguard Worker        if commands is None:             # dump all command option dicts
309*cda5da8dSAndroid Build Coastguard Worker            commands = sorted(self.command_options.keys())
310*cda5da8dSAndroid Build Coastguard Worker
311*cda5da8dSAndroid Build Coastguard Worker        if header is not None:
312*cda5da8dSAndroid Build Coastguard Worker            self.announce(indent + header)
313*cda5da8dSAndroid Build Coastguard Worker            indent = indent + "  "
314*cda5da8dSAndroid Build Coastguard Worker
315*cda5da8dSAndroid Build Coastguard Worker        if not commands:
316*cda5da8dSAndroid Build Coastguard Worker            self.announce(indent + "no commands known yet")
317*cda5da8dSAndroid Build Coastguard Worker            return
318*cda5da8dSAndroid Build Coastguard Worker
319*cda5da8dSAndroid Build Coastguard Worker        for cmd_name in commands:
320*cda5da8dSAndroid Build Coastguard Worker            opt_dict = self.command_options.get(cmd_name)
321*cda5da8dSAndroid Build Coastguard Worker            if opt_dict is None:
322*cda5da8dSAndroid Build Coastguard Worker                self.announce(indent +
323*cda5da8dSAndroid Build Coastguard Worker                              "no option dict for '%s' command" % cmd_name)
324*cda5da8dSAndroid Build Coastguard Worker            else:
325*cda5da8dSAndroid Build Coastguard Worker                self.announce(indent +
326*cda5da8dSAndroid Build Coastguard Worker                              "option dict for '%s' command:" % cmd_name)
327*cda5da8dSAndroid Build Coastguard Worker                out = pformat(opt_dict)
328*cda5da8dSAndroid Build Coastguard Worker                for line in out.split('\n'):
329*cda5da8dSAndroid Build Coastguard Worker                    self.announce(indent + "  " + line)
330*cda5da8dSAndroid Build Coastguard Worker
331*cda5da8dSAndroid Build Coastguard Worker    # -- Config file finding/parsing methods ---------------------------
332*cda5da8dSAndroid Build Coastguard Worker
333*cda5da8dSAndroid Build Coastguard Worker    def find_config_files(self):
334*cda5da8dSAndroid Build Coastguard Worker        """Find as many configuration files as should be processed for this
335*cda5da8dSAndroid Build Coastguard Worker        platform, and return a list of filenames in the order in which they
336*cda5da8dSAndroid Build Coastguard Worker        should be parsed.  The filenames returned are guaranteed to exist
337*cda5da8dSAndroid Build Coastguard Worker        (modulo nasty race conditions).
338*cda5da8dSAndroid Build Coastguard Worker
339*cda5da8dSAndroid Build Coastguard Worker        There are three possible config files: distutils.cfg in the
340*cda5da8dSAndroid Build Coastguard Worker        Distutils installation directory (ie. where the top-level
341*cda5da8dSAndroid Build Coastguard Worker        Distutils __inst__.py file lives), a file in the user's home
342*cda5da8dSAndroid Build Coastguard Worker        directory named .pydistutils.cfg on Unix and pydistutils.cfg
343*cda5da8dSAndroid Build Coastguard Worker        on Windows/Mac; and setup.cfg in the current directory.
344*cda5da8dSAndroid Build Coastguard Worker
345*cda5da8dSAndroid Build Coastguard Worker        The file in the user's home directory can be disabled with the
346*cda5da8dSAndroid Build Coastguard Worker        --no-user-cfg option.
347*cda5da8dSAndroid Build Coastguard Worker        """
348*cda5da8dSAndroid Build Coastguard Worker        files = []
349*cda5da8dSAndroid Build Coastguard Worker        check_environ()
350*cda5da8dSAndroid Build Coastguard Worker
351*cda5da8dSAndroid Build Coastguard Worker        # Where to look for the system-wide Distutils config file
352*cda5da8dSAndroid Build Coastguard Worker        sys_dir = os.path.dirname(sys.modules['distutils'].__file__)
353*cda5da8dSAndroid Build Coastguard Worker
354*cda5da8dSAndroid Build Coastguard Worker        # Look for the system config file
355*cda5da8dSAndroid Build Coastguard Worker        sys_file = os.path.join(sys_dir, "distutils.cfg")
356*cda5da8dSAndroid Build Coastguard Worker        if os.path.isfile(sys_file):
357*cda5da8dSAndroid Build Coastguard Worker            files.append(sys_file)
358*cda5da8dSAndroid Build Coastguard Worker
359*cda5da8dSAndroid Build Coastguard Worker        # What to call the per-user config file
360*cda5da8dSAndroid Build Coastguard Worker        if os.name == 'posix':
361*cda5da8dSAndroid Build Coastguard Worker            user_filename = ".pydistutils.cfg"
362*cda5da8dSAndroid Build Coastguard Worker        else:
363*cda5da8dSAndroid Build Coastguard Worker            user_filename = "pydistutils.cfg"
364*cda5da8dSAndroid Build Coastguard Worker
365*cda5da8dSAndroid Build Coastguard Worker        # And look for the user config file
366*cda5da8dSAndroid Build Coastguard Worker        if self.want_user_cfg:
367*cda5da8dSAndroid Build Coastguard Worker            user_file = os.path.join(os.path.expanduser('~'), user_filename)
368*cda5da8dSAndroid Build Coastguard Worker            if os.path.isfile(user_file):
369*cda5da8dSAndroid Build Coastguard Worker                files.append(user_file)
370*cda5da8dSAndroid Build Coastguard Worker
371*cda5da8dSAndroid Build Coastguard Worker        # All platforms support local setup.cfg
372*cda5da8dSAndroid Build Coastguard Worker        local_file = "setup.cfg"
373*cda5da8dSAndroid Build Coastguard Worker        if os.path.isfile(local_file):
374*cda5da8dSAndroid Build Coastguard Worker            files.append(local_file)
375*cda5da8dSAndroid Build Coastguard Worker
376*cda5da8dSAndroid Build Coastguard Worker        if DEBUG:
377*cda5da8dSAndroid Build Coastguard Worker            self.announce("using config files: %s" % ', '.join(files))
378*cda5da8dSAndroid Build Coastguard Worker
379*cda5da8dSAndroid Build Coastguard Worker        return files
380*cda5da8dSAndroid Build Coastguard Worker
381*cda5da8dSAndroid Build Coastguard Worker    def parse_config_files(self, filenames=None):
382*cda5da8dSAndroid Build Coastguard Worker        from configparser import ConfigParser
383*cda5da8dSAndroid Build Coastguard Worker
384*cda5da8dSAndroid Build Coastguard Worker        # Ignore install directory options if we have a venv
385*cda5da8dSAndroid Build Coastguard Worker        if sys.prefix != sys.base_prefix:
386*cda5da8dSAndroid Build Coastguard Worker            ignore_options = [
387*cda5da8dSAndroid Build Coastguard Worker                'install-base', 'install-platbase', 'install-lib',
388*cda5da8dSAndroid Build Coastguard Worker                'install-platlib', 'install-purelib', 'install-headers',
389*cda5da8dSAndroid Build Coastguard Worker                'install-scripts', 'install-data', 'prefix', 'exec-prefix',
390*cda5da8dSAndroid Build Coastguard Worker                'home', 'user', 'root']
391*cda5da8dSAndroid Build Coastguard Worker        else:
392*cda5da8dSAndroid Build Coastguard Worker            ignore_options = []
393*cda5da8dSAndroid Build Coastguard Worker
394*cda5da8dSAndroid Build Coastguard Worker        ignore_options = frozenset(ignore_options)
395*cda5da8dSAndroid Build Coastguard Worker
396*cda5da8dSAndroid Build Coastguard Worker        if filenames is None:
397*cda5da8dSAndroid Build Coastguard Worker            filenames = self.find_config_files()
398*cda5da8dSAndroid Build Coastguard Worker
399*cda5da8dSAndroid Build Coastguard Worker        if DEBUG:
400*cda5da8dSAndroid Build Coastguard Worker            self.announce("Distribution.parse_config_files():")
401*cda5da8dSAndroid Build Coastguard Worker
402*cda5da8dSAndroid Build Coastguard Worker        parser = ConfigParser()
403*cda5da8dSAndroid Build Coastguard Worker        for filename in filenames:
404*cda5da8dSAndroid Build Coastguard Worker            if DEBUG:
405*cda5da8dSAndroid Build Coastguard Worker                self.announce("  reading %s" % filename)
406*cda5da8dSAndroid Build Coastguard Worker            parser.read(filename)
407*cda5da8dSAndroid Build Coastguard Worker            for section in parser.sections():
408*cda5da8dSAndroid Build Coastguard Worker                options = parser.options(section)
409*cda5da8dSAndroid Build Coastguard Worker                opt_dict = self.get_option_dict(section)
410*cda5da8dSAndroid Build Coastguard Worker
411*cda5da8dSAndroid Build Coastguard Worker                for opt in options:
412*cda5da8dSAndroid Build Coastguard Worker                    if opt != '__name__' and opt not in ignore_options:
413*cda5da8dSAndroid Build Coastguard Worker                        val = parser.get(section,opt)
414*cda5da8dSAndroid Build Coastguard Worker                        opt = opt.replace('-', '_')
415*cda5da8dSAndroid Build Coastguard Worker                        opt_dict[opt] = (filename, val)
416*cda5da8dSAndroid Build Coastguard Worker
417*cda5da8dSAndroid Build Coastguard Worker            # Make the ConfigParser forget everything (so we retain
418*cda5da8dSAndroid Build Coastguard Worker            # the original filenames that options come from)
419*cda5da8dSAndroid Build Coastguard Worker            parser.__init__()
420*cda5da8dSAndroid Build Coastguard Worker
421*cda5da8dSAndroid Build Coastguard Worker        # If there was a "global" section in the config file, use it
422*cda5da8dSAndroid Build Coastguard Worker        # to set Distribution options.
423*cda5da8dSAndroid Build Coastguard Worker
424*cda5da8dSAndroid Build Coastguard Worker        if 'global' in self.command_options:
425*cda5da8dSAndroid Build Coastguard Worker            for (opt, (src, val)) in self.command_options['global'].items():
426*cda5da8dSAndroid Build Coastguard Worker                alias = self.negative_opt.get(opt)
427*cda5da8dSAndroid Build Coastguard Worker                try:
428*cda5da8dSAndroid Build Coastguard Worker                    if alias:
429*cda5da8dSAndroid Build Coastguard Worker                        setattr(self, alias, not strtobool(val))
430*cda5da8dSAndroid Build Coastguard Worker                    elif opt in ('verbose', 'dry_run'): # ugh!
431*cda5da8dSAndroid Build Coastguard Worker                        setattr(self, opt, strtobool(val))
432*cda5da8dSAndroid Build Coastguard Worker                    else:
433*cda5da8dSAndroid Build Coastguard Worker                        setattr(self, opt, val)
434*cda5da8dSAndroid Build Coastguard Worker                except ValueError as msg:
435*cda5da8dSAndroid Build Coastguard Worker                    raise DistutilsOptionError(msg)
436*cda5da8dSAndroid Build Coastguard Worker
437*cda5da8dSAndroid Build Coastguard Worker    # -- Command-line parsing methods ----------------------------------
438*cda5da8dSAndroid Build Coastguard Worker
439*cda5da8dSAndroid Build Coastguard Worker    def parse_command_line(self):
440*cda5da8dSAndroid Build Coastguard Worker        """Parse the setup script's command line, taken from the
441*cda5da8dSAndroid Build Coastguard Worker        'script_args' instance attribute (which defaults to 'sys.argv[1:]'
442*cda5da8dSAndroid Build Coastguard Worker        -- see 'setup()' in core.py).  This list is first processed for
443*cda5da8dSAndroid Build Coastguard Worker        "global options" -- options that set attributes of the Distribution
444*cda5da8dSAndroid Build Coastguard Worker        instance.  Then, it is alternately scanned for Distutils commands
445*cda5da8dSAndroid Build Coastguard Worker        and options for that command.  Each new command terminates the
446*cda5da8dSAndroid Build Coastguard Worker        options for the previous command.  The allowed options for a
447*cda5da8dSAndroid Build Coastguard Worker        command are determined by the 'user_options' attribute of the
448*cda5da8dSAndroid Build Coastguard Worker        command class -- thus, we have to be able to load command classes
449*cda5da8dSAndroid Build Coastguard Worker        in order to parse the command line.  Any error in that 'options'
450*cda5da8dSAndroid Build Coastguard Worker        attribute raises DistutilsGetoptError; any error on the
451*cda5da8dSAndroid Build Coastguard Worker        command-line raises DistutilsArgError.  If no Distutils commands
452*cda5da8dSAndroid Build Coastguard Worker        were found on the command line, raises DistutilsArgError.  Return
453*cda5da8dSAndroid Build Coastguard Worker        true if command-line was successfully parsed and we should carry
454*cda5da8dSAndroid Build Coastguard Worker        on with executing commands; false if no errors but we shouldn't
455*cda5da8dSAndroid Build Coastguard Worker        execute commands (currently, this only happens if user asks for
456*cda5da8dSAndroid Build Coastguard Worker        help).
457*cda5da8dSAndroid Build Coastguard Worker        """
458*cda5da8dSAndroid Build Coastguard Worker        #
459*cda5da8dSAndroid Build Coastguard Worker        # We now have enough information to show the Macintosh dialog
460*cda5da8dSAndroid Build Coastguard Worker        # that allows the user to interactively specify the "command line".
461*cda5da8dSAndroid Build Coastguard Worker        #
462*cda5da8dSAndroid Build Coastguard Worker        toplevel_options = self._get_toplevel_options()
463*cda5da8dSAndroid Build Coastguard Worker
464*cda5da8dSAndroid Build Coastguard Worker        # We have to parse the command line a bit at a time -- global
465*cda5da8dSAndroid Build Coastguard Worker        # options, then the first command, then its options, and so on --
466*cda5da8dSAndroid Build Coastguard Worker        # because each command will be handled by a different class, and
467*cda5da8dSAndroid Build Coastguard Worker        # the options that are valid for a particular class aren't known
468*cda5da8dSAndroid Build Coastguard Worker        # until we have loaded the command class, which doesn't happen
469*cda5da8dSAndroid Build Coastguard Worker        # until we know what the command is.
470*cda5da8dSAndroid Build Coastguard Worker
471*cda5da8dSAndroid Build Coastguard Worker        self.commands = []
472*cda5da8dSAndroid Build Coastguard Worker        parser = FancyGetopt(toplevel_options + self.display_options)
473*cda5da8dSAndroid Build Coastguard Worker        parser.set_negative_aliases(self.negative_opt)
474*cda5da8dSAndroid Build Coastguard Worker        parser.set_aliases({'licence': 'license'})
475*cda5da8dSAndroid Build Coastguard Worker        args = parser.getopt(args=self.script_args, object=self)
476*cda5da8dSAndroid Build Coastguard Worker        option_order = parser.get_option_order()
477*cda5da8dSAndroid Build Coastguard Worker        log.set_verbosity(self.verbose)
478*cda5da8dSAndroid Build Coastguard Worker
479*cda5da8dSAndroid Build Coastguard Worker        # for display options we return immediately
480*cda5da8dSAndroid Build Coastguard Worker        if self.handle_display_options(option_order):
481*cda5da8dSAndroid Build Coastguard Worker            return
482*cda5da8dSAndroid Build Coastguard Worker        while args:
483*cda5da8dSAndroid Build Coastguard Worker            args = self._parse_command_opts(parser, args)
484*cda5da8dSAndroid Build Coastguard Worker            if args is None:            # user asked for help (and got it)
485*cda5da8dSAndroid Build Coastguard Worker                return
486*cda5da8dSAndroid Build Coastguard Worker
487*cda5da8dSAndroid Build Coastguard Worker        # Handle the cases of --help as a "global" option, ie.
488*cda5da8dSAndroid Build Coastguard Worker        # "setup.py --help" and "setup.py --help command ...".  For the
489*cda5da8dSAndroid Build Coastguard Worker        # former, we show global options (--verbose, --dry-run, etc.)
490*cda5da8dSAndroid Build Coastguard Worker        # and display-only options (--name, --version, etc.); for the
491*cda5da8dSAndroid Build Coastguard Worker        # latter, we omit the display-only options and show help for
492*cda5da8dSAndroid Build Coastguard Worker        # each command listed on the command line.
493*cda5da8dSAndroid Build Coastguard Worker        if self.help:
494*cda5da8dSAndroid Build Coastguard Worker            self._show_help(parser,
495*cda5da8dSAndroid Build Coastguard Worker                            display_options=len(self.commands) == 0,
496*cda5da8dSAndroid Build Coastguard Worker                            commands=self.commands)
497*cda5da8dSAndroid Build Coastguard Worker            return
498*cda5da8dSAndroid Build Coastguard Worker
499*cda5da8dSAndroid Build Coastguard Worker        # Oops, no commands found -- an end-user error
500*cda5da8dSAndroid Build Coastguard Worker        if not self.commands:
501*cda5da8dSAndroid Build Coastguard Worker            raise DistutilsArgError("no commands supplied")
502*cda5da8dSAndroid Build Coastguard Worker
503*cda5da8dSAndroid Build Coastguard Worker        # All is well: return true
504*cda5da8dSAndroid Build Coastguard Worker        return True
505*cda5da8dSAndroid Build Coastguard Worker
506*cda5da8dSAndroid Build Coastguard Worker    def _get_toplevel_options(self):
507*cda5da8dSAndroid Build Coastguard Worker        """Return the non-display options recognized at the top level.
508*cda5da8dSAndroid Build Coastguard Worker
509*cda5da8dSAndroid Build Coastguard Worker        This includes options that are recognized *only* at the top
510*cda5da8dSAndroid Build Coastguard Worker        level as well as options recognized for commands.
511*cda5da8dSAndroid Build Coastguard Worker        """
512*cda5da8dSAndroid Build Coastguard Worker        return self.global_options + [
513*cda5da8dSAndroid Build Coastguard Worker            ("command-packages=", None,
514*cda5da8dSAndroid Build Coastguard Worker             "list of packages that provide distutils commands"),
515*cda5da8dSAndroid Build Coastguard Worker            ]
516*cda5da8dSAndroid Build Coastguard Worker
517*cda5da8dSAndroid Build Coastguard Worker    def _parse_command_opts(self, parser, args):
518*cda5da8dSAndroid Build Coastguard Worker        """Parse the command-line options for a single command.
519*cda5da8dSAndroid Build Coastguard Worker        'parser' must be a FancyGetopt instance; 'args' must be the list
520*cda5da8dSAndroid Build Coastguard Worker        of arguments, starting with the current command (whose options
521*cda5da8dSAndroid Build Coastguard Worker        we are about to parse).  Returns a new version of 'args' with
522*cda5da8dSAndroid Build Coastguard Worker        the next command at the front of the list; will be the empty
523*cda5da8dSAndroid Build Coastguard Worker        list if there are no more commands on the command line.  Returns
524*cda5da8dSAndroid Build Coastguard Worker        None if the user asked for help on this command.
525*cda5da8dSAndroid Build Coastguard Worker        """
526*cda5da8dSAndroid Build Coastguard Worker        # late import because of mutual dependence between these modules
527*cda5da8dSAndroid Build Coastguard Worker        from distutils.cmd import Command
528*cda5da8dSAndroid Build Coastguard Worker
529*cda5da8dSAndroid Build Coastguard Worker        # Pull the current command from the head of the command line
530*cda5da8dSAndroid Build Coastguard Worker        command = args[0]
531*cda5da8dSAndroid Build Coastguard Worker        if not command_re.match(command):
532*cda5da8dSAndroid Build Coastguard Worker            raise SystemExit("invalid command name '%s'" % command)
533*cda5da8dSAndroid Build Coastguard Worker        self.commands.append(command)
534*cda5da8dSAndroid Build Coastguard Worker
535*cda5da8dSAndroid Build Coastguard Worker        # Dig up the command class that implements this command, so we
536*cda5da8dSAndroid Build Coastguard Worker        # 1) know that it's a valid command, and 2) know which options
537*cda5da8dSAndroid Build Coastguard Worker        # it takes.
538*cda5da8dSAndroid Build Coastguard Worker        try:
539*cda5da8dSAndroid Build Coastguard Worker            cmd_class = self.get_command_class(command)
540*cda5da8dSAndroid Build Coastguard Worker        except DistutilsModuleError as msg:
541*cda5da8dSAndroid Build Coastguard Worker            raise DistutilsArgError(msg)
542*cda5da8dSAndroid Build Coastguard Worker
543*cda5da8dSAndroid Build Coastguard Worker        # Require that the command class be derived from Command -- want
544*cda5da8dSAndroid Build Coastguard Worker        # to be sure that the basic "command" interface is implemented.
545*cda5da8dSAndroid Build Coastguard Worker        if not issubclass(cmd_class, Command):
546*cda5da8dSAndroid Build Coastguard Worker            raise DistutilsClassError(
547*cda5da8dSAndroid Build Coastguard Worker                "command class %s must subclass Command" % cmd_class)
548*cda5da8dSAndroid Build Coastguard Worker
549*cda5da8dSAndroid Build Coastguard Worker        # Also make sure that the command object provides a list of its
550*cda5da8dSAndroid Build Coastguard Worker        # known options.
551*cda5da8dSAndroid Build Coastguard Worker        if not (hasattr(cmd_class, 'user_options') and
552*cda5da8dSAndroid Build Coastguard Worker                isinstance(cmd_class.user_options, list)):
553*cda5da8dSAndroid Build Coastguard Worker            msg = ("command class %s must provide "
554*cda5da8dSAndroid Build Coastguard Worker                "'user_options' attribute (a list of tuples)")
555*cda5da8dSAndroid Build Coastguard Worker            raise DistutilsClassError(msg % cmd_class)
556*cda5da8dSAndroid Build Coastguard Worker
557*cda5da8dSAndroid Build Coastguard Worker        # If the command class has a list of negative alias options,
558*cda5da8dSAndroid Build Coastguard Worker        # merge it in with the global negative aliases.
559*cda5da8dSAndroid Build Coastguard Worker        negative_opt = self.negative_opt
560*cda5da8dSAndroid Build Coastguard Worker        if hasattr(cmd_class, 'negative_opt'):
561*cda5da8dSAndroid Build Coastguard Worker            negative_opt = negative_opt.copy()
562*cda5da8dSAndroid Build Coastguard Worker            negative_opt.update(cmd_class.negative_opt)
563*cda5da8dSAndroid Build Coastguard Worker
564*cda5da8dSAndroid Build Coastguard Worker        # Check for help_options in command class.  They have a different
565*cda5da8dSAndroid Build Coastguard Worker        # format (tuple of four) so we need to preprocess them here.
566*cda5da8dSAndroid Build Coastguard Worker        if (hasattr(cmd_class, 'help_options') and
567*cda5da8dSAndroid Build Coastguard Worker                isinstance(cmd_class.help_options, list)):
568*cda5da8dSAndroid Build Coastguard Worker            help_options = fix_help_options(cmd_class.help_options)
569*cda5da8dSAndroid Build Coastguard Worker        else:
570*cda5da8dSAndroid Build Coastguard Worker            help_options = []
571*cda5da8dSAndroid Build Coastguard Worker
572*cda5da8dSAndroid Build Coastguard Worker        # All commands support the global options too, just by adding
573*cda5da8dSAndroid Build Coastguard Worker        # in 'global_options'.
574*cda5da8dSAndroid Build Coastguard Worker        parser.set_option_table(self.global_options +
575*cda5da8dSAndroid Build Coastguard Worker                                cmd_class.user_options +
576*cda5da8dSAndroid Build Coastguard Worker                                help_options)
577*cda5da8dSAndroid Build Coastguard Worker        parser.set_negative_aliases(negative_opt)
578*cda5da8dSAndroid Build Coastguard Worker        (args, opts) = parser.getopt(args[1:])
579*cda5da8dSAndroid Build Coastguard Worker        if hasattr(opts, 'help') and opts.help:
580*cda5da8dSAndroid Build Coastguard Worker            self._show_help(parser, display_options=0, commands=[cmd_class])
581*cda5da8dSAndroid Build Coastguard Worker            return
582*cda5da8dSAndroid Build Coastguard Worker
583*cda5da8dSAndroid Build Coastguard Worker        if (hasattr(cmd_class, 'help_options') and
584*cda5da8dSAndroid Build Coastguard Worker                isinstance(cmd_class.help_options, list)):
585*cda5da8dSAndroid Build Coastguard Worker            help_option_found=0
586*cda5da8dSAndroid Build Coastguard Worker            for (help_option, short, desc, func) in cmd_class.help_options:
587*cda5da8dSAndroid Build Coastguard Worker                if hasattr(opts, parser.get_attr_name(help_option)):
588*cda5da8dSAndroid Build Coastguard Worker                    help_option_found=1
589*cda5da8dSAndroid Build Coastguard Worker                    if callable(func):
590*cda5da8dSAndroid Build Coastguard Worker                        func()
591*cda5da8dSAndroid Build Coastguard Worker                    else:
592*cda5da8dSAndroid Build Coastguard Worker                        raise DistutilsClassError(
593*cda5da8dSAndroid Build Coastguard Worker                            "invalid help function %r for help option '%s': "
594*cda5da8dSAndroid Build Coastguard Worker                            "must be a callable object (function, etc.)"
595*cda5da8dSAndroid Build Coastguard Worker                            % (func, help_option))
596*cda5da8dSAndroid Build Coastguard Worker
597*cda5da8dSAndroid Build Coastguard Worker            if help_option_found:
598*cda5da8dSAndroid Build Coastguard Worker                return
599*cda5da8dSAndroid Build Coastguard Worker
600*cda5da8dSAndroid Build Coastguard Worker        # Put the options from the command-line into their official
601*cda5da8dSAndroid Build Coastguard Worker        # holding pen, the 'command_options' dictionary.
602*cda5da8dSAndroid Build Coastguard Worker        opt_dict = self.get_option_dict(command)
603*cda5da8dSAndroid Build Coastguard Worker        for (name, value) in vars(opts).items():
604*cda5da8dSAndroid Build Coastguard Worker            opt_dict[name] = ("command line", value)
605*cda5da8dSAndroid Build Coastguard Worker
606*cda5da8dSAndroid Build Coastguard Worker        return args
607*cda5da8dSAndroid Build Coastguard Worker
608*cda5da8dSAndroid Build Coastguard Worker    def finalize_options(self):
609*cda5da8dSAndroid Build Coastguard Worker        """Set final values for all the options on the Distribution
610*cda5da8dSAndroid Build Coastguard Worker        instance, analogous to the .finalize_options() method of Command
611*cda5da8dSAndroid Build Coastguard Worker        objects.
612*cda5da8dSAndroid Build Coastguard Worker        """
613*cda5da8dSAndroid Build Coastguard Worker        for attr in ('keywords', 'platforms'):
614*cda5da8dSAndroid Build Coastguard Worker            value = getattr(self.metadata, attr)
615*cda5da8dSAndroid Build Coastguard Worker            if value is None:
616*cda5da8dSAndroid Build Coastguard Worker                continue
617*cda5da8dSAndroid Build Coastguard Worker            if isinstance(value, str):
618*cda5da8dSAndroid Build Coastguard Worker                value = [elm.strip() for elm in value.split(',')]
619*cda5da8dSAndroid Build Coastguard Worker                setattr(self.metadata, attr, value)
620*cda5da8dSAndroid Build Coastguard Worker
621*cda5da8dSAndroid Build Coastguard Worker    def _show_help(self, parser, global_options=1, display_options=1,
622*cda5da8dSAndroid Build Coastguard Worker                   commands=[]):
623*cda5da8dSAndroid Build Coastguard Worker        """Show help for the setup script command-line in the form of
624*cda5da8dSAndroid Build Coastguard Worker        several lists of command-line options.  'parser' should be a
625*cda5da8dSAndroid Build Coastguard Worker        FancyGetopt instance; do not expect it to be returned in the
626*cda5da8dSAndroid Build Coastguard Worker        same state, as its option table will be reset to make it
627*cda5da8dSAndroid Build Coastguard Worker        generate the correct help text.
628*cda5da8dSAndroid Build Coastguard Worker
629*cda5da8dSAndroid Build Coastguard Worker        If 'global_options' is true, lists the global options:
630*cda5da8dSAndroid Build Coastguard Worker        --verbose, --dry-run, etc.  If 'display_options' is true, lists
631*cda5da8dSAndroid Build Coastguard Worker        the "display-only" options: --name, --version, etc.  Finally,
632*cda5da8dSAndroid Build Coastguard Worker        lists per-command help for every command name or command class
633*cda5da8dSAndroid Build Coastguard Worker        in 'commands'.
634*cda5da8dSAndroid Build Coastguard Worker        """
635*cda5da8dSAndroid Build Coastguard Worker        # late import because of mutual dependence between these modules
636*cda5da8dSAndroid Build Coastguard Worker        from distutils.core import gen_usage
637*cda5da8dSAndroid Build Coastguard Worker        from distutils.cmd import Command
638*cda5da8dSAndroid Build Coastguard Worker
639*cda5da8dSAndroid Build Coastguard Worker        if global_options:
640*cda5da8dSAndroid Build Coastguard Worker            if display_options:
641*cda5da8dSAndroid Build Coastguard Worker                options = self._get_toplevel_options()
642*cda5da8dSAndroid Build Coastguard Worker            else:
643*cda5da8dSAndroid Build Coastguard Worker                options = self.global_options
644*cda5da8dSAndroid Build Coastguard Worker            parser.set_option_table(options)
645*cda5da8dSAndroid Build Coastguard Worker            parser.print_help(self.common_usage + "\nGlobal options:")
646*cda5da8dSAndroid Build Coastguard Worker            print('')
647*cda5da8dSAndroid Build Coastguard Worker
648*cda5da8dSAndroid Build Coastguard Worker        if display_options:
649*cda5da8dSAndroid Build Coastguard Worker            parser.set_option_table(self.display_options)
650*cda5da8dSAndroid Build Coastguard Worker            parser.print_help(
651*cda5da8dSAndroid Build Coastguard Worker                "Information display options (just display " +
652*cda5da8dSAndroid Build Coastguard Worker                "information, ignore any commands)")
653*cda5da8dSAndroid Build Coastguard Worker            print('')
654*cda5da8dSAndroid Build Coastguard Worker
655*cda5da8dSAndroid Build Coastguard Worker        for command in self.commands:
656*cda5da8dSAndroid Build Coastguard Worker            if isinstance(command, type) and issubclass(command, Command):
657*cda5da8dSAndroid Build Coastguard Worker                klass = command
658*cda5da8dSAndroid Build Coastguard Worker            else:
659*cda5da8dSAndroid Build Coastguard Worker                klass = self.get_command_class(command)
660*cda5da8dSAndroid Build Coastguard Worker            if (hasattr(klass, 'help_options') and
661*cda5da8dSAndroid Build Coastguard Worker                    isinstance(klass.help_options, list)):
662*cda5da8dSAndroid Build Coastguard Worker                parser.set_option_table(klass.user_options +
663*cda5da8dSAndroid Build Coastguard Worker                                        fix_help_options(klass.help_options))
664*cda5da8dSAndroid Build Coastguard Worker            else:
665*cda5da8dSAndroid Build Coastguard Worker                parser.set_option_table(klass.user_options)
666*cda5da8dSAndroid Build Coastguard Worker            parser.print_help("Options for '%s' command:" % klass.__name__)
667*cda5da8dSAndroid Build Coastguard Worker            print('')
668*cda5da8dSAndroid Build Coastguard Worker
669*cda5da8dSAndroid Build Coastguard Worker        print(gen_usage(self.script_name))
670*cda5da8dSAndroid Build Coastguard Worker
671*cda5da8dSAndroid Build Coastguard Worker    def handle_display_options(self, option_order):
672*cda5da8dSAndroid Build Coastguard Worker        """If there were any non-global "display-only" options
673*cda5da8dSAndroid Build Coastguard Worker        (--help-commands or the metadata display options) on the command
674*cda5da8dSAndroid Build Coastguard Worker        line, display the requested info and return true; else return
675*cda5da8dSAndroid Build Coastguard Worker        false.
676*cda5da8dSAndroid Build Coastguard Worker        """
677*cda5da8dSAndroid Build Coastguard Worker        from distutils.core import gen_usage
678*cda5da8dSAndroid Build Coastguard Worker
679*cda5da8dSAndroid Build Coastguard Worker        # User just wants a list of commands -- we'll print it out and stop
680*cda5da8dSAndroid Build Coastguard Worker        # processing now (ie. if they ran "setup --help-commands foo bar",
681*cda5da8dSAndroid Build Coastguard Worker        # we ignore "foo bar").
682*cda5da8dSAndroid Build Coastguard Worker        if self.help_commands:
683*cda5da8dSAndroid Build Coastguard Worker            self.print_commands()
684*cda5da8dSAndroid Build Coastguard Worker            print('')
685*cda5da8dSAndroid Build Coastguard Worker            print(gen_usage(self.script_name))
686*cda5da8dSAndroid Build Coastguard Worker            return 1
687*cda5da8dSAndroid Build Coastguard Worker
688*cda5da8dSAndroid Build Coastguard Worker        # If user supplied any of the "display metadata" options, then
689*cda5da8dSAndroid Build Coastguard Worker        # display that metadata in the order in which the user supplied the
690*cda5da8dSAndroid Build Coastguard Worker        # metadata options.
691*cda5da8dSAndroid Build Coastguard Worker        any_display_options = 0
692*cda5da8dSAndroid Build Coastguard Worker        is_display_option = {}
693*cda5da8dSAndroid Build Coastguard Worker        for option in self.display_options:
694*cda5da8dSAndroid Build Coastguard Worker            is_display_option[option[0]] = 1
695*cda5da8dSAndroid Build Coastguard Worker
696*cda5da8dSAndroid Build Coastguard Worker        for (opt, val) in option_order:
697*cda5da8dSAndroid Build Coastguard Worker            if val and is_display_option.get(opt):
698*cda5da8dSAndroid Build Coastguard Worker                opt = translate_longopt(opt)
699*cda5da8dSAndroid Build Coastguard Worker                value = getattr(self.metadata, "get_"+opt)()
700*cda5da8dSAndroid Build Coastguard Worker                if opt in ['keywords', 'platforms']:
701*cda5da8dSAndroid Build Coastguard Worker                    print(','.join(value))
702*cda5da8dSAndroid Build Coastguard Worker                elif opt in ('classifiers', 'provides', 'requires',
703*cda5da8dSAndroid Build Coastguard Worker                             'obsoletes'):
704*cda5da8dSAndroid Build Coastguard Worker                    print('\n'.join(value))
705*cda5da8dSAndroid Build Coastguard Worker                else:
706*cda5da8dSAndroid Build Coastguard Worker                    print(value)
707*cda5da8dSAndroid Build Coastguard Worker                any_display_options = 1
708*cda5da8dSAndroid Build Coastguard Worker
709*cda5da8dSAndroid Build Coastguard Worker        return any_display_options
710*cda5da8dSAndroid Build Coastguard Worker
711*cda5da8dSAndroid Build Coastguard Worker    def print_command_list(self, commands, header, max_length):
712*cda5da8dSAndroid Build Coastguard Worker        """Print a subset of the list of all commands -- used by
713*cda5da8dSAndroid Build Coastguard Worker        'print_commands()'.
714*cda5da8dSAndroid Build Coastguard Worker        """
715*cda5da8dSAndroid Build Coastguard Worker        print(header + ":")
716*cda5da8dSAndroid Build Coastguard Worker
717*cda5da8dSAndroid Build Coastguard Worker        for cmd in commands:
718*cda5da8dSAndroid Build Coastguard Worker            klass = self.cmdclass.get(cmd)
719*cda5da8dSAndroid Build Coastguard Worker            if not klass:
720*cda5da8dSAndroid Build Coastguard Worker                klass = self.get_command_class(cmd)
721*cda5da8dSAndroid Build Coastguard Worker            try:
722*cda5da8dSAndroid Build Coastguard Worker                description = klass.description
723*cda5da8dSAndroid Build Coastguard Worker            except AttributeError:
724*cda5da8dSAndroid Build Coastguard Worker                description = "(no description available)"
725*cda5da8dSAndroid Build Coastguard Worker
726*cda5da8dSAndroid Build Coastguard Worker            print("  %-*s  %s" % (max_length, cmd, description))
727*cda5da8dSAndroid Build Coastguard Worker
728*cda5da8dSAndroid Build Coastguard Worker    def print_commands(self):
729*cda5da8dSAndroid Build Coastguard Worker        """Print out a help message listing all available commands with a
730*cda5da8dSAndroid Build Coastguard Worker        description of each.  The list is divided into "standard commands"
731*cda5da8dSAndroid Build Coastguard Worker        (listed in distutils.command.__all__) and "extra commands"
732*cda5da8dSAndroid Build Coastguard Worker        (mentioned in self.cmdclass, but not a standard command).  The
733*cda5da8dSAndroid Build Coastguard Worker        descriptions come from the command class attribute
734*cda5da8dSAndroid Build Coastguard Worker        'description'.
735*cda5da8dSAndroid Build Coastguard Worker        """
736*cda5da8dSAndroid Build Coastguard Worker        import distutils.command
737*cda5da8dSAndroid Build Coastguard Worker        std_commands = distutils.command.__all__
738*cda5da8dSAndroid Build Coastguard Worker        is_std = {}
739*cda5da8dSAndroid Build Coastguard Worker        for cmd in std_commands:
740*cda5da8dSAndroid Build Coastguard Worker            is_std[cmd] = 1
741*cda5da8dSAndroid Build Coastguard Worker
742*cda5da8dSAndroid Build Coastguard Worker        extra_commands = []
743*cda5da8dSAndroid Build Coastguard Worker        for cmd in self.cmdclass.keys():
744*cda5da8dSAndroid Build Coastguard Worker            if not is_std.get(cmd):
745*cda5da8dSAndroid Build Coastguard Worker                extra_commands.append(cmd)
746*cda5da8dSAndroid Build Coastguard Worker
747*cda5da8dSAndroid Build Coastguard Worker        max_length = 0
748*cda5da8dSAndroid Build Coastguard Worker        for cmd in (std_commands + extra_commands):
749*cda5da8dSAndroid Build Coastguard Worker            if len(cmd) > max_length:
750*cda5da8dSAndroid Build Coastguard Worker                max_length = len(cmd)
751*cda5da8dSAndroid Build Coastguard Worker
752*cda5da8dSAndroid Build Coastguard Worker        self.print_command_list(std_commands,
753*cda5da8dSAndroid Build Coastguard Worker                                "Standard commands",
754*cda5da8dSAndroid Build Coastguard Worker                                max_length)
755*cda5da8dSAndroid Build Coastguard Worker        if extra_commands:
756*cda5da8dSAndroid Build Coastguard Worker            print()
757*cda5da8dSAndroid Build Coastguard Worker            self.print_command_list(extra_commands,
758*cda5da8dSAndroid Build Coastguard Worker                                    "Extra commands",
759*cda5da8dSAndroid Build Coastguard Worker                                    max_length)
760*cda5da8dSAndroid Build Coastguard Worker
761*cda5da8dSAndroid Build Coastguard Worker    def get_command_list(self):
762*cda5da8dSAndroid Build Coastguard Worker        """Get a list of (command, description) tuples.
763*cda5da8dSAndroid Build Coastguard Worker        The list is divided into "standard commands" (listed in
764*cda5da8dSAndroid Build Coastguard Worker        distutils.command.__all__) and "extra commands" (mentioned in
765*cda5da8dSAndroid Build Coastguard Worker        self.cmdclass, but not a standard command).  The descriptions come
766*cda5da8dSAndroid Build Coastguard Worker        from the command class attribute 'description'.
767*cda5da8dSAndroid Build Coastguard Worker        """
768*cda5da8dSAndroid Build Coastguard Worker        # Currently this is only used on Mac OS, for the Mac-only GUI
769*cda5da8dSAndroid Build Coastguard Worker        # Distutils interface (by Jack Jansen)
770*cda5da8dSAndroid Build Coastguard Worker        import distutils.command
771*cda5da8dSAndroid Build Coastguard Worker        std_commands = distutils.command.__all__
772*cda5da8dSAndroid Build Coastguard Worker        is_std = {}
773*cda5da8dSAndroid Build Coastguard Worker        for cmd in std_commands:
774*cda5da8dSAndroid Build Coastguard Worker            is_std[cmd] = 1
775*cda5da8dSAndroid Build Coastguard Worker
776*cda5da8dSAndroid Build Coastguard Worker        extra_commands = []
777*cda5da8dSAndroid Build Coastguard Worker        for cmd in self.cmdclass.keys():
778*cda5da8dSAndroid Build Coastguard Worker            if not is_std.get(cmd):
779*cda5da8dSAndroid Build Coastguard Worker                extra_commands.append(cmd)
780*cda5da8dSAndroid Build Coastguard Worker
781*cda5da8dSAndroid Build Coastguard Worker        rv = []
782*cda5da8dSAndroid Build Coastguard Worker        for cmd in (std_commands + extra_commands):
783*cda5da8dSAndroid Build Coastguard Worker            klass = self.cmdclass.get(cmd)
784*cda5da8dSAndroid Build Coastguard Worker            if not klass:
785*cda5da8dSAndroid Build Coastguard Worker                klass = self.get_command_class(cmd)
786*cda5da8dSAndroid Build Coastguard Worker            try:
787*cda5da8dSAndroid Build Coastguard Worker                description = klass.description
788*cda5da8dSAndroid Build Coastguard Worker            except AttributeError:
789*cda5da8dSAndroid Build Coastguard Worker                description = "(no description available)"
790*cda5da8dSAndroid Build Coastguard Worker            rv.append((cmd, description))
791*cda5da8dSAndroid Build Coastguard Worker        return rv
792*cda5da8dSAndroid Build Coastguard Worker
793*cda5da8dSAndroid Build Coastguard Worker    # -- Command class/object methods ----------------------------------
794*cda5da8dSAndroid Build Coastguard Worker
795*cda5da8dSAndroid Build Coastguard Worker    def get_command_packages(self):
796*cda5da8dSAndroid Build Coastguard Worker        """Return a list of packages from which commands are loaded."""
797*cda5da8dSAndroid Build Coastguard Worker        pkgs = self.command_packages
798*cda5da8dSAndroid Build Coastguard Worker        if not isinstance(pkgs, list):
799*cda5da8dSAndroid Build Coastguard Worker            if pkgs is None:
800*cda5da8dSAndroid Build Coastguard Worker                pkgs = ''
801*cda5da8dSAndroid Build Coastguard Worker            pkgs = [pkg.strip() for pkg in pkgs.split(',') if pkg != '']
802*cda5da8dSAndroid Build Coastguard Worker            if "distutils.command" not in pkgs:
803*cda5da8dSAndroid Build Coastguard Worker                pkgs.insert(0, "distutils.command")
804*cda5da8dSAndroid Build Coastguard Worker            self.command_packages = pkgs
805*cda5da8dSAndroid Build Coastguard Worker        return pkgs
806*cda5da8dSAndroid Build Coastguard Worker
807*cda5da8dSAndroid Build Coastguard Worker    def get_command_class(self, command):
808*cda5da8dSAndroid Build Coastguard Worker        """Return the class that implements the Distutils command named by
809*cda5da8dSAndroid Build Coastguard Worker        'command'.  First we check the 'cmdclass' dictionary; if the
810*cda5da8dSAndroid Build Coastguard Worker        command is mentioned there, we fetch the class object from the
811*cda5da8dSAndroid Build Coastguard Worker        dictionary and return it.  Otherwise we load the command module
812*cda5da8dSAndroid Build Coastguard Worker        ("distutils.command." + command) and fetch the command class from
813*cda5da8dSAndroid Build Coastguard Worker        the module.  The loaded class is also stored in 'cmdclass'
814*cda5da8dSAndroid Build Coastguard Worker        to speed future calls to 'get_command_class()'.
815*cda5da8dSAndroid Build Coastguard Worker
816*cda5da8dSAndroid Build Coastguard Worker        Raises DistutilsModuleError if the expected module could not be
817*cda5da8dSAndroid Build Coastguard Worker        found, or if that module does not define the expected class.
818*cda5da8dSAndroid Build Coastguard Worker        """
819*cda5da8dSAndroid Build Coastguard Worker        klass = self.cmdclass.get(command)
820*cda5da8dSAndroid Build Coastguard Worker        if klass:
821*cda5da8dSAndroid Build Coastguard Worker            return klass
822*cda5da8dSAndroid Build Coastguard Worker
823*cda5da8dSAndroid Build Coastguard Worker        for pkgname in self.get_command_packages():
824*cda5da8dSAndroid Build Coastguard Worker            module_name = "%s.%s" % (pkgname, command)
825*cda5da8dSAndroid Build Coastguard Worker            klass_name = command
826*cda5da8dSAndroid Build Coastguard Worker
827*cda5da8dSAndroid Build Coastguard Worker            try:
828*cda5da8dSAndroid Build Coastguard Worker                __import__(module_name)
829*cda5da8dSAndroid Build Coastguard Worker                module = sys.modules[module_name]
830*cda5da8dSAndroid Build Coastguard Worker            except ImportError:
831*cda5da8dSAndroid Build Coastguard Worker                continue
832*cda5da8dSAndroid Build Coastguard Worker
833*cda5da8dSAndroid Build Coastguard Worker            try:
834*cda5da8dSAndroid Build Coastguard Worker                klass = getattr(module, klass_name)
835*cda5da8dSAndroid Build Coastguard Worker            except AttributeError:
836*cda5da8dSAndroid Build Coastguard Worker                raise DistutilsModuleError(
837*cda5da8dSAndroid Build Coastguard Worker                    "invalid command '%s' (no class '%s' in module '%s')"
838*cda5da8dSAndroid Build Coastguard Worker                    % (command, klass_name, module_name))
839*cda5da8dSAndroid Build Coastguard Worker
840*cda5da8dSAndroid Build Coastguard Worker            self.cmdclass[command] = klass
841*cda5da8dSAndroid Build Coastguard Worker            return klass
842*cda5da8dSAndroid Build Coastguard Worker
843*cda5da8dSAndroid Build Coastguard Worker        raise DistutilsModuleError("invalid command '%s'" % command)
844*cda5da8dSAndroid Build Coastguard Worker
845*cda5da8dSAndroid Build Coastguard Worker    def get_command_obj(self, command, create=1):
846*cda5da8dSAndroid Build Coastguard Worker        """Return the command object for 'command'.  Normally this object
847*cda5da8dSAndroid Build Coastguard Worker        is cached on a previous call to 'get_command_obj()'; if no command
848*cda5da8dSAndroid Build Coastguard Worker        object for 'command' is in the cache, then we either create and
849*cda5da8dSAndroid Build Coastguard Worker        return it (if 'create' is true) or return None.
850*cda5da8dSAndroid Build Coastguard Worker        """
851*cda5da8dSAndroid Build Coastguard Worker        cmd_obj = self.command_obj.get(command)
852*cda5da8dSAndroid Build Coastguard Worker        if not cmd_obj and create:
853*cda5da8dSAndroid Build Coastguard Worker            if DEBUG:
854*cda5da8dSAndroid Build Coastguard Worker                self.announce("Distribution.get_command_obj(): "
855*cda5da8dSAndroid Build Coastguard Worker                              "creating '%s' command object" % command)
856*cda5da8dSAndroid Build Coastguard Worker
857*cda5da8dSAndroid Build Coastguard Worker            klass = self.get_command_class(command)
858*cda5da8dSAndroid Build Coastguard Worker            cmd_obj = self.command_obj[command] = klass(self)
859*cda5da8dSAndroid Build Coastguard Worker            self.have_run[command] = 0
860*cda5da8dSAndroid Build Coastguard Worker
861*cda5da8dSAndroid Build Coastguard Worker            # Set any options that were supplied in config files
862*cda5da8dSAndroid Build Coastguard Worker            # or on the command line.  (NB. support for error
863*cda5da8dSAndroid Build Coastguard Worker            # reporting is lame here: any errors aren't reported
864*cda5da8dSAndroid Build Coastguard Worker            # until 'finalize_options()' is called, which means
865*cda5da8dSAndroid Build Coastguard Worker            # we won't report the source of the error.)
866*cda5da8dSAndroid Build Coastguard Worker            options = self.command_options.get(command)
867*cda5da8dSAndroid Build Coastguard Worker            if options:
868*cda5da8dSAndroid Build Coastguard Worker                self._set_command_options(cmd_obj, options)
869*cda5da8dSAndroid Build Coastguard Worker
870*cda5da8dSAndroid Build Coastguard Worker        return cmd_obj
871*cda5da8dSAndroid Build Coastguard Worker
872*cda5da8dSAndroid Build Coastguard Worker    def _set_command_options(self, command_obj, option_dict=None):
873*cda5da8dSAndroid Build Coastguard Worker        """Set the options for 'command_obj' from 'option_dict'.  Basically
874*cda5da8dSAndroid Build Coastguard Worker        this means copying elements of a dictionary ('option_dict') to
875*cda5da8dSAndroid Build Coastguard Worker        attributes of an instance ('command').
876*cda5da8dSAndroid Build Coastguard Worker
877*cda5da8dSAndroid Build Coastguard Worker        'command_obj' must be a Command instance.  If 'option_dict' is not
878*cda5da8dSAndroid Build Coastguard Worker        supplied, uses the standard option dictionary for this command
879*cda5da8dSAndroid Build Coastguard Worker        (from 'self.command_options').
880*cda5da8dSAndroid Build Coastguard Worker        """
881*cda5da8dSAndroid Build Coastguard Worker        command_name = command_obj.get_command_name()
882*cda5da8dSAndroid Build Coastguard Worker        if option_dict is None:
883*cda5da8dSAndroid Build Coastguard Worker            option_dict = self.get_option_dict(command_name)
884*cda5da8dSAndroid Build Coastguard Worker
885*cda5da8dSAndroid Build Coastguard Worker        if DEBUG:
886*cda5da8dSAndroid Build Coastguard Worker            self.announce("  setting options for '%s' command:" % command_name)
887*cda5da8dSAndroid Build Coastguard Worker        for (option, (source, value)) in option_dict.items():
888*cda5da8dSAndroid Build Coastguard Worker            if DEBUG:
889*cda5da8dSAndroid Build Coastguard Worker                self.announce("    %s = %s (from %s)" % (option, value,
890*cda5da8dSAndroid Build Coastguard Worker                                                         source))
891*cda5da8dSAndroid Build Coastguard Worker            try:
892*cda5da8dSAndroid Build Coastguard Worker                bool_opts = [translate_longopt(o)
893*cda5da8dSAndroid Build Coastguard Worker                             for o in command_obj.boolean_options]
894*cda5da8dSAndroid Build Coastguard Worker            except AttributeError:
895*cda5da8dSAndroid Build Coastguard Worker                bool_opts = []
896*cda5da8dSAndroid Build Coastguard Worker            try:
897*cda5da8dSAndroid Build Coastguard Worker                neg_opt = command_obj.negative_opt
898*cda5da8dSAndroid Build Coastguard Worker            except AttributeError:
899*cda5da8dSAndroid Build Coastguard Worker                neg_opt = {}
900*cda5da8dSAndroid Build Coastguard Worker
901*cda5da8dSAndroid Build Coastguard Worker            try:
902*cda5da8dSAndroid Build Coastguard Worker                is_string = isinstance(value, str)
903*cda5da8dSAndroid Build Coastguard Worker                if option in neg_opt and is_string:
904*cda5da8dSAndroid Build Coastguard Worker                    setattr(command_obj, neg_opt[option], not strtobool(value))
905*cda5da8dSAndroid Build Coastguard Worker                elif option in bool_opts and is_string:
906*cda5da8dSAndroid Build Coastguard Worker                    setattr(command_obj, option, strtobool(value))
907*cda5da8dSAndroid Build Coastguard Worker                elif hasattr(command_obj, option):
908*cda5da8dSAndroid Build Coastguard Worker                    setattr(command_obj, option, value)
909*cda5da8dSAndroid Build Coastguard Worker                else:
910*cda5da8dSAndroid Build Coastguard Worker                    raise DistutilsOptionError(
911*cda5da8dSAndroid Build Coastguard Worker                        "error in %s: command '%s' has no such option '%s'"
912*cda5da8dSAndroid Build Coastguard Worker                        % (source, command_name, option))
913*cda5da8dSAndroid Build Coastguard Worker            except ValueError as msg:
914*cda5da8dSAndroid Build Coastguard Worker                raise DistutilsOptionError(msg)
915*cda5da8dSAndroid Build Coastguard Worker
916*cda5da8dSAndroid Build Coastguard Worker    def reinitialize_command(self, command, reinit_subcommands=0):
917*cda5da8dSAndroid Build Coastguard Worker        """Reinitializes a command to the state it was in when first
918*cda5da8dSAndroid Build Coastguard Worker        returned by 'get_command_obj()': ie., initialized but not yet
919*cda5da8dSAndroid Build Coastguard Worker        finalized.  This provides the opportunity to sneak option
920*cda5da8dSAndroid Build Coastguard Worker        values in programmatically, overriding or supplementing
921*cda5da8dSAndroid Build Coastguard Worker        user-supplied values from the config files and command line.
922*cda5da8dSAndroid Build Coastguard Worker        You'll have to re-finalize the command object (by calling
923*cda5da8dSAndroid Build Coastguard Worker        'finalize_options()' or 'ensure_finalized()') before using it for
924*cda5da8dSAndroid Build Coastguard Worker        real.
925*cda5da8dSAndroid Build Coastguard Worker
926*cda5da8dSAndroid Build Coastguard Worker        'command' should be a command name (string) or command object.  If
927*cda5da8dSAndroid Build Coastguard Worker        'reinit_subcommands' is true, also reinitializes the command's
928*cda5da8dSAndroid Build Coastguard Worker        sub-commands, as declared by the 'sub_commands' class attribute (if
929*cda5da8dSAndroid Build Coastguard Worker        it has one).  See the "install" command for an example.  Only
930*cda5da8dSAndroid Build Coastguard Worker        reinitializes the sub-commands that actually matter, ie. those
931*cda5da8dSAndroid Build Coastguard Worker        whose test predicates return true.
932*cda5da8dSAndroid Build Coastguard Worker
933*cda5da8dSAndroid Build Coastguard Worker        Returns the reinitialized command object.
934*cda5da8dSAndroid Build Coastguard Worker        """
935*cda5da8dSAndroid Build Coastguard Worker        from distutils.cmd import Command
936*cda5da8dSAndroid Build Coastguard Worker        if not isinstance(command, Command):
937*cda5da8dSAndroid Build Coastguard Worker            command_name = command
938*cda5da8dSAndroid Build Coastguard Worker            command = self.get_command_obj(command_name)
939*cda5da8dSAndroid Build Coastguard Worker        else:
940*cda5da8dSAndroid Build Coastguard Worker            command_name = command.get_command_name()
941*cda5da8dSAndroid Build Coastguard Worker
942*cda5da8dSAndroid Build Coastguard Worker        if not command.finalized:
943*cda5da8dSAndroid Build Coastguard Worker            return command
944*cda5da8dSAndroid Build Coastguard Worker        command.initialize_options()
945*cda5da8dSAndroid Build Coastguard Worker        command.finalized = 0
946*cda5da8dSAndroid Build Coastguard Worker        self.have_run[command_name] = 0
947*cda5da8dSAndroid Build Coastguard Worker        self._set_command_options(command)
948*cda5da8dSAndroid Build Coastguard Worker
949*cda5da8dSAndroid Build Coastguard Worker        if reinit_subcommands:
950*cda5da8dSAndroid Build Coastguard Worker            for sub in command.get_sub_commands():
951*cda5da8dSAndroid Build Coastguard Worker                self.reinitialize_command(sub, reinit_subcommands)
952*cda5da8dSAndroid Build Coastguard Worker
953*cda5da8dSAndroid Build Coastguard Worker        return command
954*cda5da8dSAndroid Build Coastguard Worker
955*cda5da8dSAndroid Build Coastguard Worker    # -- Methods that operate on the Distribution ----------------------
956*cda5da8dSAndroid Build Coastguard Worker
957*cda5da8dSAndroid Build Coastguard Worker    def announce(self, msg, level=log.INFO):
958*cda5da8dSAndroid Build Coastguard Worker        log.log(level, msg)
959*cda5da8dSAndroid Build Coastguard Worker
960*cda5da8dSAndroid Build Coastguard Worker    def run_commands(self):
961*cda5da8dSAndroid Build Coastguard Worker        """Run each command that was seen on the setup script command line.
962*cda5da8dSAndroid Build Coastguard Worker        Uses the list of commands found and cache of command objects
963*cda5da8dSAndroid Build Coastguard Worker        created by 'get_command_obj()'.
964*cda5da8dSAndroid Build Coastguard Worker        """
965*cda5da8dSAndroid Build Coastguard Worker        for cmd in self.commands:
966*cda5da8dSAndroid Build Coastguard Worker            self.run_command(cmd)
967*cda5da8dSAndroid Build Coastguard Worker
968*cda5da8dSAndroid Build Coastguard Worker    # -- Methods that operate on its Commands --------------------------
969*cda5da8dSAndroid Build Coastguard Worker
970*cda5da8dSAndroid Build Coastguard Worker    def run_command(self, command):
971*cda5da8dSAndroid Build Coastguard Worker        """Do whatever it takes to run a command (including nothing at all,
972*cda5da8dSAndroid Build Coastguard Worker        if the command has already been run).  Specifically: if we have
973*cda5da8dSAndroid Build Coastguard Worker        already created and run the command named by 'command', return
974*cda5da8dSAndroid Build Coastguard Worker        silently without doing anything.  If the command named by 'command'
975*cda5da8dSAndroid Build Coastguard Worker        doesn't even have a command object yet, create one.  Then invoke
976*cda5da8dSAndroid Build Coastguard Worker        'run()' on that command object (or an existing one).
977*cda5da8dSAndroid Build Coastguard Worker        """
978*cda5da8dSAndroid Build Coastguard Worker        # Already been here, done that? then return silently.
979*cda5da8dSAndroid Build Coastguard Worker        if self.have_run.get(command):
980*cda5da8dSAndroid Build Coastguard Worker            return
981*cda5da8dSAndroid Build Coastguard Worker
982*cda5da8dSAndroid Build Coastguard Worker        log.info("running %s", command)
983*cda5da8dSAndroid Build Coastguard Worker        cmd_obj = self.get_command_obj(command)
984*cda5da8dSAndroid Build Coastguard Worker        cmd_obj.ensure_finalized()
985*cda5da8dSAndroid Build Coastguard Worker        cmd_obj.run()
986*cda5da8dSAndroid Build Coastguard Worker        self.have_run[command] = 1
987*cda5da8dSAndroid Build Coastguard Worker
988*cda5da8dSAndroid Build Coastguard Worker    # -- Distribution query methods ------------------------------------
989*cda5da8dSAndroid Build Coastguard Worker
990*cda5da8dSAndroid Build Coastguard Worker    def has_pure_modules(self):
991*cda5da8dSAndroid Build Coastguard Worker        return len(self.packages or self.py_modules or []) > 0
992*cda5da8dSAndroid Build Coastguard Worker
993*cda5da8dSAndroid Build Coastguard Worker    def has_ext_modules(self):
994*cda5da8dSAndroid Build Coastguard Worker        return self.ext_modules and len(self.ext_modules) > 0
995*cda5da8dSAndroid Build Coastguard Worker
996*cda5da8dSAndroid Build Coastguard Worker    def has_c_libraries(self):
997*cda5da8dSAndroid Build Coastguard Worker        return self.libraries and len(self.libraries) > 0
998*cda5da8dSAndroid Build Coastguard Worker
999*cda5da8dSAndroid Build Coastguard Worker    def has_modules(self):
1000*cda5da8dSAndroid Build Coastguard Worker        return self.has_pure_modules() or self.has_ext_modules()
1001*cda5da8dSAndroid Build Coastguard Worker
1002*cda5da8dSAndroid Build Coastguard Worker    def has_headers(self):
1003*cda5da8dSAndroid Build Coastguard Worker        return self.headers and len(self.headers) > 0
1004*cda5da8dSAndroid Build Coastguard Worker
1005*cda5da8dSAndroid Build Coastguard Worker    def has_scripts(self):
1006*cda5da8dSAndroid Build Coastguard Worker        return self.scripts and len(self.scripts) > 0
1007*cda5da8dSAndroid Build Coastguard Worker
1008*cda5da8dSAndroid Build Coastguard Worker    def has_data_files(self):
1009*cda5da8dSAndroid Build Coastguard Worker        return self.data_files and len(self.data_files) > 0
1010*cda5da8dSAndroid Build Coastguard Worker
1011*cda5da8dSAndroid Build Coastguard Worker    def is_pure(self):
1012*cda5da8dSAndroid Build Coastguard Worker        return (self.has_pure_modules() and
1013*cda5da8dSAndroid Build Coastguard Worker                not self.has_ext_modules() and
1014*cda5da8dSAndroid Build Coastguard Worker                not self.has_c_libraries())
1015*cda5da8dSAndroid Build Coastguard Worker
1016*cda5da8dSAndroid Build Coastguard Worker    # -- Metadata query methods ----------------------------------------
1017*cda5da8dSAndroid Build Coastguard Worker
1018*cda5da8dSAndroid Build Coastguard Worker    # If you're looking for 'get_name()', 'get_version()', and so forth,
1019*cda5da8dSAndroid Build Coastguard Worker    # they are defined in a sneaky way: the constructor binds self.get_XXX
1020*cda5da8dSAndroid Build Coastguard Worker    # to self.metadata.get_XXX.  The actual code is in the
1021*cda5da8dSAndroid Build Coastguard Worker    # DistributionMetadata class, below.
1022*cda5da8dSAndroid Build Coastguard Worker
1023*cda5da8dSAndroid Build Coastguard Workerclass DistributionMetadata:
1024*cda5da8dSAndroid Build Coastguard Worker    """Dummy class to hold the distribution meta-data: name, version,
1025*cda5da8dSAndroid Build Coastguard Worker    author, and so forth.
1026*cda5da8dSAndroid Build Coastguard Worker    """
1027*cda5da8dSAndroid Build Coastguard Worker
1028*cda5da8dSAndroid Build Coastguard Worker    _METHOD_BASENAMES = ("name", "version", "author", "author_email",
1029*cda5da8dSAndroid Build Coastguard Worker                         "maintainer", "maintainer_email", "url",
1030*cda5da8dSAndroid Build Coastguard Worker                         "license", "description", "long_description",
1031*cda5da8dSAndroid Build Coastguard Worker                         "keywords", "platforms", "fullname", "contact",
1032*cda5da8dSAndroid Build Coastguard Worker                         "contact_email", "classifiers", "download_url",
1033*cda5da8dSAndroid Build Coastguard Worker                         # PEP 314
1034*cda5da8dSAndroid Build Coastguard Worker                         "provides", "requires", "obsoletes",
1035*cda5da8dSAndroid Build Coastguard Worker                         )
1036*cda5da8dSAndroid Build Coastguard Worker
1037*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, path=None):
1038*cda5da8dSAndroid Build Coastguard Worker        if path is not None:
1039*cda5da8dSAndroid Build Coastguard Worker            self.read_pkg_file(open(path))
1040*cda5da8dSAndroid Build Coastguard Worker        else:
1041*cda5da8dSAndroid Build Coastguard Worker            self.name = None
1042*cda5da8dSAndroid Build Coastguard Worker            self.version = None
1043*cda5da8dSAndroid Build Coastguard Worker            self.author = None
1044*cda5da8dSAndroid Build Coastguard Worker            self.author_email = None
1045*cda5da8dSAndroid Build Coastguard Worker            self.maintainer = None
1046*cda5da8dSAndroid Build Coastguard Worker            self.maintainer_email = None
1047*cda5da8dSAndroid Build Coastguard Worker            self.url = None
1048*cda5da8dSAndroid Build Coastguard Worker            self.license = None
1049*cda5da8dSAndroid Build Coastguard Worker            self.description = None
1050*cda5da8dSAndroid Build Coastguard Worker            self.long_description = None
1051*cda5da8dSAndroid Build Coastguard Worker            self.keywords = None
1052*cda5da8dSAndroid Build Coastguard Worker            self.platforms = None
1053*cda5da8dSAndroid Build Coastguard Worker            self.classifiers = None
1054*cda5da8dSAndroid Build Coastguard Worker            self.download_url = None
1055*cda5da8dSAndroid Build Coastguard Worker            # PEP 314
1056*cda5da8dSAndroid Build Coastguard Worker            self.provides = None
1057*cda5da8dSAndroid Build Coastguard Worker            self.requires = None
1058*cda5da8dSAndroid Build Coastguard Worker            self.obsoletes = None
1059*cda5da8dSAndroid Build Coastguard Worker
1060*cda5da8dSAndroid Build Coastguard Worker    def read_pkg_file(self, file):
1061*cda5da8dSAndroid Build Coastguard Worker        """Reads the metadata values from a file object."""
1062*cda5da8dSAndroid Build Coastguard Worker        msg = message_from_file(file)
1063*cda5da8dSAndroid Build Coastguard Worker
1064*cda5da8dSAndroid Build Coastguard Worker        def _read_field(name):
1065*cda5da8dSAndroid Build Coastguard Worker            value = msg[name]
1066*cda5da8dSAndroid Build Coastguard Worker            if value == 'UNKNOWN':
1067*cda5da8dSAndroid Build Coastguard Worker                return None
1068*cda5da8dSAndroid Build Coastguard Worker            return value
1069*cda5da8dSAndroid Build Coastguard Worker
1070*cda5da8dSAndroid Build Coastguard Worker        def _read_list(name):
1071*cda5da8dSAndroid Build Coastguard Worker            values = msg.get_all(name, None)
1072*cda5da8dSAndroid Build Coastguard Worker            if values == []:
1073*cda5da8dSAndroid Build Coastguard Worker                return None
1074*cda5da8dSAndroid Build Coastguard Worker            return values
1075*cda5da8dSAndroid Build Coastguard Worker
1076*cda5da8dSAndroid Build Coastguard Worker        metadata_version = msg['metadata-version']
1077*cda5da8dSAndroid Build Coastguard Worker        self.name = _read_field('name')
1078*cda5da8dSAndroid Build Coastguard Worker        self.version = _read_field('version')
1079*cda5da8dSAndroid Build Coastguard Worker        self.description = _read_field('summary')
1080*cda5da8dSAndroid Build Coastguard Worker        # we are filling author only.
1081*cda5da8dSAndroid Build Coastguard Worker        self.author = _read_field('author')
1082*cda5da8dSAndroid Build Coastguard Worker        self.maintainer = None
1083*cda5da8dSAndroid Build Coastguard Worker        self.author_email = _read_field('author-email')
1084*cda5da8dSAndroid Build Coastguard Worker        self.maintainer_email = None
1085*cda5da8dSAndroid Build Coastguard Worker        self.url = _read_field('home-page')
1086*cda5da8dSAndroid Build Coastguard Worker        self.license = _read_field('license')
1087*cda5da8dSAndroid Build Coastguard Worker
1088*cda5da8dSAndroid Build Coastguard Worker        if 'download-url' in msg:
1089*cda5da8dSAndroid Build Coastguard Worker            self.download_url = _read_field('download-url')
1090*cda5da8dSAndroid Build Coastguard Worker        else:
1091*cda5da8dSAndroid Build Coastguard Worker            self.download_url = None
1092*cda5da8dSAndroid Build Coastguard Worker
1093*cda5da8dSAndroid Build Coastguard Worker        self.long_description = _read_field('description')
1094*cda5da8dSAndroid Build Coastguard Worker        self.description = _read_field('summary')
1095*cda5da8dSAndroid Build Coastguard Worker
1096*cda5da8dSAndroid Build Coastguard Worker        if 'keywords' in msg:
1097*cda5da8dSAndroid Build Coastguard Worker            self.keywords = _read_field('keywords').split(',')
1098*cda5da8dSAndroid Build Coastguard Worker
1099*cda5da8dSAndroid Build Coastguard Worker        self.platforms = _read_list('platform')
1100*cda5da8dSAndroid Build Coastguard Worker        self.classifiers = _read_list('classifier')
1101*cda5da8dSAndroid Build Coastguard Worker
1102*cda5da8dSAndroid Build Coastguard Worker        # PEP 314 - these fields only exist in 1.1
1103*cda5da8dSAndroid Build Coastguard Worker        if metadata_version == '1.1':
1104*cda5da8dSAndroid Build Coastguard Worker            self.requires = _read_list('requires')
1105*cda5da8dSAndroid Build Coastguard Worker            self.provides = _read_list('provides')
1106*cda5da8dSAndroid Build Coastguard Worker            self.obsoletes = _read_list('obsoletes')
1107*cda5da8dSAndroid Build Coastguard Worker        else:
1108*cda5da8dSAndroid Build Coastguard Worker            self.requires = None
1109*cda5da8dSAndroid Build Coastguard Worker            self.provides = None
1110*cda5da8dSAndroid Build Coastguard Worker            self.obsoletes = None
1111*cda5da8dSAndroid Build Coastguard Worker
1112*cda5da8dSAndroid Build Coastguard Worker    def write_pkg_info(self, base_dir):
1113*cda5da8dSAndroid Build Coastguard Worker        """Write the PKG-INFO file into the release tree.
1114*cda5da8dSAndroid Build Coastguard Worker        """
1115*cda5da8dSAndroid Build Coastguard Worker        with open(os.path.join(base_dir, 'PKG-INFO'), 'w',
1116*cda5da8dSAndroid Build Coastguard Worker                  encoding='UTF-8') as pkg_info:
1117*cda5da8dSAndroid Build Coastguard Worker            self.write_pkg_file(pkg_info)
1118*cda5da8dSAndroid Build Coastguard Worker
1119*cda5da8dSAndroid Build Coastguard Worker    def write_pkg_file(self, file):
1120*cda5da8dSAndroid Build Coastguard Worker        """Write the PKG-INFO format data to a file object.
1121*cda5da8dSAndroid Build Coastguard Worker        """
1122*cda5da8dSAndroid Build Coastguard Worker        version = '1.0'
1123*cda5da8dSAndroid Build Coastguard Worker        if (self.provides or self.requires or self.obsoletes or
1124*cda5da8dSAndroid Build Coastguard Worker                self.classifiers or self.download_url):
1125*cda5da8dSAndroid Build Coastguard Worker            version = '1.1'
1126*cda5da8dSAndroid Build Coastguard Worker
1127*cda5da8dSAndroid Build Coastguard Worker        file.write('Metadata-Version: %s\n' % version)
1128*cda5da8dSAndroid Build Coastguard Worker        file.write('Name: %s\n' % self.get_name())
1129*cda5da8dSAndroid Build Coastguard Worker        file.write('Version: %s\n' % self.get_version())
1130*cda5da8dSAndroid Build Coastguard Worker        file.write('Summary: %s\n' % self.get_description())
1131*cda5da8dSAndroid Build Coastguard Worker        file.write('Home-page: %s\n' % self.get_url())
1132*cda5da8dSAndroid Build Coastguard Worker        file.write('Author: %s\n' % self.get_contact())
1133*cda5da8dSAndroid Build Coastguard Worker        file.write('Author-email: %s\n' % self.get_contact_email())
1134*cda5da8dSAndroid Build Coastguard Worker        file.write('License: %s\n' % self.get_license())
1135*cda5da8dSAndroid Build Coastguard Worker        if self.download_url:
1136*cda5da8dSAndroid Build Coastguard Worker            file.write('Download-URL: %s\n' % self.download_url)
1137*cda5da8dSAndroid Build Coastguard Worker
1138*cda5da8dSAndroid Build Coastguard Worker        long_desc = rfc822_escape(self.get_long_description())
1139*cda5da8dSAndroid Build Coastguard Worker        file.write('Description: %s\n' % long_desc)
1140*cda5da8dSAndroid Build Coastguard Worker
1141*cda5da8dSAndroid Build Coastguard Worker        keywords = ','.join(self.get_keywords())
1142*cda5da8dSAndroid Build Coastguard Worker        if keywords:
1143*cda5da8dSAndroid Build Coastguard Worker            file.write('Keywords: %s\n' % keywords)
1144*cda5da8dSAndroid Build Coastguard Worker
1145*cda5da8dSAndroid Build Coastguard Worker        self._write_list(file, 'Platform', self.get_platforms())
1146*cda5da8dSAndroid Build Coastguard Worker        self._write_list(file, 'Classifier', self.get_classifiers())
1147*cda5da8dSAndroid Build Coastguard Worker
1148*cda5da8dSAndroid Build Coastguard Worker        # PEP 314
1149*cda5da8dSAndroid Build Coastguard Worker        self._write_list(file, 'Requires', self.get_requires())
1150*cda5da8dSAndroid Build Coastguard Worker        self._write_list(file, 'Provides', self.get_provides())
1151*cda5da8dSAndroid Build Coastguard Worker        self._write_list(file, 'Obsoletes', self.get_obsoletes())
1152*cda5da8dSAndroid Build Coastguard Worker
1153*cda5da8dSAndroid Build Coastguard Worker    def _write_list(self, file, name, values):
1154*cda5da8dSAndroid Build Coastguard Worker        for value in values:
1155*cda5da8dSAndroid Build Coastguard Worker            file.write('%s: %s\n' % (name, value))
1156*cda5da8dSAndroid Build Coastguard Worker
1157*cda5da8dSAndroid Build Coastguard Worker    # -- Metadata query methods ----------------------------------------
1158*cda5da8dSAndroid Build Coastguard Worker
1159*cda5da8dSAndroid Build Coastguard Worker    def get_name(self):
1160*cda5da8dSAndroid Build Coastguard Worker        return self.name or "UNKNOWN"
1161*cda5da8dSAndroid Build Coastguard Worker
1162*cda5da8dSAndroid Build Coastguard Worker    def get_version(self):
1163*cda5da8dSAndroid Build Coastguard Worker        return self.version or "0.0.0"
1164*cda5da8dSAndroid Build Coastguard Worker
1165*cda5da8dSAndroid Build Coastguard Worker    def get_fullname(self):
1166*cda5da8dSAndroid Build Coastguard Worker        return "%s-%s" % (self.get_name(), self.get_version())
1167*cda5da8dSAndroid Build Coastguard Worker
1168*cda5da8dSAndroid Build Coastguard Worker    def get_author(self):
1169*cda5da8dSAndroid Build Coastguard Worker        return self.author or "UNKNOWN"
1170*cda5da8dSAndroid Build Coastguard Worker
1171*cda5da8dSAndroid Build Coastguard Worker    def get_author_email(self):
1172*cda5da8dSAndroid Build Coastguard Worker        return self.author_email or "UNKNOWN"
1173*cda5da8dSAndroid Build Coastguard Worker
1174*cda5da8dSAndroid Build Coastguard Worker    def get_maintainer(self):
1175*cda5da8dSAndroid Build Coastguard Worker        return self.maintainer or "UNKNOWN"
1176*cda5da8dSAndroid Build Coastguard Worker
1177*cda5da8dSAndroid Build Coastguard Worker    def get_maintainer_email(self):
1178*cda5da8dSAndroid Build Coastguard Worker        return self.maintainer_email or "UNKNOWN"
1179*cda5da8dSAndroid Build Coastguard Worker
1180*cda5da8dSAndroid Build Coastguard Worker    def get_contact(self):
1181*cda5da8dSAndroid Build Coastguard Worker        return self.maintainer or self.author or "UNKNOWN"
1182*cda5da8dSAndroid Build Coastguard Worker
1183*cda5da8dSAndroid Build Coastguard Worker    def get_contact_email(self):
1184*cda5da8dSAndroid Build Coastguard Worker        return self.maintainer_email or self.author_email or "UNKNOWN"
1185*cda5da8dSAndroid Build Coastguard Worker
1186*cda5da8dSAndroid Build Coastguard Worker    def get_url(self):
1187*cda5da8dSAndroid Build Coastguard Worker        return self.url or "UNKNOWN"
1188*cda5da8dSAndroid Build Coastguard Worker
1189*cda5da8dSAndroid Build Coastguard Worker    def get_license(self):
1190*cda5da8dSAndroid Build Coastguard Worker        return self.license or "UNKNOWN"
1191*cda5da8dSAndroid Build Coastguard Worker    get_licence = get_license
1192*cda5da8dSAndroid Build Coastguard Worker
1193*cda5da8dSAndroid Build Coastguard Worker    def get_description(self):
1194*cda5da8dSAndroid Build Coastguard Worker        return self.description or "UNKNOWN"
1195*cda5da8dSAndroid Build Coastguard Worker
1196*cda5da8dSAndroid Build Coastguard Worker    def get_long_description(self):
1197*cda5da8dSAndroid Build Coastguard Worker        return self.long_description or "UNKNOWN"
1198*cda5da8dSAndroid Build Coastguard Worker
1199*cda5da8dSAndroid Build Coastguard Worker    def get_keywords(self):
1200*cda5da8dSAndroid Build Coastguard Worker        return self.keywords or []
1201*cda5da8dSAndroid Build Coastguard Worker
1202*cda5da8dSAndroid Build Coastguard Worker    def set_keywords(self, value):
1203*cda5da8dSAndroid Build Coastguard Worker        self.keywords = _ensure_list(value, 'keywords')
1204*cda5da8dSAndroid Build Coastguard Worker
1205*cda5da8dSAndroid Build Coastguard Worker    def get_platforms(self):
1206*cda5da8dSAndroid Build Coastguard Worker        return self.platforms or ["UNKNOWN"]
1207*cda5da8dSAndroid Build Coastguard Worker
1208*cda5da8dSAndroid Build Coastguard Worker    def set_platforms(self, value):
1209*cda5da8dSAndroid Build Coastguard Worker        self.platforms = _ensure_list(value, 'platforms')
1210*cda5da8dSAndroid Build Coastguard Worker
1211*cda5da8dSAndroid Build Coastguard Worker    def get_classifiers(self):
1212*cda5da8dSAndroid Build Coastguard Worker        return self.classifiers or []
1213*cda5da8dSAndroid Build Coastguard Worker
1214*cda5da8dSAndroid Build Coastguard Worker    def set_classifiers(self, value):
1215*cda5da8dSAndroid Build Coastguard Worker        self.classifiers = _ensure_list(value, 'classifiers')
1216*cda5da8dSAndroid Build Coastguard Worker
1217*cda5da8dSAndroid Build Coastguard Worker    def get_download_url(self):
1218*cda5da8dSAndroid Build Coastguard Worker        return self.download_url or "UNKNOWN"
1219*cda5da8dSAndroid Build Coastguard Worker
1220*cda5da8dSAndroid Build Coastguard Worker    # PEP 314
1221*cda5da8dSAndroid Build Coastguard Worker    def get_requires(self):
1222*cda5da8dSAndroid Build Coastguard Worker        return self.requires or []
1223*cda5da8dSAndroid Build Coastguard Worker
1224*cda5da8dSAndroid Build Coastguard Worker    def set_requires(self, value):
1225*cda5da8dSAndroid Build Coastguard Worker        import distutils.versionpredicate
1226*cda5da8dSAndroid Build Coastguard Worker        for v in value:
1227*cda5da8dSAndroid Build Coastguard Worker            distutils.versionpredicate.VersionPredicate(v)
1228*cda5da8dSAndroid Build Coastguard Worker        self.requires = list(value)
1229*cda5da8dSAndroid Build Coastguard Worker
1230*cda5da8dSAndroid Build Coastguard Worker    def get_provides(self):
1231*cda5da8dSAndroid Build Coastguard Worker        return self.provides or []
1232*cda5da8dSAndroid Build Coastguard Worker
1233*cda5da8dSAndroid Build Coastguard Worker    def set_provides(self, value):
1234*cda5da8dSAndroid Build Coastguard Worker        value = [v.strip() for v in value]
1235*cda5da8dSAndroid Build Coastguard Worker        for v in value:
1236*cda5da8dSAndroid Build Coastguard Worker            import distutils.versionpredicate
1237*cda5da8dSAndroid Build Coastguard Worker            distutils.versionpredicate.split_provision(v)
1238*cda5da8dSAndroid Build Coastguard Worker        self.provides = value
1239*cda5da8dSAndroid Build Coastguard Worker
1240*cda5da8dSAndroid Build Coastguard Worker    def get_obsoletes(self):
1241*cda5da8dSAndroid Build Coastguard Worker        return self.obsoletes or []
1242*cda5da8dSAndroid Build Coastguard Worker
1243*cda5da8dSAndroid Build Coastguard Worker    def set_obsoletes(self, value):
1244*cda5da8dSAndroid Build Coastguard Worker        import distutils.versionpredicate
1245*cda5da8dSAndroid Build Coastguard Worker        for v in value:
1246*cda5da8dSAndroid Build Coastguard Worker            distutils.versionpredicate.VersionPredicate(v)
1247*cda5da8dSAndroid Build Coastguard Worker        self.obsoletes = list(value)
1248*cda5da8dSAndroid Build Coastguard Worker
1249*cda5da8dSAndroid Build Coastguard Workerdef fix_help_options(options):
1250*cda5da8dSAndroid Build Coastguard Worker    """Convert a 4-tuple 'help_options' list as found in various command
1251*cda5da8dSAndroid Build Coastguard Worker    classes to the 3-tuple form required by FancyGetopt.
1252*cda5da8dSAndroid Build Coastguard Worker    """
1253*cda5da8dSAndroid Build Coastguard Worker    new_options = []
1254*cda5da8dSAndroid Build Coastguard Worker    for help_tuple in options:
1255*cda5da8dSAndroid Build Coastguard Worker        new_options.append(help_tuple[0:3])
1256*cda5da8dSAndroid Build Coastguard Worker    return new_options
1257