Mercurial > repos > guerler > springsuite
comparison planemo/lib/python3.7/site-packages/setuptools/command/egg_info.py @ 1:56ad4e20f292 draft
"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
| author | guerler |
|---|---|
| date | Fri, 31 Jul 2020 00:32:28 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 0:d30785e31577 | 1:56ad4e20f292 |
|---|---|
| 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.errors import DistutilsInternalError | |
| 7 from distutils.util import convert_path | |
| 8 from distutils import log | |
| 9 import distutils.errors | |
| 10 import distutils.filelist | |
| 11 import os | |
| 12 import re | |
| 13 import sys | |
| 14 import io | |
| 15 import warnings | |
| 16 import time | |
| 17 import collections | |
| 18 | |
| 19 from setuptools.extern import six | |
| 20 from setuptools.extern.six.moves import map | |
| 21 | |
| 22 from setuptools import Command | |
| 23 from setuptools.command.sdist import sdist | |
| 24 from setuptools.command.sdist import walk_revctrl | |
| 25 from setuptools.command.setopt import edit_config | |
| 26 from setuptools.command import bdist_egg | |
| 27 from pkg_resources import ( | |
| 28 parse_requirements, safe_name, parse_version, | |
| 29 safe_version, yield_lines, EntryPoint, iter_entry_points, to_filename) | |
| 30 import setuptools.unicode_utils as unicode_utils | |
| 31 from setuptools.glob import glob | |
| 32 | |
| 33 from setuptools.extern import packaging | |
| 34 from setuptools import SetuptoolsDeprecationWarning | |
| 35 | |
| 36 def translate_pattern(glob): | |
| 37 """ | |
| 38 Translate a file path glob like '*.txt' in to a regular expression. | |
| 39 This differs from fnmatch.translate which allows wildcards to match | |
| 40 directory separators. It also knows about '**/' which matches any number of | |
| 41 directories. | |
| 42 """ | |
| 43 pat = '' | |
| 44 | |
| 45 # This will split on '/' within [character classes]. This is deliberate. | |
| 46 chunks = glob.split(os.path.sep) | |
| 47 | |
| 48 sep = re.escape(os.sep) | |
| 49 valid_char = '[^%s]' % (sep,) | |
| 50 | |
| 51 for c, chunk in enumerate(chunks): | |
| 52 last_chunk = c == len(chunks) - 1 | |
| 53 | |
| 54 # Chunks that are a literal ** are globstars. They match anything. | |
| 55 if chunk == '**': | |
| 56 if last_chunk: | |
| 57 # Match anything if this is the last component | |
| 58 pat += '.*' | |
| 59 else: | |
| 60 # Match '(name/)*' | |
| 61 pat += '(?:%s+%s)*' % (valid_char, sep) | |
| 62 continue # Break here as the whole path component has been handled | |
| 63 | |
| 64 # Find any special characters in the remainder | |
| 65 i = 0 | |
| 66 chunk_len = len(chunk) | |
| 67 while i < chunk_len: | |
| 68 char = chunk[i] | |
| 69 if char == '*': | |
| 70 # Match any number of name characters | |
| 71 pat += valid_char + '*' | |
| 72 elif char == '?': | |
| 73 # Match a name character | |
| 74 pat += valid_char | |
| 75 elif char == '[': | |
| 76 # Character class | |
| 77 inner_i = i + 1 | |
| 78 # Skip initial !/] chars | |
| 79 if inner_i < chunk_len and chunk[inner_i] == '!': | |
| 80 inner_i = inner_i + 1 | |
| 81 if inner_i < chunk_len and chunk[inner_i] == ']': | |
| 82 inner_i = inner_i + 1 | |
| 83 | |
| 84 # Loop till the closing ] is found | |
| 85 while inner_i < chunk_len and chunk[inner_i] != ']': | |
| 86 inner_i = inner_i + 1 | |
| 87 | |
| 88 if inner_i >= chunk_len: | |
| 89 # Got to the end of the string without finding a closing ] | |
| 90 # Do not treat this as a matching group, but as a literal [ | |
| 91 pat += re.escape(char) | |
| 92 else: | |
| 93 # Grab the insides of the [brackets] | |
| 94 inner = chunk[i + 1:inner_i] | |
| 95 char_class = '' | |
| 96 | |
| 97 # Class negation | |
| 98 if inner[0] == '!': | |
| 99 char_class = '^' | |
| 100 inner = inner[1:] | |
| 101 | |
| 102 char_class += re.escape(inner) | |
| 103 pat += '[%s]' % (char_class,) | |
| 104 | |
| 105 # Skip to the end ] | |
| 106 i = inner_i | |
| 107 else: | |
| 108 pat += re.escape(char) | |
| 109 i += 1 | |
| 110 | |
| 111 # Join each chunk with the dir separator | |
| 112 if not last_chunk: | |
| 113 pat += sep | |
| 114 | |
| 115 pat += r'\Z' | |
| 116 return re.compile(pat, flags=re.MULTILINE|re.DOTALL) | |
| 117 | |
| 118 | |
| 119 class InfoCommon: | |
| 120 tag_build = None | |
| 121 tag_date = None | |
| 122 | |
| 123 @property | |
| 124 def name(self): | |
| 125 return safe_name(self.distribution.get_name()) | |
| 126 | |
| 127 def tagged_version(self): | |
| 128 version = self.distribution.get_version() | |
| 129 # egg_info may be called more than once for a distribution, | |
| 130 # in which case the version string already contains all tags. | |
| 131 if self.vtags and version.endswith(self.vtags): | |
| 132 return safe_version(version) | |
| 133 return safe_version(version + self.vtags) | |
| 134 | |
| 135 def tags(self): | |
| 136 version = '' | |
| 137 if self.tag_build: | |
| 138 version += self.tag_build | |
| 139 if self.tag_date: | |
| 140 version += time.strftime("-%Y%m%d") | |
| 141 return version | |
| 142 vtags = property(tags) | |
| 143 | |
| 144 | |
| 145 class egg_info(InfoCommon, Command): | |
| 146 description = "create a distribution's .egg-info directory" | |
| 147 | |
| 148 user_options = [ | |
| 149 ('egg-base=', 'e', "directory containing .egg-info directories" | |
| 150 " (default: top of the source tree)"), | |
| 151 ('tag-date', 'd', "Add date stamp (e.g. 20050528) to version number"), | |
| 152 ('tag-build=', 'b', "Specify explicit tag to add to version number"), | |
| 153 ('no-date', 'D', "Don't include date stamp [default]"), | |
| 154 ] | |
| 155 | |
| 156 boolean_options = ['tag-date'] | |
| 157 negative_opt = { | |
| 158 'no-date': 'tag-date', | |
| 159 } | |
| 160 | |
| 161 def initialize_options(self): | |
| 162 self.egg_base = None | |
| 163 self.egg_name = None | |
| 164 self.egg_info = None | |
| 165 self.egg_version = None | |
| 166 self.broken_egg_info = False | |
| 167 | |
| 168 #################################### | |
| 169 # allow the 'tag_svn_revision' to be detected and | |
| 170 # set, supporting sdists built on older Setuptools. | |
| 171 @property | |
| 172 def tag_svn_revision(self): | |
| 173 pass | |
| 174 | |
| 175 @tag_svn_revision.setter | |
| 176 def tag_svn_revision(self, value): | |
| 177 pass | |
| 178 #################################### | |
| 179 | |
| 180 def save_version_info(self, filename): | |
| 181 """ | |
| 182 Materialize the value of date into the | |
| 183 build tag. Install build keys in a deterministic order | |
| 184 to avoid arbitrary reordering on subsequent builds. | |
| 185 """ | |
| 186 egg_info = collections.OrderedDict() | |
| 187 # follow the order these keys would have been added | |
| 188 # when PYTHONHASHSEED=0 | |
| 189 egg_info['tag_build'] = self.tags() | |
| 190 egg_info['tag_date'] = 0 | |
| 191 edit_config(filename, dict(egg_info=egg_info)) | |
| 192 | |
| 193 def finalize_options(self): | |
| 194 # Note: we need to capture the current value returned | |
| 195 # by `self.tagged_version()`, so we can later update | |
| 196 # `self.distribution.metadata.version` without | |
| 197 # repercussions. | |
| 198 self.egg_name = self.name | |
| 199 self.egg_version = self.tagged_version() | |
| 200 parsed_version = parse_version(self.egg_version) | |
| 201 | |
| 202 try: | |
| 203 is_version = isinstance(parsed_version, packaging.version.Version) | |
| 204 spec = ( | |
| 205 "%s==%s" if is_version else "%s===%s" | |
| 206 ) | |
| 207 list( | |
| 208 parse_requirements(spec % (self.egg_name, self.egg_version)) | |
| 209 ) | |
| 210 except ValueError: | |
| 211 raise distutils.errors.DistutilsOptionError( | |
| 212 "Invalid distribution name or version syntax: %s-%s" % | |
| 213 (self.egg_name, self.egg_version) | |
| 214 ) | |
| 215 | |
| 216 if self.egg_base is None: | |
| 217 dirs = self.distribution.package_dir | |
| 218 self.egg_base = (dirs or {}).get('', os.curdir) | |
| 219 | |
| 220 self.ensure_dirname('egg_base') | |
| 221 self.egg_info = to_filename(self.egg_name) + '.egg-info' | |
| 222 if self.egg_base != os.curdir: | |
| 223 self.egg_info = os.path.join(self.egg_base, self.egg_info) | |
| 224 if '-' in self.egg_name: | |
| 225 self.check_broken_egg_info() | |
| 226 | |
| 227 # Set package version for the benefit of dumber commands | |
| 228 # (e.g. sdist, bdist_wininst, etc.) | |
| 229 # | |
| 230 self.distribution.metadata.version = self.egg_version | |
| 231 | |
| 232 # If we bootstrapped around the lack of a PKG-INFO, as might be the | |
| 233 # case in a fresh checkout, make sure that any special tags get added | |
| 234 # to the version info | |
| 235 # | |
| 236 pd = self.distribution._patched_dist | |
| 237 if pd is not None and pd.key == self.egg_name.lower(): | |
| 238 pd._version = self.egg_version | |
| 239 pd._parsed_version = parse_version(self.egg_version) | |
| 240 self.distribution._patched_dist = None | |
| 241 | |
| 242 def write_or_delete_file(self, what, filename, data, force=False): | |
| 243 """Write `data` to `filename` or delete if empty | |
| 244 | |
| 245 If `data` is non-empty, this routine is the same as ``write_file()``. | |
| 246 If `data` is empty but not ``None``, this is the same as calling | |
| 247 ``delete_file(filename)`. If `data` is ``None``, then this is a no-op | |
| 248 unless `filename` exists, in which case a warning is issued about the | |
| 249 orphaned file (if `force` is false), or deleted (if `force` is true). | |
| 250 """ | |
| 251 if data: | |
| 252 self.write_file(what, filename, data) | |
| 253 elif os.path.exists(filename): | |
| 254 if data is None and not force: | |
| 255 log.warn( | |
| 256 "%s not set in setup(), but %s exists", what, filename | |
| 257 ) | |
| 258 return | |
| 259 else: | |
| 260 self.delete_file(filename) | |
| 261 | |
| 262 def write_file(self, what, filename, data): | |
| 263 """Write `data` to `filename` (if not a dry run) after announcing it | |
| 264 | |
| 265 `what` is used in a log message to identify what is being written | |
| 266 to the file. | |
| 267 """ | |
| 268 log.info("writing %s to %s", what, filename) | |
| 269 if six.PY3: | |
| 270 data = data.encode("utf-8") | |
| 271 if not self.dry_run: | |
| 272 f = open(filename, 'wb') | |
| 273 f.write(data) | |
| 274 f.close() | |
| 275 | |
| 276 def delete_file(self, filename): | |
| 277 """Delete `filename` (if not a dry run) after announcing it""" | |
| 278 log.info("deleting %s", filename) | |
| 279 if not self.dry_run: | |
| 280 os.unlink(filename) | |
| 281 | |
| 282 def run(self): | |
| 283 self.mkpath(self.egg_info) | |
| 284 os.utime(self.egg_info, None) | |
| 285 installer = self.distribution.fetch_build_egg | |
| 286 for ep in iter_entry_points('egg_info.writers'): | |
| 287 ep.require(installer=installer) | |
| 288 writer = ep.resolve() | |
| 289 writer(self, ep.name, os.path.join(self.egg_info, ep.name)) | |
| 290 | |
| 291 # Get rid of native_libs.txt if it was put there by older bdist_egg | |
| 292 nl = os.path.join(self.egg_info, "native_libs.txt") | |
| 293 if os.path.exists(nl): | |
| 294 self.delete_file(nl) | |
| 295 | |
| 296 self.find_sources() | |
| 297 | |
| 298 def find_sources(self): | |
| 299 """Generate SOURCES.txt manifest file""" | |
| 300 manifest_filename = os.path.join(self.egg_info, "SOURCES.txt") | |
| 301 mm = manifest_maker(self.distribution) | |
| 302 mm.manifest = manifest_filename | |
| 303 mm.run() | |
| 304 self.filelist = mm.filelist | |
| 305 | |
| 306 def check_broken_egg_info(self): | |
| 307 bei = self.egg_name + '.egg-info' | |
| 308 if self.egg_base != os.curdir: | |
| 309 bei = os.path.join(self.egg_base, bei) | |
| 310 if os.path.exists(bei): | |
| 311 log.warn( | |
| 312 "-" * 78 + '\n' | |
| 313 "Note: Your current .egg-info directory has a '-' in its name;" | |
| 314 '\nthis will not work correctly with "setup.py develop".\n\n' | |
| 315 'Please rename %s to %s to correct this problem.\n' + '-' * 78, | |
| 316 bei, self.egg_info | |
| 317 ) | |
| 318 self.broken_egg_info = self.egg_info | |
| 319 self.egg_info = bei # make it work for now | |
| 320 | |
| 321 | |
| 322 class FileList(_FileList): | |
| 323 # Implementations of the various MANIFEST.in commands | |
| 324 | |
| 325 def process_template_line(self, line): | |
| 326 # Parse the line: split it up, make sure the right number of words | |
| 327 # is there, and return the relevant words. 'action' is always | |
| 328 # defined: it's the first word of the line. Which of the other | |
| 329 # three are defined depends on the action; it'll be either | |
| 330 # patterns, (dir and patterns), or (dir_pattern). | |
| 331 (action, patterns, dir, dir_pattern) = self._parse_template_line(line) | |
| 332 | |
| 333 # OK, now we know that the action is valid and we have the | |
| 334 # right number of words on the line for that action -- so we | |
| 335 # can proceed with minimal error-checking. | |
| 336 if action == 'include': | |
| 337 self.debug_print("include " + ' '.join(patterns)) | |
| 338 for pattern in patterns: | |
| 339 if not self.include(pattern): | |
| 340 log.warn("warning: no files found matching '%s'", pattern) | |
| 341 | |
| 342 elif action == 'exclude': | |
| 343 self.debug_print("exclude " + ' '.join(patterns)) | |
| 344 for pattern in patterns: | |
| 345 if not self.exclude(pattern): | |
| 346 log.warn(("warning: no previously-included files " | |
| 347 "found matching '%s'"), pattern) | |
| 348 | |
| 349 elif action == 'global-include': | |
| 350 self.debug_print("global-include " + ' '.join(patterns)) | |
| 351 for pattern in patterns: | |
| 352 if not self.global_include(pattern): | |
| 353 log.warn(("warning: no files found matching '%s' " | |
| 354 "anywhere in distribution"), pattern) | |
| 355 | |
| 356 elif action == 'global-exclude': | |
| 357 self.debug_print("global-exclude " + ' '.join(patterns)) | |
| 358 for pattern in patterns: | |
| 359 if not self.global_exclude(pattern): | |
| 360 log.warn(("warning: no previously-included files matching " | |
| 361 "'%s' found anywhere in distribution"), | |
| 362 pattern) | |
| 363 | |
| 364 elif action == 'recursive-include': | |
| 365 self.debug_print("recursive-include %s %s" % | |
| 366 (dir, ' '.join(patterns))) | |
| 367 for pattern in patterns: | |
| 368 if not self.recursive_include(dir, pattern): | |
| 369 log.warn(("warning: no files found matching '%s' " | |
| 370 "under directory '%s'"), | |
| 371 pattern, dir) | |
| 372 | |
| 373 elif action == 'recursive-exclude': | |
| 374 self.debug_print("recursive-exclude %s %s" % | |
| 375 (dir, ' '.join(patterns))) | |
| 376 for pattern in patterns: | |
| 377 if not self.recursive_exclude(dir, pattern): | |
| 378 log.warn(("warning: no previously-included files matching " | |
| 379 "'%s' found under directory '%s'"), | |
| 380 pattern, dir) | |
| 381 | |
| 382 elif action == 'graft': | |
| 383 self.debug_print("graft " + dir_pattern) | |
| 384 if not self.graft(dir_pattern): | |
| 385 log.warn("warning: no directories found matching '%s'", | |
| 386 dir_pattern) | |
| 387 | |
| 388 elif action == 'prune': | |
| 389 self.debug_print("prune " + dir_pattern) | |
| 390 if not self.prune(dir_pattern): | |
| 391 log.warn(("no previously-included directories found " | |
| 392 "matching '%s'"), dir_pattern) | |
| 393 | |
| 394 else: | |
| 395 raise DistutilsInternalError( | |
| 396 "this cannot happen: invalid action '%s'" % action) | |
| 397 | |
| 398 def _remove_files(self, predicate): | |
| 399 """ | |
| 400 Remove all files from the file list that match the predicate. | |
| 401 Return True if any matching files were removed | |
| 402 """ | |
| 403 found = False | |
| 404 for i in range(len(self.files) - 1, -1, -1): | |
| 405 if predicate(self.files[i]): | |
| 406 self.debug_print(" removing " + self.files[i]) | |
| 407 del self.files[i] | |
| 408 found = True | |
| 409 return found | |
| 410 | |
| 411 def include(self, pattern): | |
| 412 """Include files that match 'pattern'.""" | |
| 413 found = [f for f in glob(pattern) if not os.path.isdir(f)] | |
| 414 self.extend(found) | |
| 415 return bool(found) | |
| 416 | |
| 417 def exclude(self, pattern): | |
| 418 """Exclude files that match 'pattern'.""" | |
| 419 match = translate_pattern(pattern) | |
| 420 return self._remove_files(match.match) | |
| 421 | |
| 422 def recursive_include(self, dir, pattern): | |
| 423 """ | |
| 424 Include all files anywhere in 'dir/' that match the pattern. | |
| 425 """ | |
| 426 full_pattern = os.path.join(dir, '**', pattern) | |
| 427 found = [f for f in glob(full_pattern, recursive=True) | |
| 428 if not os.path.isdir(f)] | |
| 429 self.extend(found) | |
| 430 return bool(found) | |
| 431 | |
| 432 def recursive_exclude(self, dir, pattern): | |
| 433 """ | |
| 434 Exclude any file anywhere in 'dir/' that match the pattern. | |
| 435 """ | |
| 436 match = translate_pattern(os.path.join(dir, '**', pattern)) | |
| 437 return self._remove_files(match.match) | |
| 438 | |
| 439 def graft(self, dir): | |
| 440 """Include all files from 'dir/'.""" | |
| 441 found = [ | |
| 442 item | |
| 443 for match_dir in glob(dir) | |
| 444 for item in distutils.filelist.findall(match_dir) | |
| 445 ] | |
| 446 self.extend(found) | |
| 447 return bool(found) | |
| 448 | |
| 449 def prune(self, dir): | |
| 450 """Filter out files from 'dir/'.""" | |
| 451 match = translate_pattern(os.path.join(dir, '**')) | |
| 452 return self._remove_files(match.match) | |
| 453 | |
| 454 def global_include(self, pattern): | |
| 455 """ | |
| 456 Include all files anywhere in the current directory that match the | |
| 457 pattern. This is very inefficient on large file trees. | |
| 458 """ | |
| 459 if self.allfiles is None: | |
| 460 self.findall() | |
| 461 match = translate_pattern(os.path.join('**', pattern)) | |
| 462 found = [f for f in self.allfiles if match.match(f)] | |
| 463 self.extend(found) | |
| 464 return bool(found) | |
| 465 | |
| 466 def global_exclude(self, pattern): | |
| 467 """ | |
| 468 Exclude all files anywhere that match the pattern. | |
| 469 """ | |
| 470 match = translate_pattern(os.path.join('**', pattern)) | |
| 471 return self._remove_files(match.match) | |
| 472 | |
| 473 def append(self, item): | |
| 474 if item.endswith('\r'): # Fix older sdists built on Windows | |
| 475 item = item[:-1] | |
| 476 path = convert_path(item) | |
| 477 | |
| 478 if self._safe_path(path): | |
| 479 self.files.append(path) | |
| 480 | |
| 481 def extend(self, paths): | |
| 482 self.files.extend(filter(self._safe_path, paths)) | |
| 483 | |
| 484 def _repair(self): | |
| 485 """ | |
| 486 Replace self.files with only safe paths | |
| 487 | |
| 488 Because some owners of FileList manipulate the underlying | |
| 489 ``files`` attribute directly, this method must be called to | |
| 490 repair those paths. | |
| 491 """ | |
| 492 self.files = list(filter(self._safe_path, self.files)) | |
| 493 | |
| 494 def _safe_path(self, path): | |
| 495 enc_warn = "'%s' not %s encodable -- skipping" | |
| 496 | |
| 497 # To avoid accidental trans-codings errors, first to unicode | |
| 498 u_path = unicode_utils.filesys_decode(path) | |
| 499 if u_path is None: | |
| 500 log.warn("'%s' in unexpected encoding -- skipping" % path) | |
| 501 return False | |
| 502 | |
| 503 # Must ensure utf-8 encodability | |
| 504 utf8_path = unicode_utils.try_encode(u_path, "utf-8") | |
| 505 if utf8_path is None: | |
| 506 log.warn(enc_warn, path, 'utf-8') | |
| 507 return False | |
| 508 | |
| 509 try: | |
| 510 # accept is either way checks out | |
| 511 if os.path.exists(u_path) or os.path.exists(utf8_path): | |
| 512 return True | |
| 513 # this will catch any encode errors decoding u_path | |
| 514 except UnicodeEncodeError: | |
| 515 log.warn(enc_warn, path, sys.getfilesystemencoding()) | |
| 516 | |
| 517 | |
| 518 class manifest_maker(sdist): | |
| 519 template = "MANIFEST.in" | |
| 520 | |
| 521 def initialize_options(self): | |
| 522 self.use_defaults = 1 | |
| 523 self.prune = 1 | |
| 524 self.manifest_only = 1 | |
| 525 self.force_manifest = 1 | |
| 526 | |
| 527 def finalize_options(self): | |
| 528 pass | |
| 529 | |
| 530 def run(self): | |
| 531 self.filelist = FileList() | |
| 532 if not os.path.exists(self.manifest): | |
| 533 self.write_manifest() # it must exist so it'll get in the list | |
| 534 self.add_defaults() | |
| 535 if os.path.exists(self.template): | |
| 536 self.read_template() | |
| 537 self.prune_file_list() | |
| 538 self.filelist.sort() | |
| 539 self.filelist.remove_duplicates() | |
| 540 self.write_manifest() | |
| 541 | |
| 542 def _manifest_normalize(self, path): | |
| 543 path = unicode_utils.filesys_decode(path) | |
| 544 return path.replace(os.sep, '/') | |
| 545 | |
| 546 def write_manifest(self): | |
| 547 """ | |
| 548 Write the file list in 'self.filelist' to the manifest file | |
| 549 named by 'self.manifest'. | |
| 550 """ | |
| 551 self.filelist._repair() | |
| 552 | |
| 553 # Now _repairs should encodability, but not unicode | |
| 554 files = [self._manifest_normalize(f) for f in self.filelist.files] | |
| 555 msg = "writing manifest file '%s'" % self.manifest | |
| 556 self.execute(write_file, (self.manifest, files), msg) | |
| 557 | |
| 558 def warn(self, msg): | |
| 559 if not self._should_suppress_warning(msg): | |
| 560 sdist.warn(self, msg) | |
| 561 | |
| 562 @staticmethod | |
| 563 def _should_suppress_warning(msg): | |
| 564 """ | |
| 565 suppress missing-file warnings from sdist | |
| 566 """ | |
| 567 return re.match(r"standard file .*not found", msg) | |
| 568 | |
| 569 def add_defaults(self): | |
| 570 sdist.add_defaults(self) | |
| 571 self.check_license() | |
| 572 self.filelist.append(self.template) | |
| 573 self.filelist.append(self.manifest) | |
| 574 rcfiles = list(walk_revctrl()) | |
| 575 if rcfiles: | |
| 576 self.filelist.extend(rcfiles) | |
| 577 elif os.path.exists(self.manifest): | |
| 578 self.read_manifest() | |
| 579 | |
| 580 if os.path.exists("setup.py"): | |
| 581 # setup.py should be included by default, even if it's not | |
| 582 # the script called to create the sdist | |
| 583 self.filelist.append("setup.py") | |
| 584 | |
| 585 ei_cmd = self.get_finalized_command('egg_info') | |
| 586 self.filelist.graft(ei_cmd.egg_info) | |
| 587 | |
| 588 def prune_file_list(self): | |
| 589 build = self.get_finalized_command('build') | |
| 590 base_dir = self.distribution.get_fullname() | |
| 591 self.filelist.prune(build.build_base) | |
| 592 self.filelist.prune(base_dir) | |
| 593 sep = re.escape(os.sep) | |
| 594 self.filelist.exclude_pattern(r'(^|' + sep + r')(RCS|CVS|\.svn)' + sep, | |
| 595 is_regex=1) | |
| 596 | |
| 597 | |
| 598 def write_file(filename, contents): | |
| 599 """Create a file with the specified name and write 'contents' (a | |
| 600 sequence of strings without line terminators) to it. | |
| 601 """ | |
| 602 contents = "\n".join(contents) | |
| 603 | |
| 604 # assuming the contents has been vetted for utf-8 encoding | |
| 605 contents = contents.encode("utf-8") | |
| 606 | |
| 607 with open(filename, "wb") as f: # always write POSIX-style manifest | |
| 608 f.write(contents) | |
| 609 | |
| 610 | |
| 611 def write_pkg_info(cmd, basename, filename): | |
| 612 log.info("writing %s", filename) | |
| 613 if not cmd.dry_run: | |
| 614 metadata = cmd.distribution.metadata | |
| 615 metadata.version, oldver = cmd.egg_version, metadata.version | |
| 616 metadata.name, oldname = cmd.egg_name, metadata.name | |
| 617 | |
| 618 try: | |
| 619 # write unescaped data to PKG-INFO, so older pkg_resources | |
| 620 # can still parse it | |
| 621 metadata.write_pkg_info(cmd.egg_info) | |
| 622 finally: | |
| 623 metadata.name, metadata.version = oldname, oldver | |
| 624 | |
| 625 safe = getattr(cmd.distribution, 'zip_safe', None) | |
| 626 | |
| 627 bdist_egg.write_safety_flag(cmd.egg_info, safe) | |
| 628 | |
| 629 | |
| 630 def warn_depends_obsolete(cmd, basename, filename): | |
| 631 if os.path.exists(filename): | |
| 632 log.warn( | |
| 633 "WARNING: 'depends.txt' is not used by setuptools 0.6!\n" | |
| 634 "Use the install_requires/extras_require setup() args instead." | |
| 635 ) | |
| 636 | |
| 637 | |
| 638 def _write_requirements(stream, reqs): | |
| 639 lines = yield_lines(reqs or ()) | |
| 640 append_cr = lambda line: line + '\n' | |
| 641 lines = map(append_cr, lines) | |
| 642 stream.writelines(lines) | |
| 643 | |
| 644 | |
| 645 def write_requirements(cmd, basename, filename): | |
| 646 dist = cmd.distribution | |
| 647 data = six.StringIO() | |
| 648 _write_requirements(data, dist.install_requires) | |
| 649 extras_require = dist.extras_require or {} | |
| 650 for extra in sorted(extras_require): | |
| 651 data.write('\n[{extra}]\n'.format(**vars())) | |
| 652 _write_requirements(data, extras_require[extra]) | |
| 653 cmd.write_or_delete_file("requirements", filename, data.getvalue()) | |
| 654 | |
| 655 | |
| 656 def write_setup_requirements(cmd, basename, filename): | |
| 657 data = io.StringIO() | |
| 658 _write_requirements(data, cmd.distribution.setup_requires) | |
| 659 cmd.write_or_delete_file("setup-requirements", filename, data.getvalue()) | |
| 660 | |
| 661 | |
| 662 def write_toplevel_names(cmd, basename, filename): | |
| 663 pkgs = dict.fromkeys( | |
| 664 [ | |
| 665 k.split('.', 1)[0] | |
| 666 for k in cmd.distribution.iter_distribution_names() | |
| 667 ] | |
| 668 ) | |
| 669 cmd.write_file("top-level names", filename, '\n'.join(sorted(pkgs)) + '\n') | |
| 670 | |
| 671 | |
| 672 def overwrite_arg(cmd, basename, filename): | |
| 673 write_arg(cmd, basename, filename, True) | |
| 674 | |
| 675 | |
| 676 def write_arg(cmd, basename, filename, force=False): | |
| 677 argname = os.path.splitext(basename)[0] | |
| 678 value = getattr(cmd.distribution, argname, None) | |
| 679 if value is not None: | |
| 680 value = '\n'.join(value) + '\n' | |
| 681 cmd.write_or_delete_file(argname, filename, value, force) | |
| 682 | |
| 683 | |
| 684 def write_entries(cmd, basename, filename): | |
| 685 ep = cmd.distribution.entry_points | |
| 686 | |
| 687 if isinstance(ep, six.string_types) or ep is None: | |
| 688 data = ep | |
| 689 elif ep is not None: | |
| 690 data = [] | |
| 691 for section, contents in sorted(ep.items()): | |
| 692 if not isinstance(contents, six.string_types): | |
| 693 contents = EntryPoint.parse_group(section, contents) | |
| 694 contents = '\n'.join(sorted(map(str, contents.values()))) | |
| 695 data.append('[%s]\n%s\n\n' % (section, contents)) | |
| 696 data = ''.join(data) | |
| 697 | |
| 698 cmd.write_or_delete_file('entry points', filename, data, True) | |
| 699 | |
| 700 | |
| 701 def get_pkg_info_revision(): | |
| 702 """ | |
| 703 Get a -r### off of PKG-INFO Version in case this is an sdist of | |
| 704 a subversion revision. | |
| 705 """ | |
| 706 warnings.warn("get_pkg_info_revision is deprecated.", EggInfoDeprecationWarning) | |
| 707 if os.path.exists('PKG-INFO'): | |
| 708 with io.open('PKG-INFO') as f: | |
| 709 for line in f: | |
| 710 match = re.match(r"Version:.*-r(\d+)\s*$", line) | |
| 711 if match: | |
| 712 return int(match.group(1)) | |
| 713 return 0 | |
| 714 | |
| 715 | |
| 716 class EggInfoDeprecationWarning(SetuptoolsDeprecationWarning): | |
| 717 """Class for warning about deprecations in eggInfo in setupTools. Not ignored by default, unlike DeprecationWarning.""" |
