PageRenderTime 45ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/setuptools/command/sdist.py

https://bitbucket.org/mumak/distribute
Python | 262 lines | 193 code | 62 blank | 7 comment | 33 complexity | f87ad32782e336e477a0b518115a539f MD5 | raw file
  1. from distutils.command.sdist import sdist as _sdist
  2. from distutils.util import convert_path
  3. from distutils import log
  4. import os, re, sys, pkg_resources
  5. from glob import glob
  6. entities = [
  7. ("&lt;","<"), ("&gt;", ">"), ("&quot;", '"'), ("&apos;", "'"),
  8. ("&amp;", "&")
  9. ]
  10. def unescape(data):
  11. for old,new in entities:
  12. data = data.replace(old,new)
  13. return data
  14. def re_finder(pattern, postproc=None):
  15. def find(dirname, filename):
  16. f = open(filename,'rU')
  17. data = f.read()
  18. f.close()
  19. for match in pattern.finditer(data):
  20. path = match.group(1)
  21. if postproc:
  22. path = postproc(path)
  23. yield joinpath(dirname,path)
  24. return find
  25. def joinpath(prefix,suffix):
  26. if not prefix:
  27. return suffix
  28. return os.path.join(prefix,suffix)
  29. def walk_revctrl(dirname=''):
  30. """Find all files under revision control"""
  31. for ep in pkg_resources.iter_entry_points('setuptools.file_finders'):
  32. for item in ep.load()(dirname):
  33. yield item
  34. def _default_revctrl(dirname=''):
  35. for path, finder in finders:
  36. path = joinpath(dirname,path)
  37. if os.path.isfile(path):
  38. for path in finder(dirname,path):
  39. if os.path.isfile(path):
  40. yield path
  41. elif os.path.isdir(path):
  42. for item in _default_revctrl(path):
  43. yield item
  44. def externals_finder(dirname, filename):
  45. """Find any 'svn:externals' directories"""
  46. found = False
  47. f = open(filename,'rt')
  48. for line in iter(f.readline, ''): # can't use direct iter!
  49. parts = line.split()
  50. if len(parts)==2:
  51. kind,length = parts
  52. data = f.read(int(length))
  53. if kind=='K' and data=='svn:externals':
  54. found = True
  55. elif kind=='V' and found:
  56. f.close()
  57. break
  58. else:
  59. f.close()
  60. return
  61. for line in data.splitlines():
  62. parts = line.split()
  63. if parts:
  64. yield joinpath(dirname, parts[0])
  65. entries_pattern = re.compile(r'name="([^"]+)"(?![^>]+deleted="true")', re.I)
  66. def entries_finder(dirname, filename):
  67. f = open(filename,'rU')
  68. data = f.read()
  69. f.close()
  70. if data.startswith('10') or data.startswith('9') or data.startswith('8'):
  71. for record in map(str.splitlines, data.split('\n\x0c\n')[1:]):
  72. # subversion 1.6/1.5/1.4
  73. if not record or len(record)>=6 and record[5]=="delete":
  74. continue # skip deleted
  75. yield joinpath(dirname, record[0])
  76. elif data.startswith('<?xml'):
  77. for match in entries_pattern.finditer(data):
  78. yield joinpath(dirname,unescape(match.group(1)))
  79. else:
  80. log.warn("unrecognized .svn/entries format in %s", dirname)
  81. finders = [
  82. (convert_path('CVS/Entries'),
  83. re_finder(re.compile(r"^\w?/([^/]+)/", re.M))),
  84. (convert_path('.svn/entries'), entries_finder),
  85. (convert_path('.svn/dir-props'), externals_finder),
  86. (convert_path('.svn/dir-prop-base'), externals_finder), # svn 1.4
  87. ]
  88. class sdist(_sdist):
  89. """Smart sdist that finds anything supported by revision control"""
  90. user_options = [
  91. ('formats=', None,
  92. "formats for source distribution (comma-separated list)"),
  93. ('keep-temp', 'k',
  94. "keep the distribution tree around after creating " +
  95. "archive file(s)"),
  96. ('dist-dir=', 'd',
  97. "directory to put the source distribution archive(s) in "
  98. "[default: dist]"),
  99. ]
  100. negative_opt = {}
  101. def run(self):
  102. self.run_command('egg_info')
  103. ei_cmd = self.get_finalized_command('egg_info')
  104. self.filelist = ei_cmd.filelist
  105. self.filelist.append(os.path.join(ei_cmd.egg_info,'SOURCES.txt'))
  106. self.check_readme()
  107. self.check_metadata()
  108. self.make_distribution()
  109. dist_files = getattr(self.distribution,'dist_files',[])
  110. for file in self.archive_files:
  111. data = ('sdist', '', file)
  112. if data not in dist_files:
  113. dist_files.append(data)
  114. def add_defaults(self):
  115. standards = [('README', 'README.rst', 'README.txt'),
  116. self.distribution.script_name]
  117. for fn in standards:
  118. if isinstance(fn, tuple):
  119. alts = fn
  120. got_it = 0
  121. for fn in alts:
  122. if os.path.exists(fn):
  123. got_it = 1
  124. self.filelist.append(fn)
  125. break
  126. if not got_it:
  127. self.warn("standard file not found: should have one of " +
  128. ', '.join(alts))
  129. else:
  130. if os.path.exists(fn):
  131. self.filelist.append(fn)
  132. else:
  133. self.warn("standard file '%s' not found" % fn)
  134. optional = ['test/test*.py', 'setup.cfg']
  135. for pattern in optional:
  136. files = filter(os.path.isfile, glob(pattern))
  137. if files:
  138. self.filelist.extend(files)
  139. # getting python files
  140. if self.distribution.has_pure_modules():
  141. build_py = self.get_finalized_command('build_py')
  142. self.filelist.extend(build_py.get_source_files())
  143. if self.distribution.has_ext_modules():
  144. build_ext = self.get_finalized_command('build_ext')
  145. self.filelist.extend(build_ext.get_source_files())
  146. if self.distribution.has_c_libraries():
  147. build_clib = self.get_finalized_command('build_clib')
  148. self.filelist.extend(build_clib.get_source_files())
  149. if self.distribution.has_scripts():
  150. build_scripts = self.get_finalized_command('build_scripts')
  151. self.filelist.extend(build_scripts.get_source_files())
  152. def __read_template_hack(self):
  153. # This grody hack closes the template file (MANIFEST.in) if an
  154. # exception occurs during read_template.
  155. # Doing so prevents an error when easy_install attempts to delete the
  156. # file.
  157. try:
  158. _sdist.read_template(self)
  159. except:
  160. sys.exc_info()[2].tb_next.tb_frame.f_locals['template'].close()
  161. raise
  162. # Beginning with Python 2.7.2, 3.1.4, and 3.2.1, this leaky file handle
  163. # has been fixed, so only override the method if we're using an earlier
  164. # Python.
  165. if (
  166. sys.version_info < (2,7,2)
  167. or (3,0) <= sys.version_info < (3,1,4)
  168. or (3,2) <= sys.version_info < (3,2,1)
  169. ):
  170. read_template = __read_template_hack
  171. def check_readme(self):
  172. alts = ("README", "README.txt")
  173. for f in alts:
  174. if os.path.exists(f):
  175. return
  176. else:
  177. self.warn(
  178. "standard file not found: should have one of " +', '.join(alts)
  179. )
  180. def make_release_tree(self, base_dir, files):
  181. _sdist.make_release_tree(self, base_dir, files)
  182. # Save any egg_info command line options used to create this sdist
  183. dest = os.path.join(base_dir, 'setup.cfg')
  184. if hasattr(os,'link') and os.path.exists(dest):
  185. # unlink and re-copy, since it might be hard-linked, and
  186. # we don't want to change the source version
  187. os.unlink(dest)
  188. self.copy_file('setup.cfg', dest)
  189. self.get_finalized_command('egg_info').save_version_info(dest)
  190. #