PageRenderTime 44ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/env/lib/python3.3/site-packages/setuptools/command/egg_info.py

https://github.com/wantsomechocolate/MosaicMaker
Python | 489 lines | 486 code | 1 blank | 2 comment | 3 complexity | 9b7a44f70950e890d8f745bc62c33eb1 MD5 | raw file
  1. """setuptools.command.egg_info
  2. Create a distribution's .egg-info directory and contents"""
  3. # This module should be kept compatible with Python 2.3
  4. import os, re, sys
  5. from setuptools import Command
  6. from distutils.errors import *
  7. from distutils import log
  8. from setuptools.command.sdist import sdist
  9. from setuptools.compat import basestring
  10. from distutils.util import convert_path
  11. from distutils.filelist import FileList as _FileList
  12. from pkg_resources import parse_requirements, safe_name, parse_version, \
  13. safe_version, yield_lines, EntryPoint, iter_entry_points, to_filename
  14. from setuptools.command.sdist import walk_revctrl
  15. class egg_info(Command):
  16. description = "create a distribution's .egg-info directory"
  17. user_options = [
  18. ('egg-base=', 'e', "directory containing .egg-info directories"
  19. " (default: top of the source tree)"),
  20. ('tag-svn-revision', 'r',
  21. "Add subversion revision ID to version number"),
  22. ('tag-date', 'd', "Add date stamp (e.g. 20050528) to version number"),
  23. ('tag-build=', 'b', "Specify explicit tag to add to version number"),
  24. ('no-svn-revision', 'R',
  25. "Don't add subversion revision ID [default]"),
  26. ('no-date', 'D', "Don't include date stamp [default]"),
  27. ]
  28. boolean_options = ['tag-date', 'tag-svn-revision']
  29. negative_opt = {'no-svn-revision': 'tag-svn-revision',
  30. 'no-date': 'tag-date'}
  31. def initialize_options(self):
  32. self.egg_name = None
  33. self.egg_version = None
  34. self.egg_base = None
  35. self.egg_info = None
  36. self.tag_build = None
  37. self.tag_svn_revision = 0
  38. self.tag_date = 0
  39. self.broken_egg_info = False
  40. self.vtags = None
  41. def save_version_info(self, filename):
  42. from setuptools.command.setopt import edit_config
  43. edit_config(
  44. filename,
  45. {'egg_info':
  46. {'tag_svn_revision':0, 'tag_date': 0, 'tag_build': self.tags()}
  47. }
  48. )
  49. def finalize_options (self):
  50. self.egg_name = safe_name(self.distribution.get_name())
  51. self.vtags = self.tags()
  52. self.egg_version = self.tagged_version()
  53. try:
  54. list(
  55. parse_requirements('%s==%s' % (self.egg_name,self.egg_version))
  56. )
  57. except ValueError:
  58. raise DistutilsOptionError(
  59. "Invalid distribution name or version syntax: %s-%s" %
  60. (self.egg_name,self.egg_version)
  61. )
  62. if self.egg_base is None:
  63. dirs = self.distribution.package_dir
  64. self.egg_base = (dirs or {}).get('',os.curdir)
  65. self.ensure_dirname('egg_base')
  66. self.egg_info = to_filename(self.egg_name)+'.egg-info'
  67. if self.egg_base != os.curdir:
  68. self.egg_info = os.path.join(self.egg_base, self.egg_info)
  69. if '-' in self.egg_name: self.check_broken_egg_info()
  70. # Set package version for the benefit of dumber commands
  71. # (e.g. sdist, bdist_wininst, etc.)
  72. #
  73. self.distribution.metadata.version = self.egg_version
  74. # If we bootstrapped around the lack of a PKG-INFO, as might be the
  75. # case in a fresh checkout, make sure that any special tags get added
  76. # to the version info
  77. #
  78. pd = self.distribution._patched_dist
  79. if pd is not None and pd.key==self.egg_name.lower():
  80. pd._version = self.egg_version
  81. pd._parsed_version = parse_version(self.egg_version)
  82. self.distribution._patched_dist = None
  83. def write_or_delete_file(self, what, filename, data, force=False):
  84. """Write `data` to `filename` or delete if empty
  85. If `data` is non-empty, this routine is the same as ``write_file()``.
  86. If `data` is empty but not ``None``, this is the same as calling
  87. ``delete_file(filename)`. If `data` is ``None``, then this is a no-op
  88. unless `filename` exists, in which case a warning is issued about the
  89. orphaned file (if `force` is false), or deleted (if `force` is true).
  90. """
  91. if data:
  92. self.write_file(what, filename, data)
  93. elif os.path.exists(filename):
  94. if data is None and not force:
  95. log.warn(
  96. "%s not set in setup(), but %s exists", what, filename
  97. )
  98. return
  99. else:
  100. self.delete_file(filename)
  101. def write_file(self, what, filename, data):
  102. """Write `data` to `filename` (if not a dry run) after announcing it
  103. `what` is used in a log message to identify what is being written
  104. to the file.
  105. """
  106. log.info("writing %s to %s", what, filename)
  107. if sys.version_info >= (3,):
  108. data = data.encode("utf-8")
  109. if not self.dry_run:
  110. f = open(filename, 'wb')
  111. f.write(data)
  112. f.close()
  113. def delete_file(self, filename):
  114. """Delete `filename` (if not a dry run) after announcing it"""
  115. log.info("deleting %s", filename)
  116. if not self.dry_run:
  117. os.unlink(filename)
  118. def tagged_version(self):
  119. version = self.distribution.get_version()
  120. # egg_info may be called more than once for a distribution,
  121. # in which case the version string already contains all tags.
  122. if self.vtags and version.endswith(self.vtags):
  123. return safe_version(version)
  124. return safe_version(version + self.vtags)
  125. def run(self):
  126. self.mkpath(self.egg_info)
  127. installer = self.distribution.fetch_build_egg
  128. for ep in iter_entry_points('egg_info.writers'):
  129. writer = ep.load(installer=installer)
  130. writer(self, ep.name, os.path.join(self.egg_info,ep.name))
  131. # Get rid of native_libs.txt if it was put there by older bdist_egg
  132. nl = os.path.join(self.egg_info, "native_libs.txt")
  133. if os.path.exists(nl):
  134. self.delete_file(nl)
  135. self.find_sources()
  136. def tags(self):
  137. version = ''
  138. if self.tag_build:
  139. version+=self.tag_build
  140. if self.tag_svn_revision and (
  141. os.path.exists('.svn') or os.path.exists('PKG-INFO')
  142. ): version += '-r%s' % self.get_svn_revision()
  143. if self.tag_date:
  144. import time; version += time.strftime("-%Y%m%d")
  145. return version
  146. @staticmethod
  147. def get_svn_revision():
  148. revision = 0
  149. urlre = re.compile('url="([^"]+)"')
  150. revre = re.compile('committed-rev="(\d+)"')
  151. for base,dirs,files in os.walk(os.curdir):
  152. if '.svn' not in dirs:
  153. dirs[:] = []
  154. continue # no sense walking uncontrolled subdirs
  155. dirs.remove('.svn')
  156. f = open(os.path.join(base,'.svn','entries'))
  157. data = f.read()
  158. f.close()
  159. if data.startswith('<?xml'):
  160. dirurl = urlre.search(data).group(1) # get repository URL
  161. localrev = max([int(m.group(1)) for m in revre.finditer(data)]+[0])
  162. else:
  163. try: svnver = int(data.splitlines()[0])
  164. except: svnver=-1
  165. if svnver<8:
  166. log.warn("unrecognized .svn/entries format; skipping %s", base)
  167. dirs[:] = []
  168. continue
  169. data = list(map(str.splitlines,data.split('\n\x0c\n')))
  170. del data[0][0] # get rid of the '8' or '9' or '10'
  171. dirurl = data[0][3]
  172. localrev = max([int(d[9]) for d in data if len(d)>9 and d[9]]+[0])
  173. if base==os.curdir:
  174. base_url = dirurl+'/' # save the root url
  175. elif not dirurl.startswith(base_url):
  176. dirs[:] = []
  177. continue # not part of the same svn tree, skip it
  178. revision = max(revision, localrev)
  179. return str(revision or get_pkg_info_revision())
  180. def find_sources(self):
  181. """Generate SOURCES.txt manifest file"""
  182. manifest_filename = os.path.join(self.egg_info,"SOURCES.txt")
  183. mm = manifest_maker(self.distribution)
  184. mm.manifest = manifest_filename
  185. mm.run()
  186. self.filelist = mm.filelist
  187. def check_broken_egg_info(self):
  188. bei = self.egg_name+'.egg-info'
  189. if self.egg_base != os.curdir:
  190. bei = os.path.join(self.egg_base, bei)
  191. if os.path.exists(bei):
  192. log.warn(
  193. "-"*78+'\n'
  194. "Note: Your current .egg-info directory has a '-' in its name;"
  195. '\nthis will not work correctly with "setup.py develop".\n\n'
  196. 'Please rename %s to %s to correct this problem.\n'+'-'*78,
  197. bei, self.egg_info
  198. )
  199. self.broken_egg_info = self.egg_info
  200. self.egg_info = bei # make it work for now
  201. class FileList(_FileList):
  202. """File list that accepts only existing, platform-independent paths"""
  203. def append(self, item):
  204. if item.endswith('\r'): # Fix older sdists built on Windows
  205. item = item[:-1]
  206. path = convert_path(item)
  207. if sys.version_info >= (3,):
  208. try:
  209. if os.path.exists(path) or os.path.exists(path.encode('utf-8')):
  210. self.files.append(path)
  211. except UnicodeEncodeError:
  212. # Accept UTF-8 filenames even if LANG=C
  213. if os.path.exists(path.encode('utf-8')):
  214. self.files.append(path)
  215. else:
  216. log.warn("'%s' not %s encodable -- skipping", path,
  217. sys.getfilesystemencoding())
  218. else:
  219. if os.path.exists(path):
  220. self.files.append(path)
  221. class manifest_maker(sdist):
  222. template = "MANIFEST.in"
  223. def initialize_options (self):
  224. self.use_defaults = 1
  225. self.prune = 1
  226. self.manifest_only = 1
  227. self.force_manifest = 1
  228. def finalize_options(self):
  229. pass
  230. def run(self):
  231. self.filelist = FileList()
  232. if not os.path.exists(self.manifest):
  233. self.write_manifest() # it must exist so it'll get in the list
  234. self.filelist.findall()
  235. self.add_defaults()
  236. if os.path.exists(self.template):
  237. self.read_template()
  238. self.prune_file_list()
  239. self.filelist.sort()
  240. self.filelist.remove_duplicates()
  241. self.write_manifest()
  242. def write_manifest (self):
  243. """Write the file list in 'self.filelist' (presumably as filled in
  244. by 'add_defaults()' and 'read_template()') to the manifest file
  245. named by 'self.manifest'.
  246. """
  247. # The manifest must be UTF-8 encodable. See #303.
  248. if sys.version_info >= (3,):
  249. files = []
  250. for file in self.filelist.files:
  251. try:
  252. file.encode("utf-8")
  253. except UnicodeEncodeError:
  254. log.warn("'%s' not UTF-8 encodable -- skipping" % file)
  255. else:
  256. files.append(file)
  257. self.filelist.files = files
  258. files = self.filelist.files
  259. if os.sep!='/':
  260. files = [f.replace(os.sep,'/') for f in files]
  261. self.execute(write_file, (self.manifest, files),
  262. "writing manifest file '%s'" % self.manifest)
  263. def warn(self, msg): # suppress missing-file warnings from sdist
  264. if not msg.startswith("standard file not found:"):
  265. sdist.warn(self, msg)
  266. def add_defaults(self):
  267. sdist.add_defaults(self)
  268. self.filelist.append(self.template)
  269. self.filelist.append(self.manifest)
  270. rcfiles = list(walk_revctrl())
  271. if rcfiles:
  272. self.filelist.extend(rcfiles)
  273. elif os.path.exists(self.manifest):
  274. self.read_manifest()
  275. ei_cmd = self.get_finalized_command('egg_info')
  276. self.filelist.include_pattern("*", prefix=ei_cmd.egg_info)
  277. def prune_file_list (self):
  278. build = self.get_finalized_command('build')
  279. base_dir = self.distribution.get_fullname()
  280. self.filelist.exclude_pattern(None, prefix=build.build_base)
  281. self.filelist.exclude_pattern(None, prefix=base_dir)
  282. sep = re.escape(os.sep)
  283. self.filelist.exclude_pattern(sep+r'(RCS|CVS|\.svn)'+sep, is_regex=1)
  284. def write_file (filename, contents):
  285. """Create a file with the specified name and write 'contents' (a
  286. sequence of strings without line terminators) to it.
  287. """
  288. contents = "\n".join(contents)
  289. if sys.version_info >= (3,):
  290. contents = contents.encode("utf-8")
  291. f = open(filename, "wb") # always write POSIX-style manifest
  292. f.write(contents)
  293. f.close()
  294. def write_pkg_info(cmd, basename, filename):
  295. log.info("writing %s", filename)
  296. if not cmd.dry_run:
  297. metadata = cmd.distribution.metadata
  298. metadata.version, oldver = cmd.egg_version, metadata.version
  299. metadata.name, oldname = cmd.egg_name, metadata.name
  300. try:
  301. # write unescaped data to PKG-INFO, so older pkg_resources
  302. # can still parse it
  303. metadata.write_pkg_info(cmd.egg_info)
  304. finally:
  305. metadata.name, metadata.version = oldname, oldver
  306. safe = getattr(cmd.distribution,'zip_safe',None)
  307. from setuptools.command import bdist_egg
  308. bdist_egg.write_safety_flag(cmd.egg_info, safe)
  309. def warn_depends_obsolete(cmd, basename, filename):
  310. if os.path.exists(filename):
  311. log.warn(
  312. "WARNING: 'depends.txt' is not used by setuptools 0.6!\n"
  313. "Use the install_requires/extras_require setup() args instead."
  314. )
  315. def write_requirements(cmd, basename, filename):
  316. dist = cmd.distribution
  317. data = ['\n'.join(yield_lines(dist.install_requires or ()))]
  318. for extra,reqs in (dist.extras_require or {}).items():
  319. data.append('\n\n[%s]\n%s' % (extra, '\n'.join(yield_lines(reqs))))
  320. cmd.write_or_delete_file("requirements", filename, ''.join(data))
  321. def write_toplevel_names(cmd, basename, filename):
  322. pkgs = dict.fromkeys(
  323. [k.split('.',1)[0]
  324. for k in cmd.distribution.iter_distribution_names()
  325. ]
  326. )
  327. cmd.write_file("top-level names", filename, '\n'.join(pkgs)+'\n')
  328. def overwrite_arg(cmd, basename, filename):
  329. write_arg(cmd, basename, filename, True)
  330. def write_arg(cmd, basename, filename, force=False):
  331. argname = os.path.splitext(basename)[0]
  332. value = getattr(cmd.distribution, argname, None)
  333. if value is not None:
  334. value = '\n'.join(value)+'\n'
  335. cmd.write_or_delete_file(argname, filename, value, force)
  336. def write_entries(cmd, basename, filename):
  337. ep = cmd.distribution.entry_points
  338. if isinstance(ep,basestring) or ep is None:
  339. data = ep
  340. elif ep is not None:
  341. data = []
  342. for section, contents in ep.items():
  343. if not isinstance(contents,basestring):
  344. contents = EntryPoint.parse_group(section, contents)
  345. contents = '\n'.join(map(str,contents.values()))
  346. data.append('[%s]\n%s\n\n' % (section,contents))
  347. data = ''.join(data)
  348. cmd.write_or_delete_file('entry points', filename, data, True)
  349. def get_pkg_info_revision():
  350. # See if we can get a -r### off of PKG-INFO, in case this is an sdist of
  351. # a subversion revision
  352. #
  353. if os.path.exists('PKG-INFO'):
  354. f = open('PKG-INFO','rU')
  355. for line in f:
  356. match = re.match(r"Version:.*-r(\d+)\s*$", line)
  357. if match:
  358. return int(match.group(1))
  359. f.close()
  360. return 0
  361. #