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