Mercurial > repos > bcclaywell > argo_navis
comparison venv/lib/python2.7/site-packages/setuptools/command/egg_info.py @ 0:d67268158946 draft
planemo upload commit a3f181f5f126803c654b3a66dd4e83a48f7e203b
| author | bcclaywell |
|---|---|
| date | Mon, 12 Oct 2015 17:43:33 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:d67268158946 |
|---|---|
| 1 """setuptools.command.egg_info | |
| 2 | |
| 3 Create a distribution's .egg-info directory and contents""" | |
| 4 | |
| 5 from distutils.filelist import FileList as _FileList | |
| 6 from distutils.util import convert_path | |
| 7 from distutils import log | |
| 8 import distutils.errors | |
| 9 import distutils.filelist | |
| 10 import os | |
| 11 import re | |
| 12 import sys | |
| 13 | |
| 14 try: | |
| 15 from setuptools_svn import svn_utils | |
| 16 except ImportError: | |
| 17 pass | |
| 18 | |
| 19 from setuptools import Command | |
| 20 from setuptools.command.sdist import sdist | |
| 21 from setuptools.compat import basestring, PY3, StringIO | |
| 22 from setuptools.command.sdist import walk_revctrl | |
| 23 from pkg_resources import ( | |
| 24 parse_requirements, safe_name, parse_version, | |
| 25 safe_version, yield_lines, EntryPoint, iter_entry_points, to_filename) | |
| 26 import setuptools.unicode_utils as unicode_utils | |
| 27 | |
| 28 from pkg_resources import packaging | |
| 29 | |
| 30 class egg_info(Command): | |
| 31 description = "create a distribution's .egg-info directory" | |
| 32 | |
| 33 user_options = [ | |
| 34 ('egg-base=', 'e', "directory containing .egg-info directories" | |
| 35 " (default: top of the source tree)"), | |
| 36 ('tag-svn-revision', 'r', | |
| 37 "Add subversion revision ID to version number"), | |
| 38 ('tag-date', 'd', "Add date stamp (e.g. 20050528) to version number"), | |
| 39 ('tag-build=', 'b', "Specify explicit tag to add to version number"), | |
| 40 ('no-svn-revision', 'R', | |
| 41 "Don't add subversion revision ID [default]"), | |
| 42 ('no-date', 'D', "Don't include date stamp [default]"), | |
| 43 ] | |
| 44 | |
| 45 boolean_options = ['tag-date', 'tag-svn-revision'] | |
| 46 negative_opt = {'no-svn-revision': 'tag-svn-revision', | |
| 47 'no-date': 'tag-date'} | |
| 48 | |
| 49 def initialize_options(self): | |
| 50 self.egg_name = None | |
| 51 self.egg_version = None | |
| 52 self.egg_base = None | |
| 53 self.egg_info = None | |
| 54 self.tag_build = None | |
| 55 self.tag_svn_revision = 0 | |
| 56 self.tag_date = 0 | |
| 57 self.broken_egg_info = False | |
| 58 self.vtags = None | |
| 59 | |
| 60 def save_version_info(self, filename): | |
| 61 from setuptools.command.setopt import edit_config | |
| 62 | |
| 63 values = dict( | |
| 64 egg_info=dict( | |
| 65 tag_svn_revision=0, | |
| 66 tag_date=0, | |
| 67 tag_build=self.tags(), | |
| 68 ) | |
| 69 ) | |
| 70 edit_config(filename, values) | |
| 71 | |
| 72 def finalize_options(self): | |
| 73 self.egg_name = safe_name(self.distribution.get_name()) | |
| 74 self.vtags = self.tags() | |
| 75 self.egg_version = self.tagged_version() | |
| 76 | |
| 77 parsed_version = parse_version(self.egg_version) | |
| 78 | |
| 79 try: | |
| 80 is_version = isinstance(parsed_version, packaging.version.Version) | |
| 81 spec = ( | |
| 82 "%s==%s" if is_version else "%s===%s" | |
| 83 ) | |
| 84 list( | |
| 85 parse_requirements(spec % (self.egg_name, self.egg_version)) | |
| 86 ) | |
| 87 except ValueError: | |
| 88 raise distutils.errors.DistutilsOptionError( | |
| 89 "Invalid distribution name or version syntax: %s-%s" % | |
| 90 (self.egg_name, self.egg_version) | |
| 91 ) | |
| 92 | |
| 93 if self.egg_base is None: | |
| 94 dirs = self.distribution.package_dir | |
| 95 self.egg_base = (dirs or {}).get('', os.curdir) | |
| 96 | |
| 97 self.ensure_dirname('egg_base') | |
| 98 self.egg_info = to_filename(self.egg_name) + '.egg-info' | |
| 99 if self.egg_base != os.curdir: | |
| 100 self.egg_info = os.path.join(self.egg_base, self.egg_info) | |
| 101 if '-' in self.egg_name: | |
| 102 self.check_broken_egg_info() | |
| 103 | |
| 104 # Set package version for the benefit of dumber commands | |
| 105 # (e.g. sdist, bdist_wininst, etc.) | |
| 106 # | |
| 107 self.distribution.metadata.version = self.egg_version | |
| 108 | |
| 109 # If we bootstrapped around the lack of a PKG-INFO, as might be the | |
| 110 # case in a fresh checkout, make sure that any special tags get added | |
| 111 # to the version info | |
| 112 # | |
| 113 pd = self.distribution._patched_dist | |
| 114 if pd is not None and pd.key == self.egg_name.lower(): | |
| 115 pd._version = self.egg_version | |
| 116 pd._parsed_version = parse_version(self.egg_version) | |
| 117 self.distribution._patched_dist = None | |
| 118 | |
| 119 def write_or_delete_file(self, what, filename, data, force=False): | |
| 120 """Write `data` to `filename` or delete if empty | |
| 121 | |
| 122 If `data` is non-empty, this routine is the same as ``write_file()``. | |
| 123 If `data` is empty but not ``None``, this is the same as calling | |
| 124 ``delete_file(filename)`. If `data` is ``None``, then this is a no-op | |
| 125 unless `filename` exists, in which case a warning is issued about the | |
| 126 orphaned file (if `force` is false), or deleted (if `force` is true). | |
| 127 """ | |
| 128 if data: | |
| 129 self.write_file(what, filename, data) | |
| 130 elif os.path.exists(filename): | |
| 131 if data is None and not force: | |
| 132 log.warn( | |
| 133 "%s not set in setup(), but %s exists", what, filename | |
| 134 ) | |
| 135 return | |
| 136 else: | |
| 137 self.delete_file(filename) | |
| 138 | |
| 139 def write_file(self, what, filename, data): | |
| 140 """Write `data` to `filename` (if not a dry run) after announcing it | |
| 141 | |
| 142 `what` is used in a log message to identify what is being written | |
| 143 to the file. | |
| 144 """ | |
| 145 log.info("writing %s to %s", what, filename) | |
| 146 if PY3: | |
| 147 data = data.encode("utf-8") | |
| 148 if not self.dry_run: | |
| 149 f = open(filename, 'wb') | |
| 150 f.write(data) | |
| 151 f.close() | |
| 152 | |
| 153 def delete_file(self, filename): | |
| 154 """Delete `filename` (if not a dry run) after announcing it""" | |
| 155 log.info("deleting %s", filename) | |
| 156 if not self.dry_run: | |
| 157 os.unlink(filename) | |
| 158 | |
| 159 def tagged_version(self): | |
| 160 version = self.distribution.get_version() | |
| 161 # egg_info may be called more than once for a distribution, | |
| 162 # in which case the version string already contains all tags. | |
| 163 if self.vtags and version.endswith(self.vtags): | |
| 164 return safe_version(version) | |
| 165 return safe_version(version + self.vtags) | |
| 166 | |
| 167 def run(self): | |
| 168 self.mkpath(self.egg_info) | |
| 169 installer = self.distribution.fetch_build_egg | |
| 170 for ep in iter_entry_points('egg_info.writers'): | |
| 171 ep.require(installer=installer) | |
| 172 writer = ep.resolve() | |
| 173 writer(self, ep.name, os.path.join(self.egg_info, ep.name)) | |
| 174 | |
| 175 # Get rid of native_libs.txt if it was put there by older bdist_egg | |
| 176 nl = os.path.join(self.egg_info, "native_libs.txt") | |
| 177 if os.path.exists(nl): | |
| 178 self.delete_file(nl) | |
| 179 | |
| 180 self.find_sources() | |
| 181 | |
| 182 def tags(self): | |
| 183 version = '' | |
| 184 if self.tag_build: | |
| 185 version += self.tag_build | |
| 186 if self.tag_svn_revision: | |
| 187 rev = self.get_svn_revision() | |
| 188 if rev: # is 0 if it's not an svn working copy | |
| 189 version += '-r%s' % rev | |
| 190 if self.tag_date: | |
| 191 import time | |
| 192 | |
| 193 version += time.strftime("-%Y%m%d") | |
| 194 return version | |
| 195 | |
| 196 @staticmethod | |
| 197 def get_svn_revision(): | |
| 198 if 'svn_utils' not in globals(): | |
| 199 return "0" | |
| 200 return str(svn_utils.SvnInfo.load(os.curdir).get_revision()) | |
| 201 | |
| 202 def find_sources(self): | |
| 203 """Generate SOURCES.txt manifest file""" | |
| 204 manifest_filename = os.path.join(self.egg_info, "SOURCES.txt") | |
| 205 mm = manifest_maker(self.distribution) | |
| 206 mm.manifest = manifest_filename | |
| 207 mm.run() | |
| 208 self.filelist = mm.filelist | |
| 209 | |
| 210 def check_broken_egg_info(self): | |
| 211 bei = self.egg_name + '.egg-info' | |
| 212 if self.egg_base != os.curdir: | |
| 213 bei = os.path.join(self.egg_base, bei) | |
| 214 if os.path.exists(bei): | |
| 215 log.warn( | |
| 216 "-" * 78 + '\n' | |
| 217 "Note: Your current .egg-info directory has a '-' in its name;" | |
| 218 '\nthis will not work correctly with "setup.py develop".\n\n' | |
| 219 'Please rename %s to %s to correct this problem.\n' + '-' * 78, | |
| 220 bei, self.egg_info | |
| 221 ) | |
| 222 self.broken_egg_info = self.egg_info | |
| 223 self.egg_info = bei # make it work for now | |
| 224 | |
| 225 | |
| 226 class FileList(_FileList): | |
| 227 """File list that accepts only existing, platform-independent paths""" | |
| 228 | |
| 229 def append(self, item): | |
| 230 if item.endswith('\r'): # Fix older sdists built on Windows | |
| 231 item = item[:-1] | |
| 232 path = convert_path(item) | |
| 233 | |
| 234 if self._safe_path(path): | |
| 235 self.files.append(path) | |
| 236 | |
| 237 def extend(self, paths): | |
| 238 self.files.extend(filter(self._safe_path, paths)) | |
| 239 | |
| 240 def _repair(self): | |
| 241 """ | |
| 242 Replace self.files with only safe paths | |
| 243 | |
| 244 Because some owners of FileList manipulate the underlying | |
| 245 ``files`` attribute directly, this method must be called to | |
| 246 repair those paths. | |
| 247 """ | |
| 248 self.files = list(filter(self._safe_path, self.files)) | |
| 249 | |
| 250 def _safe_path(self, path): | |
| 251 enc_warn = "'%s' not %s encodable -- skipping" | |
| 252 | |
| 253 # To avoid accidental trans-codings errors, first to unicode | |
| 254 u_path = unicode_utils.filesys_decode(path) | |
| 255 if u_path is None: | |
| 256 log.warn("'%s' in unexpected encoding -- skipping" % path) | |
| 257 return False | |
| 258 | |
| 259 # Must ensure utf-8 encodability | |
| 260 utf8_path = unicode_utils.try_encode(u_path, "utf-8") | |
| 261 if utf8_path is None: | |
| 262 log.warn(enc_warn, path, 'utf-8') | |
| 263 return False | |
| 264 | |
| 265 try: | |
| 266 # accept is either way checks out | |
| 267 if os.path.exists(u_path) or os.path.exists(utf8_path): | |
| 268 return True | |
| 269 # this will catch any encode errors decoding u_path | |
| 270 except UnicodeEncodeError: | |
| 271 log.warn(enc_warn, path, sys.getfilesystemencoding()) | |
| 272 | |
| 273 | |
| 274 class manifest_maker(sdist): | |
| 275 template = "MANIFEST.in" | |
| 276 | |
| 277 def initialize_options(self): | |
| 278 self.use_defaults = 1 | |
| 279 self.prune = 1 | |
| 280 self.manifest_only = 1 | |
| 281 self.force_manifest = 1 | |
| 282 | |
| 283 def finalize_options(self): | |
| 284 pass | |
| 285 | |
| 286 def run(self): | |
| 287 self.filelist = FileList() | |
| 288 if not os.path.exists(self.manifest): | |
| 289 self.write_manifest() # it must exist so it'll get in the list | |
| 290 self.filelist.findall() | |
| 291 self.add_defaults() | |
| 292 if os.path.exists(self.template): | |
| 293 self.read_template() | |
| 294 self.prune_file_list() | |
| 295 self.filelist.sort() | |
| 296 self.filelist.remove_duplicates() | |
| 297 self.write_manifest() | |
| 298 | |
| 299 def _manifest_normalize(self, path): | |
| 300 path = unicode_utils.filesys_decode(path) | |
| 301 return path.replace(os.sep, '/') | |
| 302 | |
| 303 def write_manifest(self): | |
| 304 """ | |
| 305 Write the file list in 'self.filelist' to the manifest file | |
| 306 named by 'self.manifest'. | |
| 307 """ | |
| 308 self.filelist._repair() | |
| 309 | |
| 310 # Now _repairs should encodability, but not unicode | |
| 311 files = [self._manifest_normalize(f) for f in self.filelist.files] | |
| 312 msg = "writing manifest file '%s'" % self.manifest | |
| 313 self.execute(write_file, (self.manifest, files), msg) | |
| 314 | |
| 315 def warn(self, msg): # suppress missing-file warnings from sdist | |
| 316 if not msg.startswith("standard file not found:"): | |
| 317 sdist.warn(self, msg) | |
| 318 | |
| 319 def add_defaults(self): | |
| 320 sdist.add_defaults(self) | |
| 321 self.filelist.append(self.template) | |
| 322 self.filelist.append(self.manifest) | |
| 323 rcfiles = list(walk_revctrl()) | |
| 324 if rcfiles: | |
| 325 self.filelist.extend(rcfiles) | |
| 326 elif os.path.exists(self.manifest): | |
| 327 self.read_manifest() | |
| 328 ei_cmd = self.get_finalized_command('egg_info') | |
| 329 self._add_egg_info(cmd=ei_cmd) | |
| 330 self.filelist.include_pattern("*", prefix=ei_cmd.egg_info) | |
| 331 | |
| 332 def _add_egg_info(self, cmd): | |
| 333 """ | |
| 334 Add paths for egg-info files for an external egg-base. | |
| 335 | |
| 336 The egg-info files are written to egg-base. If egg-base is | |
| 337 outside the current working directory, this method | |
| 338 searchs the egg-base directory for files to include | |
| 339 in the manifest. Uses distutils.filelist.findall (which is | |
| 340 really the version monkeypatched in by setuptools/__init__.py) | |
| 341 to perform the search. | |
| 342 | |
| 343 Since findall records relative paths, prefix the returned | |
| 344 paths with cmd.egg_base, so add_default's include_pattern call | |
| 345 (which is looking for the absolute cmd.egg_info) will match | |
| 346 them. | |
| 347 """ | |
| 348 if cmd.egg_base == os.curdir: | |
| 349 # egg-info files were already added by something else | |
| 350 return | |
| 351 | |
| 352 discovered = distutils.filelist.findall(cmd.egg_base) | |
| 353 resolved = (os.path.join(cmd.egg_base, path) for path in discovered) | |
| 354 self.filelist.allfiles.extend(resolved) | |
| 355 | |
| 356 def prune_file_list(self): | |
| 357 build = self.get_finalized_command('build') | |
| 358 base_dir = self.distribution.get_fullname() | |
| 359 self.filelist.exclude_pattern(None, prefix=build.build_base) | |
| 360 self.filelist.exclude_pattern(None, prefix=base_dir) | |
| 361 sep = re.escape(os.sep) | |
| 362 self.filelist.exclude_pattern(r'(^|' + sep + r')(RCS|CVS|\.svn)' + sep, | |
| 363 is_regex=1) | |
| 364 | |
| 365 | |
| 366 def write_file(filename, contents): | |
| 367 """Create a file with the specified name and write 'contents' (a | |
| 368 sequence of strings without line terminators) to it. | |
| 369 """ | |
| 370 contents = "\n".join(contents) | |
| 371 | |
| 372 # assuming the contents has been vetted for utf-8 encoding | |
| 373 contents = contents.encode("utf-8") | |
| 374 | |
| 375 with open(filename, "wb") as f: # always write POSIX-style manifest | |
| 376 f.write(contents) | |
| 377 | |
| 378 | |
| 379 def write_pkg_info(cmd, basename, filename): | |
| 380 log.info("writing %s", filename) | |
| 381 if not cmd.dry_run: | |
| 382 metadata = cmd.distribution.metadata | |
| 383 metadata.version, oldver = cmd.egg_version, metadata.version | |
| 384 metadata.name, oldname = cmd.egg_name, metadata.name | |
| 385 try: | |
| 386 # write unescaped data to PKG-INFO, so older pkg_resources | |
| 387 # can still parse it | |
| 388 metadata.write_pkg_info(cmd.egg_info) | |
| 389 finally: | |
| 390 metadata.name, metadata.version = oldname, oldver | |
| 391 | |
| 392 safe = getattr(cmd.distribution, 'zip_safe', None) | |
| 393 from setuptools.command import bdist_egg | |
| 394 | |
| 395 bdist_egg.write_safety_flag(cmd.egg_info, safe) | |
| 396 | |
| 397 | |
| 398 def warn_depends_obsolete(cmd, basename, filename): | |
| 399 if os.path.exists(filename): | |
| 400 log.warn( | |
| 401 "WARNING: 'depends.txt' is not used by setuptools 0.6!\n" | |
| 402 "Use the install_requires/extras_require setup() args instead." | |
| 403 ) | |
| 404 | |
| 405 | |
| 406 def _write_requirements(stream, reqs): | |
| 407 lines = yield_lines(reqs or ()) | |
| 408 append_cr = lambda line: line + '\n' | |
| 409 lines = map(append_cr, lines) | |
| 410 stream.writelines(lines) | |
| 411 | |
| 412 | |
| 413 def write_requirements(cmd, basename, filename): | |
| 414 dist = cmd.distribution | |
| 415 data = StringIO() | |
| 416 _write_requirements(data, dist.install_requires) | |
| 417 extras_require = dist.extras_require or {} | |
| 418 for extra in sorted(extras_require): | |
| 419 data.write('\n[{extra}]\n'.format(**vars())) | |
| 420 _write_requirements(data, extras_require[extra]) | |
| 421 cmd.write_or_delete_file("requirements", filename, data.getvalue()) | |
| 422 | |
| 423 | |
| 424 def write_setup_requirements(cmd, basename, filename): | |
| 425 data = StringIO() | |
| 426 _write_requirements(data, cmd.distribution.setup_requires) | |
| 427 cmd.write_or_delete_file("setup-requirements", filename, data.getvalue()) | |
| 428 | |
| 429 | |
| 430 def write_toplevel_names(cmd, basename, filename): | |
| 431 pkgs = dict.fromkeys( | |
| 432 [ | |
| 433 k.split('.', 1)[0] | |
| 434 for k in cmd.distribution.iter_distribution_names() | |
| 435 ] | |
| 436 ) | |
| 437 cmd.write_file("top-level names", filename, '\n'.join(sorted(pkgs)) + '\n') | |
| 438 | |
| 439 | |
| 440 def overwrite_arg(cmd, basename, filename): | |
| 441 write_arg(cmd, basename, filename, True) | |
| 442 | |
| 443 | |
| 444 def write_arg(cmd, basename, filename, force=False): | |
| 445 argname = os.path.splitext(basename)[0] | |
| 446 value = getattr(cmd.distribution, argname, None) | |
| 447 if value is not None: | |
| 448 value = '\n'.join(value) + '\n' | |
| 449 cmd.write_or_delete_file(argname, filename, value, force) | |
| 450 | |
| 451 | |
| 452 def write_entries(cmd, basename, filename): | |
| 453 ep = cmd.distribution.entry_points | |
| 454 | |
| 455 if isinstance(ep, basestring) or ep is None: | |
| 456 data = ep | |
| 457 elif ep is not None: | |
| 458 data = [] | |
| 459 for section, contents in sorted(ep.items()): | |
| 460 if not isinstance(contents, basestring): | |
| 461 contents = EntryPoint.parse_group(section, contents) | |
| 462 contents = '\n'.join(sorted(map(str, contents.values()))) | |
| 463 data.append('[%s]\n%s\n\n' % (section, contents)) | |
| 464 data = ''.join(data) | |
| 465 | |
| 466 cmd.write_or_delete_file('entry points', filename, data, True) | |
| 467 | |
| 468 | |
| 469 def get_pkg_info_revision(): | |
| 470 # See if we can get a -r### off of PKG-INFO, in case this is an sdist of | |
| 471 # a subversion revision | |
| 472 # | |
| 473 if os.path.exists('PKG-INFO'): | |
| 474 f = open('PKG-INFO', 'rU') | |
| 475 for line in f: | |
| 476 match = re.match(r"Version:.*-r(\d+)\s*$", line) | |
| 477 if match: | |
| 478 return int(match.group(1)) | |
| 479 f.close() | |
| 480 return 0 |
