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 |
"""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 |
#
|