Package _setup :: Module setup
[hide private]
[frames] | no frames]

Source Code for Module _setup.setup

  1  # -*- coding: ascii -*- 
  2  # 
  3  # Copyright 2007, 2008, 2009, 2010 
  4  # Andr\xe9 Malo or his licensors, as applicable 
  5  # 
  6  # Licensed under the Apache License, Version 2.0 (the "License"); 
  7  # you may not use this file except in compliance with the License. 
  8  # You may obtain a copy of the License at 
  9  # 
 10  #     http://www.apache.org/licenses/LICENSE-2.0 
 11  # 
 12  # Unless required by applicable law or agreed to in writing, software 
 13  # distributed under the License is distributed on an "AS IS" BASIS, 
 14  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 15  # See the License for the specific language governing permissions and 
 16  # limitations under the License. 
 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   
39 -def check_python_version(version_min, version_max):
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
57 -def find_description(docs):
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
102 -def find_classifiers(docs):
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
121 -def find_provides(docs):
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
140 -def find_license(docs):
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
157 -def find_packages(manifest):
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
179 -def find_data(name, docs):
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
227 -def make_manifest(manifest, config, docs, kwargs):
228 """ Create file list to pack up """ 229 # pylint: disable = R0912 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 # TODO: work with default values: 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 #from pprint import pprint; pprint(("build_py", cmd.get_source_files())) 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 #from pprint import pprint; pprint(("build_ext", cmd.get_source_files())) 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 #import pprint; pprint.pprint(("build_clib", cmd.get_source_files())) 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 #import pprint; pprint.pprint(("build_scripts", cmd.get_source_files())) 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 #from pprint import pprint; pprint(("install_data", cmd.get_inputs())) 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 #'build_scripts' : build_scripts, 378 #'install_scripts': install_scripts, 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 # monkey-patch crappy manifest writer awaz. 393 from distutils.command import sdist 394 sdist.sdist.get_file_list = sdist.sdist.read_manifest 395 396 return _core.setup(**kwargs)
397