|
1 """distutils.core |
|
2 |
|
3 The only module that needs to be imported to use the Distutils; provides |
|
4 the 'setup' function (which is to be called from the setup script). Also |
|
5 indirectly provides the Distribution and Command classes, although they are |
|
6 really defined in distutils.dist and distutils.cmd. |
|
7 """ |
|
8 |
|
9 # This module should be kept compatible with Python 2.1. |
|
10 |
|
11 __revision__ = "$Id: core.py 65806 2008-08-18 11:13:45Z marc-andre.lemburg $" |
|
12 |
|
13 import sys, os |
|
14 from types import * |
|
15 |
|
16 from distutils.debug import DEBUG |
|
17 from distutils.errors import * |
|
18 from distutils.util import grok_environment_error |
|
19 |
|
20 # Mainly import these so setup scripts can "from distutils.core import" them. |
|
21 from distutils.dist import Distribution |
|
22 from distutils.cmd import Command |
|
23 from distutils.config import PyPIRCCommand |
|
24 from distutils.extension import Extension |
|
25 |
|
26 # This is a barebones help message generated displayed when the user |
|
27 # runs the setup script with no arguments at all. More useful help |
|
28 # is generated with various --help options: global help, list commands, |
|
29 # and per-command help. |
|
30 USAGE = """\ |
|
31 usage: %(script)s [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...] |
|
32 or: %(script)s --help [cmd1 cmd2 ...] |
|
33 or: %(script)s --help-commands |
|
34 or: %(script)s cmd --help |
|
35 """ |
|
36 |
|
37 def gen_usage (script_name): |
|
38 script = os.path.basename(script_name) |
|
39 return USAGE % vars() |
|
40 |
|
41 |
|
42 # Some mild magic to control the behaviour of 'setup()' from 'run_setup()'. |
|
43 _setup_stop_after = None |
|
44 _setup_distribution = None |
|
45 |
|
46 # Legal keyword arguments for the setup() function |
|
47 setup_keywords = ('distclass', 'script_name', 'script_args', 'options', |
|
48 'name', 'version', 'author', 'author_email', |
|
49 'maintainer', 'maintainer_email', 'url', 'license', |
|
50 'description', 'long_description', 'keywords', |
|
51 'platforms', 'classifiers', 'download_url', |
|
52 'requires', 'provides', 'obsoletes', |
|
53 ) |
|
54 |
|
55 # Legal keyword arguments for the Extension constructor |
|
56 extension_keywords = ('name', 'sources', 'include_dirs', |
|
57 'define_macros', 'undef_macros', |
|
58 'library_dirs', 'libraries', 'runtime_library_dirs', |
|
59 'extra_objects', 'extra_compile_args', 'extra_link_args', |
|
60 'swig_opts', 'export_symbols', 'depends', 'language') |
|
61 |
|
62 def setup (**attrs): |
|
63 """The gateway to the Distutils: do everything your setup script needs |
|
64 to do, in a highly flexible and user-driven way. Briefly: create a |
|
65 Distribution instance; find and parse config files; parse the command |
|
66 line; run each Distutils command found there, customized by the options |
|
67 supplied to 'setup()' (as keyword arguments), in config files, and on |
|
68 the command line. |
|
69 |
|
70 The Distribution instance might be an instance of a class supplied via |
|
71 the 'distclass' keyword argument to 'setup'; if no such class is |
|
72 supplied, then the Distribution class (in dist.py) is instantiated. |
|
73 All other arguments to 'setup' (except for 'cmdclass') are used to set |
|
74 attributes of the Distribution instance. |
|
75 |
|
76 The 'cmdclass' argument, if supplied, is a dictionary mapping command |
|
77 names to command classes. Each command encountered on the command line |
|
78 will be turned into a command class, which is in turn instantiated; any |
|
79 class found in 'cmdclass' is used in place of the default, which is |
|
80 (for command 'foo_bar') class 'foo_bar' in module |
|
81 'distutils.command.foo_bar'. The command class must provide a |
|
82 'user_options' attribute which is a list of option specifiers for |
|
83 'distutils.fancy_getopt'. Any command-line options between the current |
|
84 and the next command are used to set attributes of the current command |
|
85 object. |
|
86 |
|
87 When the entire command-line has been successfully parsed, calls the |
|
88 'run()' method on each command object in turn. This method will be |
|
89 driven entirely by the Distribution object (which each command object |
|
90 has a reference to, thanks to its constructor), and the |
|
91 command-specific options that became attributes of each command |
|
92 object. |
|
93 """ |
|
94 |
|
95 global _setup_stop_after, _setup_distribution |
|
96 |
|
97 # Determine the distribution class -- either caller-supplied or |
|
98 # our Distribution (see below). |
|
99 klass = attrs.get('distclass') |
|
100 if klass: |
|
101 del attrs['distclass'] |
|
102 else: |
|
103 klass = Distribution |
|
104 |
|
105 if 'script_name' not in attrs: |
|
106 attrs['script_name'] = os.path.basename(sys.argv[0]) |
|
107 if 'script_args' not in attrs: |
|
108 attrs['script_args'] = sys.argv[1:] |
|
109 |
|
110 # Create the Distribution instance, using the remaining arguments |
|
111 # (ie. everything except distclass) to initialize it |
|
112 try: |
|
113 _setup_distribution = dist = klass(attrs) |
|
114 except DistutilsSetupError, msg: |
|
115 if 'name' in attrs: |
|
116 raise SystemExit, "error in %s setup command: %s" % \ |
|
117 (attrs['name'], msg) |
|
118 else: |
|
119 raise SystemExit, "error in setup command: %s" % msg |
|
120 |
|
121 if _setup_stop_after == "init": |
|
122 return dist |
|
123 |
|
124 # Find and parse the config file(s): they will override options from |
|
125 # the setup script, but be overridden by the command line. |
|
126 dist.parse_config_files() |
|
127 |
|
128 if DEBUG: |
|
129 print "options (after parsing config files):" |
|
130 dist.dump_option_dicts() |
|
131 |
|
132 if _setup_stop_after == "config": |
|
133 return dist |
|
134 |
|
135 # Parse the command line; any command-line errors are the end user's |
|
136 # fault, so turn them into SystemExit to suppress tracebacks. |
|
137 try: |
|
138 ok = dist.parse_command_line() |
|
139 except DistutilsArgError, msg: |
|
140 raise SystemExit, gen_usage(dist.script_name) + "\nerror: %s" % msg |
|
141 |
|
142 if DEBUG: |
|
143 print "options (after parsing command line):" |
|
144 dist.dump_option_dicts() |
|
145 |
|
146 if _setup_stop_after == "commandline": |
|
147 return dist |
|
148 |
|
149 # And finally, run all the commands found on the command line. |
|
150 if ok: |
|
151 try: |
|
152 dist.run_commands() |
|
153 except KeyboardInterrupt: |
|
154 raise SystemExit, "interrupted" |
|
155 except (IOError, os.error), exc: |
|
156 error = grok_environment_error(exc) |
|
157 |
|
158 if DEBUG: |
|
159 sys.stderr.write(error + "\n") |
|
160 raise |
|
161 else: |
|
162 raise SystemExit, error |
|
163 |
|
164 except (DistutilsError, |
|
165 CCompilerError), msg: |
|
166 if DEBUG: |
|
167 raise |
|
168 else: |
|
169 raise SystemExit, "error: " + str(msg) |
|
170 |
|
171 return dist |
|
172 |
|
173 # setup () |
|
174 |
|
175 |
|
176 def run_setup (script_name, script_args=None, stop_after="run"): |
|
177 """Run a setup script in a somewhat controlled environment, and |
|
178 return the Distribution instance that drives things. This is useful |
|
179 if you need to find out the distribution meta-data (passed as |
|
180 keyword args from 'script' to 'setup()', or the contents of the |
|
181 config files or command-line. |
|
182 |
|
183 'script_name' is a file that will be run with 'execfile()'; |
|
184 'sys.argv[0]' will be replaced with 'script' for the duration of the |
|
185 call. 'script_args' is a list of strings; if supplied, |
|
186 'sys.argv[1:]' will be replaced by 'script_args' for the duration of |
|
187 the call. |
|
188 |
|
189 'stop_after' tells 'setup()' when to stop processing; possible |
|
190 values: |
|
191 init |
|
192 stop after the Distribution instance has been created and |
|
193 populated with the keyword arguments to 'setup()' |
|
194 config |
|
195 stop after config files have been parsed (and their data |
|
196 stored in the Distribution instance) |
|
197 commandline |
|
198 stop after the command-line ('sys.argv[1:]' or 'script_args') |
|
199 have been parsed (and the data stored in the Distribution) |
|
200 run [default] |
|
201 stop after all commands have been run (the same as if 'setup()' |
|
202 had been called in the usual way |
|
203 |
|
204 Returns the Distribution instance, which provides all information |
|
205 used to drive the Distutils. |
|
206 """ |
|
207 if stop_after not in ('init', 'config', 'commandline', 'run'): |
|
208 raise ValueError, "invalid value for 'stop_after': %r" % (stop_after,) |
|
209 |
|
210 global _setup_stop_after, _setup_distribution |
|
211 _setup_stop_after = stop_after |
|
212 |
|
213 save_argv = sys.argv |
|
214 g = {'__file__': script_name} |
|
215 l = {} |
|
216 try: |
|
217 try: |
|
218 sys.argv[0] = script_name |
|
219 if script_args is not None: |
|
220 sys.argv[1:] = script_args |
|
221 exec open(script_name, 'r').read() in g, l |
|
222 finally: |
|
223 sys.argv = save_argv |
|
224 _setup_stop_after = None |
|
225 except SystemExit: |
|
226 # Hmm, should we do something if exiting with a non-zero code |
|
227 # (ie. error)? |
|
228 pass |
|
229 except: |
|
230 raise |
|
231 |
|
232 if _setup_distribution is None: |
|
233 raise RuntimeError, \ |
|
234 ("'distutils.core.setup()' was never called -- " |
|
235 "perhaps '%s' is not a Distutils setup script?") % \ |
|
236 script_name |
|
237 |
|
238 # I wonder if the setup script's namespace -- g and l -- would be of |
|
239 # any interest to callers? |
|
240 #print "_setup_distribution:", _setup_distribution |
|
241 return _setup_distribution |
|
242 |
|
243 # run_setup () |