17db96d56Sopenharmony_ci"""distutils.core 27db96d56Sopenharmony_ci 37db96d56Sopenharmony_ciThe only module that needs to be imported to use the Distutils; provides 47db96d56Sopenharmony_cithe 'setup' function (which is to be called from the setup script). Also 57db96d56Sopenharmony_ciindirectly provides the Distribution and Command classes, although they are 67db96d56Sopenharmony_cireally defined in distutils.dist and distutils.cmd. 77db96d56Sopenharmony_ci""" 87db96d56Sopenharmony_ci 97db96d56Sopenharmony_ciimport os 107db96d56Sopenharmony_ciimport sys 117db96d56Sopenharmony_ci 127db96d56Sopenharmony_cifrom distutils.debug import DEBUG 137db96d56Sopenharmony_cifrom distutils.errors import * 147db96d56Sopenharmony_ci 157db96d56Sopenharmony_ci# Mainly import these so setup scripts can "from distutils.core import" them. 167db96d56Sopenharmony_cifrom distutils.dist import Distribution 177db96d56Sopenharmony_cifrom distutils.cmd import Command 187db96d56Sopenharmony_cifrom distutils.config import PyPIRCCommand 197db96d56Sopenharmony_cifrom distutils.extension import Extension 207db96d56Sopenharmony_ci 217db96d56Sopenharmony_ci# This is a barebones help message generated displayed when the user 227db96d56Sopenharmony_ci# runs the setup script with no arguments at all. More useful help 237db96d56Sopenharmony_ci# is generated with various --help options: global help, list commands, 247db96d56Sopenharmony_ci# and per-command help. 257db96d56Sopenharmony_ciUSAGE = """\ 267db96d56Sopenharmony_ciusage: %(script)s [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...] 277db96d56Sopenharmony_ci or: %(script)s --help [cmd1 cmd2 ...] 287db96d56Sopenharmony_ci or: %(script)s --help-commands 297db96d56Sopenharmony_ci or: %(script)s cmd --help 307db96d56Sopenharmony_ci""" 317db96d56Sopenharmony_ci 327db96d56Sopenharmony_cidef gen_usage (script_name): 337db96d56Sopenharmony_ci script = os.path.basename(script_name) 347db96d56Sopenharmony_ci return USAGE % vars() 357db96d56Sopenharmony_ci 367db96d56Sopenharmony_ci 377db96d56Sopenharmony_ci# Some mild magic to control the behaviour of 'setup()' from 'run_setup()'. 387db96d56Sopenharmony_ci_setup_stop_after = None 397db96d56Sopenharmony_ci_setup_distribution = None 407db96d56Sopenharmony_ci 417db96d56Sopenharmony_ci# Legal keyword arguments for the setup() function 427db96d56Sopenharmony_cisetup_keywords = ('distclass', 'script_name', 'script_args', 'options', 437db96d56Sopenharmony_ci 'name', 'version', 'author', 'author_email', 447db96d56Sopenharmony_ci 'maintainer', 'maintainer_email', 'url', 'license', 457db96d56Sopenharmony_ci 'description', 'long_description', 'keywords', 467db96d56Sopenharmony_ci 'platforms', 'classifiers', 'download_url', 477db96d56Sopenharmony_ci 'requires', 'provides', 'obsoletes', 487db96d56Sopenharmony_ci ) 497db96d56Sopenharmony_ci 507db96d56Sopenharmony_ci# Legal keyword arguments for the Extension constructor 517db96d56Sopenharmony_ciextension_keywords = ('name', 'sources', 'include_dirs', 527db96d56Sopenharmony_ci 'define_macros', 'undef_macros', 537db96d56Sopenharmony_ci 'library_dirs', 'libraries', 'runtime_library_dirs', 547db96d56Sopenharmony_ci 'extra_objects', 'extra_compile_args', 'extra_link_args', 557db96d56Sopenharmony_ci 'swig_opts', 'export_symbols', 'depends', 'language') 567db96d56Sopenharmony_ci 577db96d56Sopenharmony_cidef setup (**attrs): 587db96d56Sopenharmony_ci """The gateway to the Distutils: do everything your setup script needs 597db96d56Sopenharmony_ci to do, in a highly flexible and user-driven way. Briefly: create a 607db96d56Sopenharmony_ci Distribution instance; find and parse config files; parse the command 617db96d56Sopenharmony_ci line; run each Distutils command found there, customized by the options 627db96d56Sopenharmony_ci supplied to 'setup()' (as keyword arguments), in config files, and on 637db96d56Sopenharmony_ci the command line. 647db96d56Sopenharmony_ci 657db96d56Sopenharmony_ci The Distribution instance might be an instance of a class supplied via 667db96d56Sopenharmony_ci the 'distclass' keyword argument to 'setup'; if no such class is 677db96d56Sopenharmony_ci supplied, then the Distribution class (in dist.py) is instantiated. 687db96d56Sopenharmony_ci All other arguments to 'setup' (except for 'cmdclass') are used to set 697db96d56Sopenharmony_ci attributes of the Distribution instance. 707db96d56Sopenharmony_ci 717db96d56Sopenharmony_ci The 'cmdclass' argument, if supplied, is a dictionary mapping command 727db96d56Sopenharmony_ci names to command classes. Each command encountered on the command line 737db96d56Sopenharmony_ci will be turned into a command class, which is in turn instantiated; any 747db96d56Sopenharmony_ci class found in 'cmdclass' is used in place of the default, which is 757db96d56Sopenharmony_ci (for command 'foo_bar') class 'foo_bar' in module 767db96d56Sopenharmony_ci 'distutils.command.foo_bar'. The command class must provide a 777db96d56Sopenharmony_ci 'user_options' attribute which is a list of option specifiers for 787db96d56Sopenharmony_ci 'distutils.fancy_getopt'. Any command-line options between the current 797db96d56Sopenharmony_ci and the next command are used to set attributes of the current command 807db96d56Sopenharmony_ci object. 817db96d56Sopenharmony_ci 827db96d56Sopenharmony_ci When the entire command-line has been successfully parsed, calls the 837db96d56Sopenharmony_ci 'run()' method on each command object in turn. This method will be 847db96d56Sopenharmony_ci driven entirely by the Distribution object (which each command object 857db96d56Sopenharmony_ci has a reference to, thanks to its constructor), and the 867db96d56Sopenharmony_ci command-specific options that became attributes of each command 877db96d56Sopenharmony_ci object. 887db96d56Sopenharmony_ci """ 897db96d56Sopenharmony_ci 907db96d56Sopenharmony_ci global _setup_stop_after, _setup_distribution 917db96d56Sopenharmony_ci 927db96d56Sopenharmony_ci # Determine the distribution class -- either caller-supplied or 937db96d56Sopenharmony_ci # our Distribution (see below). 947db96d56Sopenharmony_ci klass = attrs.get('distclass') 957db96d56Sopenharmony_ci if klass: 967db96d56Sopenharmony_ci del attrs['distclass'] 977db96d56Sopenharmony_ci else: 987db96d56Sopenharmony_ci klass = Distribution 997db96d56Sopenharmony_ci 1007db96d56Sopenharmony_ci if 'script_name' not in attrs: 1017db96d56Sopenharmony_ci attrs['script_name'] = os.path.basename(sys.argv[0]) 1027db96d56Sopenharmony_ci if 'script_args' not in attrs: 1037db96d56Sopenharmony_ci attrs['script_args'] = sys.argv[1:] 1047db96d56Sopenharmony_ci 1057db96d56Sopenharmony_ci # Create the Distribution instance, using the remaining arguments 1067db96d56Sopenharmony_ci # (ie. everything except distclass) to initialize it 1077db96d56Sopenharmony_ci try: 1087db96d56Sopenharmony_ci _setup_distribution = dist = klass(attrs) 1097db96d56Sopenharmony_ci except DistutilsSetupError as msg: 1107db96d56Sopenharmony_ci if 'name' not in attrs: 1117db96d56Sopenharmony_ci raise SystemExit("error in setup command: %s" % msg) 1127db96d56Sopenharmony_ci else: 1137db96d56Sopenharmony_ci raise SystemExit("error in %s setup command: %s" % \ 1147db96d56Sopenharmony_ci (attrs['name'], msg)) 1157db96d56Sopenharmony_ci 1167db96d56Sopenharmony_ci if _setup_stop_after == "init": 1177db96d56Sopenharmony_ci return dist 1187db96d56Sopenharmony_ci 1197db96d56Sopenharmony_ci # Find and parse the config file(s): they will override options from 1207db96d56Sopenharmony_ci # the setup script, but be overridden by the command line. 1217db96d56Sopenharmony_ci dist.parse_config_files() 1227db96d56Sopenharmony_ci 1237db96d56Sopenharmony_ci if DEBUG: 1247db96d56Sopenharmony_ci print("options (after parsing config files):") 1257db96d56Sopenharmony_ci dist.dump_option_dicts() 1267db96d56Sopenharmony_ci 1277db96d56Sopenharmony_ci if _setup_stop_after == "config": 1287db96d56Sopenharmony_ci return dist 1297db96d56Sopenharmony_ci 1307db96d56Sopenharmony_ci # Parse the command line and override config files; any 1317db96d56Sopenharmony_ci # command-line errors are the end user's fault, so turn them into 1327db96d56Sopenharmony_ci # SystemExit to suppress tracebacks. 1337db96d56Sopenharmony_ci try: 1347db96d56Sopenharmony_ci ok = dist.parse_command_line() 1357db96d56Sopenharmony_ci except DistutilsArgError as msg: 1367db96d56Sopenharmony_ci raise SystemExit(gen_usage(dist.script_name) + "\nerror: %s" % msg) 1377db96d56Sopenharmony_ci 1387db96d56Sopenharmony_ci if DEBUG: 1397db96d56Sopenharmony_ci print("options (after parsing command line):") 1407db96d56Sopenharmony_ci dist.dump_option_dicts() 1417db96d56Sopenharmony_ci 1427db96d56Sopenharmony_ci if _setup_stop_after == "commandline": 1437db96d56Sopenharmony_ci return dist 1447db96d56Sopenharmony_ci 1457db96d56Sopenharmony_ci # And finally, run all the commands found on the command line. 1467db96d56Sopenharmony_ci if ok: 1477db96d56Sopenharmony_ci try: 1487db96d56Sopenharmony_ci dist.run_commands() 1497db96d56Sopenharmony_ci except KeyboardInterrupt: 1507db96d56Sopenharmony_ci raise SystemExit("interrupted") 1517db96d56Sopenharmony_ci except OSError as exc: 1527db96d56Sopenharmony_ci if DEBUG: 1537db96d56Sopenharmony_ci sys.stderr.write("error: %s\n" % (exc,)) 1547db96d56Sopenharmony_ci raise 1557db96d56Sopenharmony_ci else: 1567db96d56Sopenharmony_ci raise SystemExit("error: %s" % (exc,)) 1577db96d56Sopenharmony_ci 1587db96d56Sopenharmony_ci except (DistutilsError, 1597db96d56Sopenharmony_ci CCompilerError) as msg: 1607db96d56Sopenharmony_ci if DEBUG: 1617db96d56Sopenharmony_ci raise 1627db96d56Sopenharmony_ci else: 1637db96d56Sopenharmony_ci raise SystemExit("error: " + str(msg)) 1647db96d56Sopenharmony_ci 1657db96d56Sopenharmony_ci return dist 1667db96d56Sopenharmony_ci 1677db96d56Sopenharmony_ci# setup () 1687db96d56Sopenharmony_ci 1697db96d56Sopenharmony_ci 1707db96d56Sopenharmony_cidef run_setup (script_name, script_args=None, stop_after="run"): 1717db96d56Sopenharmony_ci """Run a setup script in a somewhat controlled environment, and 1727db96d56Sopenharmony_ci return the Distribution instance that drives things. This is useful 1737db96d56Sopenharmony_ci if you need to find out the distribution meta-data (passed as 1747db96d56Sopenharmony_ci keyword args from 'script' to 'setup()', or the contents of the 1757db96d56Sopenharmony_ci config files or command-line. 1767db96d56Sopenharmony_ci 1777db96d56Sopenharmony_ci 'script_name' is a file that will be read and run with 'exec()'; 1787db96d56Sopenharmony_ci 'sys.argv[0]' will be replaced with 'script' for the duration of the 1797db96d56Sopenharmony_ci call. 'script_args' is a list of strings; if supplied, 1807db96d56Sopenharmony_ci 'sys.argv[1:]' will be replaced by 'script_args' for the duration of 1817db96d56Sopenharmony_ci the call. 1827db96d56Sopenharmony_ci 1837db96d56Sopenharmony_ci 'stop_after' tells 'setup()' when to stop processing; possible 1847db96d56Sopenharmony_ci values: 1857db96d56Sopenharmony_ci init 1867db96d56Sopenharmony_ci stop after the Distribution instance has been created and 1877db96d56Sopenharmony_ci populated with the keyword arguments to 'setup()' 1887db96d56Sopenharmony_ci config 1897db96d56Sopenharmony_ci stop after config files have been parsed (and their data 1907db96d56Sopenharmony_ci stored in the Distribution instance) 1917db96d56Sopenharmony_ci commandline 1927db96d56Sopenharmony_ci stop after the command-line ('sys.argv[1:]' or 'script_args') 1937db96d56Sopenharmony_ci have been parsed (and the data stored in the Distribution) 1947db96d56Sopenharmony_ci run [default] 1957db96d56Sopenharmony_ci stop after all commands have been run (the same as if 'setup()' 1967db96d56Sopenharmony_ci had been called in the usual way 1977db96d56Sopenharmony_ci 1987db96d56Sopenharmony_ci Returns the Distribution instance, which provides all information 1997db96d56Sopenharmony_ci used to drive the Distutils. 2007db96d56Sopenharmony_ci """ 2017db96d56Sopenharmony_ci if stop_after not in ('init', 'config', 'commandline', 'run'): 2027db96d56Sopenharmony_ci raise ValueError("invalid value for 'stop_after': %r" % (stop_after,)) 2037db96d56Sopenharmony_ci 2047db96d56Sopenharmony_ci global _setup_stop_after, _setup_distribution 2057db96d56Sopenharmony_ci _setup_stop_after = stop_after 2067db96d56Sopenharmony_ci 2077db96d56Sopenharmony_ci save_argv = sys.argv.copy() 2087db96d56Sopenharmony_ci g = {'__file__': script_name} 2097db96d56Sopenharmony_ci try: 2107db96d56Sopenharmony_ci try: 2117db96d56Sopenharmony_ci sys.argv[0] = script_name 2127db96d56Sopenharmony_ci if script_args is not None: 2137db96d56Sopenharmony_ci sys.argv[1:] = script_args 2147db96d56Sopenharmony_ci with open(script_name, 'rb') as f: 2157db96d56Sopenharmony_ci exec(f.read(), g) 2167db96d56Sopenharmony_ci finally: 2177db96d56Sopenharmony_ci sys.argv = save_argv 2187db96d56Sopenharmony_ci _setup_stop_after = None 2197db96d56Sopenharmony_ci except SystemExit: 2207db96d56Sopenharmony_ci # Hmm, should we do something if exiting with a non-zero code 2217db96d56Sopenharmony_ci # (ie. error)? 2227db96d56Sopenharmony_ci pass 2237db96d56Sopenharmony_ci 2247db96d56Sopenharmony_ci if _setup_distribution is None: 2257db96d56Sopenharmony_ci raise RuntimeError(("'distutils.core.setup()' was never called -- " 2267db96d56Sopenharmony_ci "perhaps '%s' is not a Distutils setup script?") % \ 2277db96d56Sopenharmony_ci script_name) 2287db96d56Sopenharmony_ci 2297db96d56Sopenharmony_ci # I wonder if the setup script's namespace -- g and l -- would be of 2307db96d56Sopenharmony_ci # any interest to callers? 2317db96d56Sopenharmony_ci #print "_setup_distribution:", _setup_distribution 2327db96d56Sopenharmony_ci return _setup_distribution 2337db96d56Sopenharmony_ci 2347db96d56Sopenharmony_ci# run_setup () 235