1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 """
18 ===================
19 Main setup runner
20 ===================
21
22 This module provides a wrapper around the distutils core setup.
23 """
24 __author__ = u"Andr\xe9 Malo"
25 __docformat__ = "restructuredtext en"
26
27 import ConfigParser as _config_parser
28 from distutils import core as _core
29 import os as _os
30 import posixpath as _posixpath
31 import sys as _sys
32
33 from _setup import data as _data
34 from _setup import ext as _ext
35 from _setup import util as _util
36 from _setup import shell as _shell
37
38
40 """ Check python version """
41 pyversion = map(int, _sys.version_info[:3])
42 min_required = map(int, '.'.join((version_min, '0.0.0')).split('.')[:3])
43 if pyversion < min_required:
44 raise EnvironmentError("Need at least python %s (vs. %s)" % (
45 '.'.join(map(str, min_required)), '.'.join(pyversion)
46 ))
47 if version_max:
48 max_required = map(
49 int, '.'.join((version_max, '0.0.0')).split('.')[:3]
50 )
51 if pyversion > version_max:
52 raise EnvironmentError("Need at max python %s (vs. %s)" % (
53 '.'.join(map(str, max_required)), '.'.join(pyversion)
54 ))
55
56
58 """
59 Determine the package description from DESCRIPTION
60
61 :Parameters:
62 `docs` : ``dict``
63 Docs config section
64
65 :Return: Tuple of summary, description and license
66 (``('summary', 'description', 'license')``)
67 (all may be ``None``)
68 :Rtype: ``tuple``
69 """
70 summary = None
71 filename = docs.get('meta.summary', 'SUMMARY').strip()
72 if filename and _os.path.isfile(filename):
73 fp = file(filename)
74 try:
75 try:
76 summary = fp.read().strip().splitlines()[0].rstrip()
77 except IndexError:
78 summary = ''
79 finally:
80 fp.close()
81
82 description = None
83 filename = docs.get('meta.description', 'DESCRIPTION').strip()
84 if filename and _os.path.isfile(filename):
85 fp = file(filename)
86 try:
87 description = fp.read().rstrip()
88 finally:
89 fp.close()
90
91 if summary is None and description:
92 from docutils import core
93 summary = core.publish_parts(
94 source=description,
95 source_path=filename,
96 writer_name='html',
97 )['title'].encode('utf-8')
98
99 return summary, description
100
101
103 """
104 Determine classifiers from CLASSIFIERS
105
106 :return: List of classifiers (``['classifier', ...]``)
107 :rtype: ``list``
108 """
109 filename = docs.get('meta.classifiers', 'CLASSIFIERS').strip()
110 if filename and _os.path.isfile(filename):
111 fp = file(filename)
112 try:
113 content = fp.read()
114 finally:
115 fp.close()
116 content = [item.strip() for item in content.splitlines()]
117 return [item for item in content if item and not item.startswith('#')]
118 return []
119
120
122 """
123 Determine provides from PROVIDES
124
125 :return: List of provides (``['provides', ...]``)
126 :rtype: ``list``
127 """
128 filename = docs.get('meta.provides', 'PROVIDES').strip()
129 if filename and _os.path.isfile(filename):
130 fp = file(filename)
131 try:
132 content = fp.read()
133 finally:
134 fp.close()
135 content = [item.strip() for item in content.splitlines()]
136 return [item for item in content if item and not item.startswith('#')]
137 return []
138
139
141 """
142 Determine license from LICENSE
143
144 :return: License text
145 :rtype: ``str``
146 """
147 filename = docs.get('meta.license', 'LICENSE').strip()
148 if filename and _os.path.isfile(filename):
149 fp = file(filename)
150 try:
151 return fp.read().rstrip()
152 finally:
153 fp.close()
154 return None
155
156
158 """ Determine packages and subpackages """
159 packages = {}
160 collect = manifest['packages.collect'].split()
161 lib = manifest.get('packages.lib', '.')
162 try:
163 sep = _os.path.sep
164 except AttributeError:
165 sep = _os.path.join('1', '2')[1:-1]
166 for root in collect:
167 for dirpath, _, filenames in _shell.walk(_os.path.join(lib, root)):
168 if dirpath.find('.svn') >= 0:
169 continue
170 if '__init__.py' in filenames:
171 packages[
172 _os.path.normpath(dirpath).replace(sep, '.')
173 ] = None
174 packages = packages.keys()
175 packages.sort()
176 return packages
177
178
180 """ Determine data files """
181 result = []
182 if docs.get('extra', '').strip():
183 result.append(_data.Data(docs['extra'].split(),
184 prefix='share/doc/%s' % name,
185 ))
186 if docs.get('examples.dir', '').strip():
187 tpl = ['recursive-include %s *' % docs['examples.dir']]
188 if docs.get('examples.ignore', '').strip():
189 tpl.extend(["global-exclude %s" % item
190 for item in docs['examples.ignore'].split()
191 ])
192 strip = int(docs.get('examples.strip', '') or 0)
193 result.append(_data.Documentation.from_templates(*tpl, **{
194 'strip': strip,
195 'prefix': 'share/doc/%s' % name,
196 'preserve': 1,
197 }))
198 if docs.get('userdoc.dir', '').strip():
199 tpl = ['recursive-include %s *' % docs['userdoc.dir']]
200 if docs.get('userdoc.ignore', '').strip():
201 tpl.extend(["global-exclude %s" % item
202 for item in docs['userdoc.ignore'].split()
203 ])
204 strip = int(docs.get('userdoc.strip', '') or 0)
205 result.append(_data.Documentation.from_templates(*tpl, **{
206 'strip': strip,
207 'prefix': 'share/doc/%s' % name,
208 'preserve': 1,
209 }))
210 if docs.get('apidoc.dir', '').strip():
211 tpl = ['recursive-include %s *' % docs['apidoc.dir']]
212 if docs.get('apidoc.ignore', '').strip():
213 tpl.extend(["global-exclude %s" % item
214 for item in docs['apidoc.ignore'].split()
215 ])
216 strip = int(docs.get('apidoc.strip', '') or 0)
217 result.append(_data.Documentation.from_templates(*tpl, **{
218 'strip': strip,
219 'prefix': 'share/doc/%s' % name,
220 'preserve': 1,
221 }))
222 if docs.get('man', '').strip():
223 result.extend(_data.Manpages.dispatch(docs['man'].split()))
224 return result
225
226
228 """ Create file list to pack up """
229
230 kwargs = kwargs.copy()
231 kwargs['script_args'] = ['install']
232 kwargs['packages'] = list(kwargs.get('packages') or ()) + ['_setup']
233 _core._setup_stop_after = "commandline"
234 try:
235 dist = _core.setup(**kwargs)
236 finally:
237 _core._setup_stop_after = None
238
239 result = ['MANIFEST', 'PKG-INFO', 'setup.py'] + list(config)
240
241 for key in ('classifiers', 'description', 'summary', 'provides',
242 'license'):
243 filename = docs.get('meta.' + key, '').strip()
244 if filename and _os.path.isfile(filename):
245 result.append(filename)
246
247 cmd = dist.get_command_obj("build_py")
248 cmd.ensure_finalized()
249
250 for item in cmd.get_source_files():
251 result.append(_posixpath.sep.join(
252 _os.path.normpath(item).split(_os.path.sep)
253 ))
254
255 cmd = dist.get_command_obj("build_ext")
256 cmd.ensure_finalized()
257
258 for item in cmd.get_source_files():
259 result.append(_posixpath.sep.join(
260 _os.path.normpath(item).split(_os.path.sep)
261 ))
262 for ext in cmd.extensions:
263 if ext.depends:
264 result.extend([_posixpath.sep.join(
265 _os.path.normpath(item).split(_os.path.sep)
266 ) for item in ext.depends])
267
268 cmd = dist.get_command_obj("build_clib")
269 cmd.ensure_finalized()
270 if cmd.libraries:
271
272 for item in cmd.get_source_files():
273 result.append(_posixpath.sep.join(
274 _os.path.normpath(item).split(_os.path.sep)
275 ))
276 for lib in cmd.libraries:
277 if lib[1].get('depends'):
278 result.extend([_posixpath.sep.join(
279 _os.path.normpath(item).split(_os.path.sep)
280 ) for item in lib[1]['depends']])
281
282 cmd = dist.get_command_obj("build_scripts")
283 cmd.ensure_finalized()
284
285 if cmd.get_source_files():
286 for item in cmd.get_source_files():
287 result.append(_posixpath.sep.join(
288 _os.path.normpath(item).split(_os.path.sep)
289 ))
290
291 cmd = dist.get_command_obj("install_data")
292 cmd.ensure_finalized()
293
294 try:
295 strings = basestring
296 except NameError:
297 strings = (str, unicode)
298
299 for item in cmd.get_inputs():
300 if isinstance(item, strings):
301 result.append(item)
302 else:
303 result.extend(item[1])
304
305 for item in manifest.get('dist', '').split():
306 result.append(item)
307 if _os.path.isdir(item):
308 for filename in _shell.files(item):
309 result.append(filename)
310
311 result = dict([(item, None) for item in result]).keys()
312 result.sort()
313 return result
314
315
316 -def run(config=('package.cfg',), ext=None, script_args=None, manifest_only=0):
317 """ Main runner """
318 if ext is None:
319 ext = []
320
321 cfg = _util.SafeConfigParser()
322 cfg.read(config)
323 pkg = dict(cfg.items('package'))
324 if pkg.get('python.min'):
325 python_min = pkg['python.min']
326 python_max = pkg.get('python.max') or None
327 check_python_version(python_min, python_max)
328
329 manifest = dict(cfg.items('manifest'))
330 try:
331 docs = dict(cfg.items('docs'))
332 except _config_parser.NoSectionError:
333 docs = {}
334
335 summary, description = find_description(docs)
336 scripts = manifest.get('scripts', '').strip() or None
337 if scripts:
338 scripts = scripts.split()
339 modules = manifest.get('modules', '').strip() or None
340 if modules:
341 modules = modules.split()
342 keywords = docs.get('meta.keywords', '').strip() or None
343 if keywords:
344 keywords = keywords.split()
345 revision = pkg.get('version.revision', '').strip()
346 if revision:
347 revision = "-r%s" % (revision,)
348
349 kwargs = {
350 'name': pkg['name'],
351 'version': "%s%s" % (
352 pkg['version.number'],
353 ["", "-dev%s" % (revision,)][
354 _util.humanbool('version.dev', pkg['version.dev'])
355 ],
356 ),
357 'provides': find_provides(docs),
358 'description': summary,
359 'long_description': description,
360 'classifiers': find_classifiers(docs),
361 'keywords': keywords,
362 'author': pkg['author.name'],
363 'author_email': pkg['author.email'],
364 'maintainer': pkg.get('maintainer.name'),
365 'maintainer_email': pkg.get('maintainer.email'),
366 'url': pkg.get('url.homepage'),
367 'download_url': pkg.get('url.download'),
368 'license': find_license(docs),
369 'package_dir': {'': manifest.get('packages.lib', '.')},
370 'packages': find_packages(manifest),
371 'py_modules': modules,
372 'ext_modules': ext,
373 'scripts': scripts,
374 'script_args': script_args,
375 'data_files': find_data(pkg['name'], docs),
376 'cmdclass': {
377
378
379
380 'build_ext' : _ext.BuildExt,
381 'install' : _data.Install,
382 'install_data' : _data.InstallData,
383 }
384 }
385 for key in ('provides',):
386 if key not in _core.setup_keywords:
387 del kwargs[key]
388
389 if manifest_only:
390 return make_manifest(manifest, config, docs, kwargs)
391
392
393 from distutils.command import sdist
394 sdist.sdist.get_file_list = sdist.sdist.read_manifest
395
396 return _core.setup(**kwargs)
397