root / env / lib / python2.7 / site-packages / distribute-0.6.19-py2.7.egg / setuptools / command / egg_info.py @ 1a305335
History | View | Annotate | Download (14 KB)
1 | 1a305335 | officers | """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, sys |
||
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 sys.version_info >= (3,): |
||
152 | data = data.encode("utf-8")
|
||
153 | if not self.dry_run: |
||
154 | f = open(filename, 'wb') |
||
155 | f.write(data) |
||
156 | f.close() |
||
157 | |||
158 | def delete_file(self, filename): |
||
159 | """Delete `filename` (if not a dry run) after announcing it"""
|
||
160 | log.info("deleting %s", filename)
|
||
161 | if not self.dry_run: |
||
162 | os.unlink(filename) |
||
163 | |||
164 | def tagged_version(self): |
||
165 | return safe_version(self.distribution.get_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 | writer = ep.load(installer=installer) |
||
172 | writer(self, ep.name, os.path.join(self.egg_info,ep.name)) |
||
173 | |||
174 | # Get rid of native_libs.txt if it was put there by older bdist_egg
|
||
175 | nl = os.path.join(self.egg_info, "native_libs.txt") |
||
176 | if os.path.exists(nl):
|
||
177 | self.delete_file(nl)
|
||
178 | |||
179 | self.find_sources()
|
||
180 | |||
181 | def tags(self): |
||
182 | version = ''
|
||
183 | if self.tag_build: |
||
184 | version+=self.tag_build
|
||
185 | if self.tag_svn_revision and ( |
||
186 | os.path.exists('.svn') or os.path.exists('PKG-INFO') |
||
187 | ): version += '-r%s' % self.get_svn_revision() |
||
188 | if self.tag_date: |
||
189 | import time; version += time.strftime("-%Y%m%d") |
||
190 | return version
|
||
191 | |||
192 | |||
193 | |||
194 | |||
195 | |||
196 | |||
197 | |||
198 | |||
199 | |||
200 | |||
201 | |||
202 | |||
203 | |||
204 | |||
205 | |||
206 | |||
207 | |||
208 | def get_svn_revision(self): |
||
209 | revision = 0
|
||
210 | urlre = re.compile('url="([^"]+)"')
|
||
211 | revre = re.compile('committed-rev="(\d+)"')
|
||
212 | |||
213 | for base,dirs,files in os.walk(os.curdir): |
||
214 | if '.svn' not in dirs: |
||
215 | dirs[:] = [] |
||
216 | continue # no sense walking uncontrolled subdirs |
||
217 | dirs.remove('.svn')
|
||
218 | f = open(os.path.join(base,'.svn','entries')) |
||
219 | data = f.read() |
||
220 | f.close() |
||
221 | |||
222 | if data.startswith('10') or data.startswith('9') or data.startswith('8'): |
||
223 | data = map(str.splitlines,data.split('\n\x0c\n')) |
||
224 | del data[0][0] # get rid of the '8' or '9' or '10' |
||
225 | dirurl = data[0][3] |
||
226 | localrev = max([int(d[9]) for d in data if len(d)>9 and d[9]]+[0]) |
||
227 | elif data.startswith('<?xml'): |
||
228 | dirurl = urlre.search(data).group(1) # get repository URL |
||
229 | localrev = max([int(m.group(1)) for m in revre.finditer(data)]+[0]) |
||
230 | else:
|
||
231 | log.warn("unrecognized .svn/entries format; skipping %s", base)
|
||
232 | dirs[:] = [] |
||
233 | continue
|
||
234 | if base==os.curdir:
|
||
235 | base_url = dirurl+'/' # save the root url |
||
236 | elif not dirurl.startswith(base_url): |
||
237 | dirs[:] = [] |
||
238 | continue # not part of the same svn tree, skip it |
||
239 | revision = max(revision, localrev)
|
||
240 | |||
241 | return str(revision or get_pkg_info_revision()) |
||
242 | |||
243 | |||
244 | |||
245 | |||
246 | |||
247 | |||
248 | |||
249 | def find_sources(self): |
||
250 | """Generate SOURCES.txt manifest file"""
|
||
251 | manifest_filename = os.path.join(self.egg_info,"SOURCES.txt") |
||
252 | mm = manifest_maker(self.distribution)
|
||
253 | mm.manifest = manifest_filename |
||
254 | mm.run() |
||
255 | self.filelist = mm.filelist
|
||
256 | |||
257 | def check_broken_egg_info(self): |
||
258 | bei = self.egg_name+'.egg-info' |
||
259 | if self.egg_base != os.curdir: |
||
260 | bei = os.path.join(self.egg_base, bei)
|
||
261 | if os.path.exists(bei):
|
||
262 | log.warn( |
||
263 | "-"*78+'\n' |
||
264 | "Note: Your current .egg-info directory has a '-' in its name;"
|
||
265 | '\nthis will not work correctly with "setup.py develop".\n\n'
|
||
266 | 'Please rename %s to %s to correct this problem.\n'+'-'*78, |
||
267 | bei, self.egg_info
|
||
268 | ) |
||
269 | self.broken_egg_info = self.egg_info |
||
270 | self.egg_info = bei # make it work for now |
||
271 | |||
272 | class FileList(FileList): |
||
273 | """File list that accepts only existing, platform-independent paths"""
|
||
274 | |||
275 | def append(self, item): |
||
276 | if item.endswith('\r'): # Fix older sdists built on Windows |
||
277 | item = item[:-1]
|
||
278 | path = convert_path(item) |
||
279 | if os.path.exists(path):
|
||
280 | self.files.append(path)
|
||
281 | |||
282 | |||
283 | |||
284 | |||
285 | |||
286 | |||
287 | |||
288 | |||
289 | |||
290 | class manifest_maker(sdist): |
||
291 | |||
292 | template = "MANIFEST.in"
|
||
293 | |||
294 | def initialize_options (self): |
||
295 | self.use_defaults = 1 |
||
296 | self.prune = 1 |
||
297 | self.manifest_only = 1 |
||
298 | self.force_manifest = 1 |
||
299 | |||
300 | def finalize_options(self): |
||
301 | pass
|
||
302 | |||
303 | def run(self): |
||
304 | self.filelist = FileList()
|
||
305 | if not os.path.exists(self.manifest): |
||
306 | self.write_manifest() # it must exist so it'll get in the list |
||
307 | self.filelist.findall()
|
||
308 | self.add_defaults()
|
||
309 | if os.path.exists(self.template): |
||
310 | self.read_template()
|
||
311 | self.prune_file_list()
|
||
312 | self.filelist.sort()
|
||
313 | self.filelist.remove_duplicates()
|
||
314 | self.write_manifest()
|
||
315 | |||
316 | def write_manifest (self): |
||
317 | """Write the file list in 'self.filelist' (presumably as filled in
|
||
318 | by 'add_defaults()' and 'read_template()') to the manifest file
|
||
319 | named by 'self.manifest'.
|
||
320 | """
|
||
321 | files = self.filelist.files
|
||
322 | if os.sep!='/': |
||
323 | files = [f.replace(os.sep,'/') for f in files] |
||
324 | self.execute(write_file, (self.manifest, files), |
||
325 | "writing manifest file '%s'" % self.manifest) |
||
326 | |||
327 | def warn(self, msg): # suppress missing-file warnings from sdist |
||
328 | if not msg.startswith("standard file not found:"): |
||
329 | sdist.warn(self, msg)
|
||
330 | |||
331 | def add_defaults(self): |
||
332 | sdist.add_defaults(self)
|
||
333 | self.filelist.append(self.template) |
||
334 | self.filelist.append(self.manifest) |
||
335 | rcfiles = list(walk_revctrl())
|
||
336 | if rcfiles:
|
||
337 | self.filelist.extend(rcfiles)
|
||
338 | elif os.path.exists(self.manifest): |
||
339 | self.read_manifest()
|
||
340 | ei_cmd = self.get_finalized_command('egg_info') |
||
341 | self.filelist.include_pattern("*", prefix=ei_cmd.egg_info) |
||
342 | |||
343 | def prune_file_list (self): |
||
344 | build = self.get_finalized_command('build') |
||
345 | base_dir = self.distribution.get_fullname()
|
||
346 | self.filelist.exclude_pattern(None, prefix=build.build_base) |
||
347 | self.filelist.exclude_pattern(None, prefix=base_dir) |
||
348 | sep = re.escape(os.sep) |
||
349 | self.filelist.exclude_pattern(sep+r'(RCS|CVS|\.svn)'+sep, is_regex=1) |
||
350 | |||
351 | |||
352 | def write_file (filename, contents): |
||
353 | """Create a file with the specified name and write 'contents' (a
|
||
354 | sequence of strings without line terminators) to it.
|
||
355 | """
|
||
356 | contents = "\n".join(contents)
|
||
357 | if sys.version_info >= (3,): |
||
358 | contents = contents.encode("utf-8")
|
||
359 | f = open(filename, "wb") # always write POSIX-style manifest |
||
360 | f.write(contents) |
||
361 | f.close() |
||
362 | |||
363 | |||
364 | |||
365 | |||
366 | |||
367 | |||
368 | |||
369 | |||
370 | |||
371 | |||
372 | |||
373 | |||
374 | |||
375 | def write_pkg_info(cmd, basename, filename): |
||
376 | log.info("writing %s", filename)
|
||
377 | if not cmd.dry_run: |
||
378 | metadata = cmd.distribution.metadata |
||
379 | metadata.version, oldver = cmd.egg_version, metadata.version |
||
380 | metadata.name, oldname = cmd.egg_name, metadata.name |
||
381 | try:
|
||
382 | # write unescaped data to PKG-INFO, so older pkg_resources
|
||
383 | # can still parse it
|
||
384 | metadata.write_pkg_info(cmd.egg_info) |
||
385 | finally:
|
||
386 | metadata.name, metadata.version = oldname, oldver |
||
387 | |||
388 | safe = getattr(cmd.distribution,'zip_safe',None) |
||
389 | import bdist_egg; bdist_egg.write_safety_flag(cmd.egg_info, safe) |
||
390 | |||
391 | def warn_depends_obsolete(cmd, basename, filename): |
||
392 | if os.path.exists(filename):
|
||
393 | log.warn( |
||
394 | "WARNING: 'depends.txt' is not used by setuptools 0.6!\n"
|
||
395 | "Use the install_requires/extras_require setup() args instead."
|
||
396 | ) |
||
397 | |||
398 | |||
399 | def write_requirements(cmd, basename, filename): |
||
400 | dist = cmd.distribution |
||
401 | data = ['\n'.join(yield_lines(dist.install_requires or ()))] |
||
402 | for extra,reqs in (dist.extras_require or {}).items(): |
||
403 | data.append('\n\n[%s]\n%s' % (extra, '\n'.join(yield_lines(reqs)))) |
||
404 | cmd.write_or_delete_file("requirements", filename, ''.join(data)) |
||
405 | |||
406 | def write_toplevel_names(cmd, basename, filename): |
||
407 | pkgs = dict.fromkeys(
|
||
408 | [k.split('.',1)[0] |
||
409 | for k in cmd.distribution.iter_distribution_names() |
||
410 | ] |
||
411 | ) |
||
412 | cmd.write_file("top-level names", filename, '\n'.join(pkgs)+'\n') |
||
413 | |||
414 | |||
415 | |||
416 | def overwrite_arg(cmd, basename, filename): |
||
417 | write_arg(cmd, basename, filename, True)
|
||
418 | |||
419 | def write_arg(cmd, basename, filename, force=False): |
||
420 | argname = os.path.splitext(basename)[0]
|
||
421 | value = getattr(cmd.distribution, argname, None) |
||
422 | if value is not None: |
||
423 | value = '\n'.join(value)+'\n' |
||
424 | cmd.write_or_delete_file(argname, filename, value, force) |
||
425 | |||
426 | def write_entries(cmd, basename, filename): |
||
427 | ep = cmd.distribution.entry_points |
||
428 | |||
429 | if isinstance(ep,basestring) or ep is None: |
||
430 | data = ep |
||
431 | elif ep is not None: |
||
432 | data = [] |
||
433 | for section, contents in ep.items(): |
||
434 | if not isinstance(contents,basestring): |
||
435 | contents = EntryPoint.parse_group(section, contents) |
||
436 | contents = '\n'.join(map(str,contents.values())) |
||
437 | data.append('[%s]\n%s\n\n' % (section,contents))
|
||
438 | data = ''.join(data)
|
||
439 | |||
440 | cmd.write_or_delete_file('entry points', filename, data, True) |
||
441 | |||
442 | def get_pkg_info_revision(): |
||
443 | # See if we can get a -r### off of PKG-INFO, in case this is an sdist of
|
||
444 | # a subversion revision
|
||
445 | #
|
||
446 | if os.path.exists('PKG-INFO'): |
||
447 | f = open('PKG-INFO','rU') |
||
448 | for line in f: |
||
449 | match = re.match(r"Version:.*-r(\d+)\s*$", line)
|
||
450 | if match:
|
||
451 | return int(match.group(1)) |
||
452 | f.close() |
||
453 | return 0 |
||
454 | |||
455 | |||
456 | |||
457 | # |