root / env / lib / python2.7 / site-packages / distribute-0.6.19-py2.7.egg / setuptools / command / easy_install.py @ 1a305335
History | View | Annotate | Download (68.5 KB)
1 |
#!python
|
---|---|
2 |
"""\
|
3 |
Easy Install
|
4 |
------------
|
5 |
|
6 |
A tool for doing automatic download/extract/build of distutils-based Python
|
7 |
packages. For detailed documentation, see the accompanying EasyInstall.txt
|
8 |
file, or visit the `EasyInstall home page`__.
|
9 |
|
10 |
__ http://packages.python.org/distribute/easy_install.html
|
11 |
|
12 |
"""
|
13 |
import sys, os.path, zipimport, shutil, tempfile, zipfile, re, stat, random |
14 |
from glob import glob |
15 |
from setuptools import Command, _dont_write_bytecode |
16 |
from setuptools.sandbox import run_setup |
17 |
from distutils import log, dir_util |
18 |
from distutils.util import get_platform |
19 |
from distutils.util import convert_path, subst_vars |
20 |
from distutils.sysconfig import get_python_lib, get_config_vars |
21 |
from distutils.errors import DistutilsArgError, DistutilsOptionError, \ |
22 |
DistutilsError, DistutilsPlatformError |
23 |
from distutils.command.install import INSTALL_SCHEMES, SCHEME_KEYS |
24 |
from setuptools.archive_util import unpack_archive |
25 |
from setuptools.package_index import PackageIndex |
26 |
from setuptools.package_index import URL_SCHEME |
27 |
from setuptools.command import bdist_egg, egg_info |
28 |
from pkg_resources import yield_lines, normalize_path, resource_string, \ |
29 |
ensure_directory, get_distribution, find_distributions, \ |
30 |
Environment, Requirement, Distribution, \ |
31 |
PathMetadata, EggMetadata, WorkingSet, \ |
32 |
DistributionNotFound, VersionConflict, \ |
33 |
DEVELOP_DIST
|
34 |
|
35 |
sys_executable = os.path.normpath(sys.executable) |
36 |
|
37 |
__all__ = [ |
38 |
'samefile', 'easy_install', 'PthDistributions', 'extract_wininst_cfg', |
39 |
'main', 'get_exe_prefixes', |
40 |
] |
41 |
|
42 |
import site |
43 |
HAS_USER_SITE = not sys.version < "2.6" and site.ENABLE_USER_SITE |
44 |
|
45 |
def samefile(p1,p2): |
46 |
if hasattr(os.path,'samefile') and ( |
47 |
os.path.exists(p1) and os.path.exists(p2)
|
48 |
): |
49 |
return os.path.samefile(p1,p2)
|
50 |
return (
|
51 |
os.path.normpath(os.path.normcase(p1)) == |
52 |
os.path.normpath(os.path.normcase(p2)) |
53 |
) |
54 |
|
55 |
if sys.version_info <= (3,): |
56 |
def _to_ascii(s): |
57 |
return s
|
58 |
def isascii(s): |
59 |
try:
|
60 |
unicode(s, 'ascii') |
61 |
return True |
62 |
except UnicodeError: |
63 |
return False |
64 |
else:
|
65 |
def _to_ascii(s): |
66 |
return s.encode('ascii') |
67 |
def isascii(s): |
68 |
try:
|
69 |
s.encode('ascii')
|
70 |
return True |
71 |
except UnicodeError: |
72 |
return False |
73 |
|
74 |
class easy_install(Command): |
75 |
"""Manage a download/build/install process"""
|
76 |
description = "Find/get/install Python packages"
|
77 |
command_consumes_arguments = True
|
78 |
|
79 |
user_options = [ |
80 |
('prefix=', None, "installation prefix"), |
81 |
("zip-ok", "z", "install package as a zipfile"), |
82 |
("multi-version", "m", "make apps have to require() a version"), |
83 |
("upgrade", "U", "force upgrade (searches PyPI for latest versions)"), |
84 |
("install-dir=", "d", "install package to DIR"), |
85 |
("script-dir=", "s", "install scripts to DIR"), |
86 |
("exclude-scripts", "x", "Don't install scripts"), |
87 |
("always-copy", "a", "Copy all needed packages to install dir"), |
88 |
("index-url=", "i", "base URL of Python Package Index"), |
89 |
("find-links=", "f", "additional URL(s) to search for packages"), |
90 |
("delete-conflicting", "D", "no longer needed; don't use this"), |
91 |
("ignore-conflicts-at-my-risk", None, |
92 |
"no longer needed; don't use this"),
|
93 |
("build-directory=", "b", |
94 |
"download/extract/build in DIR; keep the results"),
|
95 |
('optimize=', 'O', |
96 |
"also compile with optimization: -O1 for \"python -O\", "
|
97 |
"-O2 for \"python -OO\", and -O0 to disable [default: -O0]"),
|
98 |
('record=', None, |
99 |
"filename in which to record list of installed files"),
|
100 |
('always-unzip', 'Z', "don't install as a zipfile, no matter what"), |
101 |
('site-dirs=','S',"list of directories where .pth files work"), |
102 |
('editable', 'e', "Install specified packages in editable form"), |
103 |
('no-deps', 'N', "don't install dependencies"), |
104 |
('allow-hosts=', 'H', "pattern(s) that hostnames must match"), |
105 |
('local-snapshots-ok', 'l', "allow building eggs from local checkouts"), |
106 |
('version', None, "print version information and exit"), |
107 |
('no-find-links', None, |
108 |
"Don't load find-links defined in packages being installed")
|
109 |
] |
110 |
boolean_options = [ |
111 |
'zip-ok', 'multi-version', 'exclude-scripts', 'upgrade', 'always-copy', |
112 |
'delete-conflicting', 'ignore-conflicts-at-my-risk', 'editable', |
113 |
'no-deps', 'local-snapshots-ok', 'version' |
114 |
] |
115 |
|
116 |
if HAS_USER_SITE:
|
117 |
user_options.append(('user', None, |
118 |
"install in user site-package '%s'" % site.USER_SITE))
|
119 |
boolean_options.append('user')
|
120 |
|
121 |
|
122 |
negative_opt = {'always-unzip': 'zip-ok'} |
123 |
create_index = PackageIndex |
124 |
|
125 |
def initialize_options(self): |
126 |
if HAS_USER_SITE:
|
127 |
whereami = os.path.abspath(__file__) |
128 |
self.user = whereami.startswith(site.USER_SITE)
|
129 |
else:
|
130 |
self.user = 0 |
131 |
|
132 |
self.zip_ok = self.local_snapshots_ok = None |
133 |
self.install_dir = self.script_dir = self.exclude_scripts = None |
134 |
self.index_url = None |
135 |
self.find_links = None |
136 |
self.build_directory = None |
137 |
self.args = None |
138 |
self.optimize = self.record = None |
139 |
self.upgrade = self.always_copy = self.multi_version = None |
140 |
self.editable = self.no_deps = self.allow_hosts = None |
141 |
self.root = self.prefix = self.no_report = None |
142 |
self.version = None |
143 |
self.install_purelib = None # for pure module distributions |
144 |
self.install_platlib = None # non-pure (dists w/ extensions) |
145 |
self.install_headers = None # for C/C++ headers |
146 |
self.install_lib = None # set to either purelib or platlib |
147 |
self.install_scripts = None |
148 |
self.install_data = None |
149 |
self.install_base = None |
150 |
self.install_platbase = None |
151 |
if HAS_USER_SITE:
|
152 |
self.install_userbase = site.USER_BASE
|
153 |
self.install_usersite = site.USER_SITE
|
154 |
else:
|
155 |
self.install_userbase = None |
156 |
self.install_usersite = None |
157 |
self.no_find_links = None |
158 |
|
159 |
# Options not specifiable via command line
|
160 |
self.package_index = None |
161 |
self.pth_file = self.always_copy_from = None |
162 |
self.delete_conflicting = None |
163 |
self.ignore_conflicts_at_my_risk = None |
164 |
self.site_dirs = None |
165 |
self.installed_projects = {}
|
166 |
self.sitepy_installed = False |
167 |
# Always read easy_install options, even if we are subclassed, or have
|
168 |
# an independent instance created. This ensures that defaults will
|
169 |
# always come from the standard configuration file(s)' "easy_install"
|
170 |
# section, even if this is a "develop" or "install" command, or some
|
171 |
# other embedding.
|
172 |
self._dry_run = None |
173 |
self.verbose = self.distribution.verbose |
174 |
self.distribution._set_command_options(
|
175 |
self, self.distribution.get_option_dict('easy_install') |
176 |
) |
177 |
|
178 |
def delete_blockers(self, blockers): |
179 |
for filename in blockers: |
180 |
if os.path.exists(filename) or os.path.islink(filename): |
181 |
log.info("Deleting %s", filename)
|
182 |
if not self.dry_run: |
183 |
if os.path.isdir(filename) and not os.path.islink(filename): |
184 |
rmtree(filename) |
185 |
else:
|
186 |
os.unlink(filename) |
187 |
|
188 |
def finalize_options(self): |
189 |
if self.version: |
190 |
print 'distribute %s' % get_distribution('distribute').version |
191 |
sys.exit() |
192 |
|
193 |
py_version = sys.version.split()[0]
|
194 |
prefix, exec_prefix = get_config_vars('prefix', 'exec_prefix') |
195 |
|
196 |
self.config_vars = {'dist_name': self.distribution.get_name(), |
197 |
'dist_version': self.distribution.get_version(), |
198 |
'dist_fullname': self.distribution.get_fullname(), |
199 |
'py_version': py_version,
|
200 |
'py_version_short': py_version[0:3], |
201 |
'py_version_nodot': py_version[0] + py_version[2], |
202 |
'sys_prefix': prefix,
|
203 |
'prefix': prefix,
|
204 |
'sys_exec_prefix': exec_prefix,
|
205 |
'exec_prefix': exec_prefix,
|
206 |
# Only python 3.2+ has abiflags
|
207 |
'abiflags': getattr(sys, 'abiflags', ''), |
208 |
} |
209 |
|
210 |
if HAS_USER_SITE:
|
211 |
self.config_vars['userbase'] = self.install_userbase |
212 |
self.config_vars['usersite'] = self.install_usersite |
213 |
|
214 |
# fix the install_dir if "--user" was used
|
215 |
#XXX: duplicate of the code in the setup command
|
216 |
if self.user and HAS_USER_SITE: |
217 |
self.create_home_path()
|
218 |
if self.install_userbase is None: |
219 |
raise DistutilsPlatformError(
|
220 |
"User base directory is not specified")
|
221 |
self.install_base = self.install_platbase = self.install_userbase |
222 |
if os.name == 'posix': |
223 |
self.select_scheme("unix_user") |
224 |
else:
|
225 |
self.select_scheme(os.name + "_user") |
226 |
|
227 |
self.expand_basedirs()
|
228 |
self.expand_dirs()
|
229 |
|
230 |
self._expand('install_dir','script_dir','build_directory','site_dirs') |
231 |
# If a non-default installation directory was specified, default the
|
232 |
# script directory to match it.
|
233 |
if self.script_dir is None: |
234 |
self.script_dir = self.install_dir |
235 |
|
236 |
if self.no_find_links is None: |
237 |
self.no_find_links = False |
238 |
|
239 |
# Let install_dir get set by install_lib command, which in turn
|
240 |
# gets its info from the install command, and takes into account
|
241 |
# --prefix and --home and all that other crud.
|
242 |
self.set_undefined_options('install_lib', |
243 |
('install_dir','install_dir') |
244 |
) |
245 |
# Likewise, set default script_dir from 'install_scripts.install_dir'
|
246 |
self.set_undefined_options('install_scripts', |
247 |
('install_dir', 'script_dir') |
248 |
) |
249 |
|
250 |
if self.user and self.install_purelib: |
251 |
self.install_dir = self.install_purelib |
252 |
self.script_dir = self.install_scripts |
253 |
# default --record from the install command
|
254 |
self.set_undefined_options('install', ('record', 'record')) |
255 |
normpath = map(normalize_path, sys.path)
|
256 |
self.all_site_dirs = get_site_dirs()
|
257 |
if self.site_dirs is not None: |
258 |
site_dirs = [ |
259 |
os.path.expanduser(s.strip()) for s in self.site_dirs.split(',') |
260 |
] |
261 |
for d in site_dirs: |
262 |
if not os.path.isdir(d): |
263 |
log.warn("%s (in --site-dirs) does not exist", d)
|
264 |
elif normalize_path(d) not in normpath: |
265 |
raise DistutilsOptionError(
|
266 |
d+" (in --site-dirs) is not on sys.path"
|
267 |
) |
268 |
else:
|
269 |
self.all_site_dirs.append(normalize_path(d))
|
270 |
if not self.editable: self.check_site_dir() |
271 |
self.index_url = self.index_url or "http://pypi.python.org/simple" |
272 |
self.shadow_path = self.all_site_dirs[:] |
273 |
for path_item in self.install_dir, normalize_path(self.script_dir): |
274 |
if path_item not in self.shadow_path: |
275 |
self.shadow_path.insert(0, path_item) |
276 |
|
277 |
if self.allow_hosts is not None: |
278 |
hosts = [s.strip() for s in self.allow_hosts.split(',')] |
279 |
else:
|
280 |
hosts = ['*']
|
281 |
if self.package_index is None: |
282 |
self.package_index = self.create_index( |
283 |
self.index_url, search_path = self.shadow_path, hosts=hosts, |
284 |
) |
285 |
self.local_index = Environment(self.shadow_path+sys.path) |
286 |
|
287 |
if self.find_links is not None: |
288 |
if isinstance(self.find_links, basestring): |
289 |
self.find_links = self.find_links.split() |
290 |
else:
|
291 |
self.find_links = []
|
292 |
if self.local_snapshots_ok: |
293 |
self.package_index.scan_egg_links(self.shadow_path+sys.path) |
294 |
if not self.no_find_links: |
295 |
self.package_index.add_find_links(self.find_links) |
296 |
self.set_undefined_options('install_lib', ('optimize','optimize')) |
297 |
if not isinstance(self.optimize,int): |
298 |
try:
|
299 |
self.optimize = int(self.optimize) |
300 |
if not (0 <= self.optimize <= 2): raise ValueError |
301 |
except ValueError: |
302 |
raise DistutilsOptionError("--optimize must be 0, 1, or 2") |
303 |
|
304 |
if self.delete_conflicting and self.ignore_conflicts_at_my_risk: |
305 |
raise DistutilsOptionError(
|
306 |
"Can't use both --delete-conflicting and "
|
307 |
"--ignore-conflicts-at-my-risk at the same time"
|
308 |
) |
309 |
if self.editable and not self.build_directory: |
310 |
raise DistutilsArgError(
|
311 |
"Must specify a build directory (-b) when using --editable"
|
312 |
) |
313 |
if not self.args: |
314 |
raise DistutilsArgError(
|
315 |
"No urls, filenames, or requirements specified (see --help)")
|
316 |
|
317 |
self.outputs = []
|
318 |
|
319 |
|
320 |
def _expand_attrs(self, attrs): |
321 |
for attr in attrs: |
322 |
val = getattr(self, attr) |
323 |
if val is not None: |
324 |
if os.name == 'posix' or os.name == 'nt': |
325 |
val = os.path.expanduser(val) |
326 |
val = subst_vars(val, self.config_vars)
|
327 |
setattr(self, attr, val) |
328 |
|
329 |
def expand_basedirs(self): |
330 |
"""Calls `os.path.expanduser` on install_base, install_platbase and
|
331 |
root."""
|
332 |
self._expand_attrs(['install_base', 'install_platbase', 'root']) |
333 |
|
334 |
def expand_dirs(self): |
335 |
"""Calls `os.path.expanduser` on install dirs."""
|
336 |
self._expand_attrs(['install_purelib', 'install_platlib', |
337 |
'install_lib', 'install_headers', |
338 |
'install_scripts', 'install_data',]) |
339 |
|
340 |
def run(self): |
341 |
if self.verbose != self.distribution.verbose: |
342 |
log.set_verbosity(self.verbose)
|
343 |
try:
|
344 |
for spec in self.args: |
345 |
self.easy_install(spec, not self.no_deps) |
346 |
if self.record: |
347 |
outputs = self.outputs
|
348 |
if self.root: # strip any package prefix |
349 |
root_len = len(self.root) |
350 |
for counter in xrange(len(outputs)): |
351 |
outputs[counter] = outputs[counter][root_len:] |
352 |
from distutils import file_util |
353 |
self.execute(
|
354 |
file_util.write_file, (self.record, outputs),
|
355 |
"writing list of installed files to '%s'" %
|
356 |
self.record
|
357 |
) |
358 |
self.warn_deprecated_options()
|
359 |
finally:
|
360 |
log.set_verbosity(self.distribution.verbose)
|
361 |
|
362 |
def pseudo_tempname(self): |
363 |
"""Return a pseudo-tempname base in the install directory.
|
364 |
This code is intentionally naive; if a malicious party can write to
|
365 |
the target directory you're already in deep doodoo.
|
366 |
"""
|
367 |
try:
|
368 |
pid = os.getpid() |
369 |
except:
|
370 |
pid = random.randint(0,sys.maxint)
|
371 |
return os.path.join(self.install_dir, "test-easy-install-%s" % pid) |
372 |
|
373 |
def warn_deprecated_options(self): |
374 |
if self.delete_conflicting or self.ignore_conflicts_at_my_risk: |
375 |
log.warn( |
376 |
"Note: The -D, --delete-conflicting and"
|
377 |
" --ignore-conflicts-at-my-risk no longer have any purpose"
|
378 |
" and should not be used."
|
379 |
) |
380 |
|
381 |
def check_site_dir(self): |
382 |
"""Verify that self.install_dir is .pth-capable dir, if needed"""
|
383 |
|
384 |
instdir = normalize_path(self.install_dir)
|
385 |
pth_file = os.path.join(instdir,'easy-install.pth')
|
386 |
|
387 |
# Is it a configured, PYTHONPATH, implicit, or explicit site dir?
|
388 |
is_site_dir = instdir in self.all_site_dirs |
389 |
|
390 |
if not is_site_dir: |
391 |
# No? Then directly test whether it does .pth file processing
|
392 |
is_site_dir = self.check_pth_processing()
|
393 |
else:
|
394 |
# make sure we can write to target dir
|
395 |
testfile = self.pseudo_tempname()+'.write-test' |
396 |
test_exists = os.path.exists(testfile) |
397 |
try:
|
398 |
if test_exists: os.unlink(testfile)
|
399 |
open(testfile,'w').close() |
400 |
os.unlink(testfile) |
401 |
except (OSError,IOError): |
402 |
self.cant_write_to_target()
|
403 |
|
404 |
if not is_site_dir and not self.multi_version: |
405 |
# Can't install non-multi to non-site dir
|
406 |
raise DistutilsError(self.no_default_version_msg()) |
407 |
|
408 |
if is_site_dir:
|
409 |
if self.pth_file is None: |
410 |
self.pth_file = PthDistributions(pth_file, self.all_site_dirs) |
411 |
else:
|
412 |
self.pth_file = None |
413 |
|
414 |
PYTHONPATH = os.environ.get('PYTHONPATH','').split(os.pathsep) |
415 |
if instdir not in map(normalize_path, filter(None,PYTHONPATH)): |
416 |
# only PYTHONPATH dirs need a site.py, so pretend it's there
|
417 |
self.sitepy_installed = True |
418 |
elif self.multi_version and not os.path.exists(pth_file): |
419 |
self.sitepy_installed = True # don't need site.py in this case |
420 |
self.pth_file = None # and don't create a .pth file |
421 |
self.install_dir = instdir
|
422 |
|
423 |
def cant_write_to_target(self): |
424 |
msg = """can't create or remove files in install directory
|
425 |
|
426 |
The following error occurred while trying to add or remove files in the
|
427 |
installation directory:
|
428 |
|
429 |
%s
|
430 |
|
431 |
The installation directory you specified (via --install-dir, --prefix, or
|
432 |
the distutils default setting) was:
|
433 |
|
434 |
%s
|
435 |
""" % (sys.exc_info()[1], self.install_dir,) |
436 |
|
437 |
if not os.path.exists(self.install_dir): |
438 |
msg += """
|
439 |
This directory does not currently exist. Please create it and try again, or
|
440 |
choose a different installation directory (using the -d or --install-dir
|
441 |
option).
|
442 |
"""
|
443 |
else:
|
444 |
msg += """
|
445 |
Perhaps your account does not have write access to this directory? If the
|
446 |
installation directory is a system-owned directory, you may need to sign in
|
447 |
as the administrator or "root" account. If you do not have administrative
|
448 |
access to this machine, you may wish to choose a different installation
|
449 |
directory, preferably one that is listed in your PYTHONPATH environment
|
450 |
variable.
|
451 |
|
452 |
For information on other options, you may wish to consult the
|
453 |
documentation at:
|
454 |
|
455 |
http://packages.python.org/distribute/easy_install.html
|
456 |
|
457 |
Please make the appropriate changes for your system and try again.
|
458 |
"""
|
459 |
raise DistutilsError(msg)
|
460 |
|
461 |
|
462 |
|
463 |
|
464 |
def check_pth_processing(self): |
465 |
"""Empirically verify whether .pth files are supported in inst. dir"""
|
466 |
instdir = self.install_dir
|
467 |
log.info("Checking .pth file support in %s", instdir)
|
468 |
pth_file = self.pseudo_tempname()+".pth" |
469 |
ok_file = pth_file+'.ok'
|
470 |
ok_exists = os.path.exists(ok_file) |
471 |
try:
|
472 |
if ok_exists: os.unlink(ok_file)
|
473 |
dirname = os.path.dirname(ok_file) |
474 |
if not os.path.exists(dirname): |
475 |
os.makedirs(dirname) |
476 |
f = open(pth_file,'w') |
477 |
except (OSError,IOError): |
478 |
self.cant_write_to_target()
|
479 |
else:
|
480 |
try:
|
481 |
f.write("import os;open(%r,'w').write('OK')\n" % (ok_file,))
|
482 |
f.close(); f=None
|
483 |
executable = sys.executable |
484 |
if os.name=='nt': |
485 |
dirname,basename = os.path.split(executable) |
486 |
alt = os.path.join(dirname,'pythonw.exe')
|
487 |
if basename.lower()=='python.exe' and os.path.exists(alt): |
488 |
# use pythonw.exe to avoid opening a console window
|
489 |
executable = alt |
490 |
|
491 |
from distutils.spawn import spawn |
492 |
spawn([executable,'-E','-c','pass'],0) |
493 |
|
494 |
if os.path.exists(ok_file):
|
495 |
log.info( |
496 |
"TEST PASSED: %s appears to support .pth files",
|
497 |
instdir |
498 |
) |
499 |
return True |
500 |
finally:
|
501 |
if f: f.close()
|
502 |
if os.path.exists(ok_file): os.unlink(ok_file)
|
503 |
if os.path.exists(pth_file): os.unlink(pth_file)
|
504 |
if not self.multi_version: |
505 |
log.warn("TEST FAILED: %s does NOT support .pth files", instdir)
|
506 |
return False |
507 |
|
508 |
def install_egg_scripts(self, dist): |
509 |
"""Write all the scripts for `dist`, unless scripts are excluded"""
|
510 |
if not self.exclude_scripts and dist.metadata_isdir('scripts'): |
511 |
for script_name in dist.metadata_listdir('scripts'): |
512 |
self.install_script(
|
513 |
dist, script_name, |
514 |
dist.get_metadata('scripts/'+script_name)
|
515 |
) |
516 |
self.install_wrapper_scripts(dist)
|
517 |
|
518 |
def add_output(self, path): |
519 |
if os.path.isdir(path):
|
520 |
for base, dirs, files in os.walk(path): |
521 |
for filename in files: |
522 |
self.outputs.append(os.path.join(base,filename))
|
523 |
else:
|
524 |
self.outputs.append(path)
|
525 |
|
526 |
def not_editable(self, spec): |
527 |
if self.editable: |
528 |
raise DistutilsArgError(
|
529 |
"Invalid argument %r: you can't use filenames or URLs "
|
530 |
"with --editable (except via the --find-links option)."
|
531 |
% (spec,) |
532 |
) |
533 |
|
534 |
def check_editable(self,spec): |
535 |
if not self.editable: |
536 |
return
|
537 |
|
538 |
if os.path.exists(os.path.join(self.build_directory, spec.key)): |
539 |
raise DistutilsArgError(
|
540 |
"%r already exists in %s; can't do a checkout there" %
|
541 |
(spec.key, self.build_directory)
|
542 |
) |
543 |
|
544 |
|
545 |
|
546 |
|
547 |
|
548 |
|
549 |
def easy_install(self, spec, deps=False): |
550 |
tmpdir = tempfile.mkdtemp(prefix="easy_install-")
|
551 |
download = None
|
552 |
if not self.editable: self.install_site_py() |
553 |
|
554 |
try:
|
555 |
if not isinstance(spec,Requirement): |
556 |
if URL_SCHEME(spec):
|
557 |
# It's a url, download it to tmpdir and process
|
558 |
self.not_editable(spec)
|
559 |
download = self.package_index.download(spec, tmpdir)
|
560 |
return self.install_item(None, download, tmpdir, deps, True) |
561 |
|
562 |
elif os.path.exists(spec):
|
563 |
# Existing file or directory, just process it directly
|
564 |
self.not_editable(spec)
|
565 |
return self.install_item(None, spec, tmpdir, deps, True) |
566 |
else:
|
567 |
spec = parse_requirement_arg(spec) |
568 |
|
569 |
self.check_editable(spec)
|
570 |
dist = self.package_index.fetch_distribution(
|
571 |
spec, tmpdir, self.upgrade, self.editable, not self.always_copy, |
572 |
self.local_index
|
573 |
) |
574 |
|
575 |
if dist is None: |
576 |
msg = "Could not find suitable distribution for %r" % spec
|
577 |
if self.always_copy: |
578 |
msg+=" (--always-copy skips system and development eggs)"
|
579 |
raise DistutilsError(msg)
|
580 |
elif dist.precedence==DEVELOP_DIST:
|
581 |
# .egg-info dists don't need installing, just process deps
|
582 |
self.process_distribution(spec, dist, deps, "Using") |
583 |
return dist
|
584 |
else:
|
585 |
return self.install_item(spec, dist.location, tmpdir, deps) |
586 |
|
587 |
finally:
|
588 |
if os.path.exists(tmpdir):
|
589 |
rmtree(tmpdir) |
590 |
|
591 |
def install_item(self, spec, download, tmpdir, deps, install_needed=False): |
592 |
|
593 |
# Installation is also needed if file in tmpdir or is not an egg
|
594 |
install_needed = install_needed or self.always_copy |
595 |
install_needed = install_needed or os.path.dirname(download) == tmpdir
|
596 |
install_needed = install_needed or not download.endswith('.egg') |
597 |
install_needed = install_needed or (
|
598 |
self.always_copy_from is not None and |
599 |
os.path.dirname(normalize_path(download)) == |
600 |
normalize_path(self.always_copy_from)
|
601 |
) |
602 |
|
603 |
if spec and not install_needed: |
604 |
# at this point, we know it's a local .egg, we just don't know if
|
605 |
# it's already installed.
|
606 |
for dist in self.local_index[spec.project_name]: |
607 |
if dist.location==download:
|
608 |
break
|
609 |
else:
|
610 |
install_needed = True # it's not in the local index |
611 |
|
612 |
log.info("Processing %s", os.path.basename(download))
|
613 |
|
614 |
if install_needed:
|
615 |
dists = self.install_eggs(spec, download, tmpdir)
|
616 |
for dist in dists: |
617 |
self.process_distribution(spec, dist, deps)
|
618 |
else:
|
619 |
dists = [self.check_conflicts(self.egg_distribution(download))] |
620 |
self.process_distribution(spec, dists[0], deps, "Using") |
621 |
|
622 |
if spec is not None: |
623 |
for dist in dists: |
624 |
if dist in spec: |
625 |
return dist
|
626 |
|
627 |
|
628 |
|
629 |
def select_scheme(self, name): |
630 |
"""Sets the install directories by applying the install schemes."""
|
631 |
# it's the caller's problem if they supply a bad name!
|
632 |
scheme = INSTALL_SCHEMES[name] |
633 |
for key in SCHEME_KEYS: |
634 |
attrname = 'install_' + key
|
635 |
if getattr(self, attrname) is None: |
636 |
setattr(self, attrname, scheme[key]) |
637 |
|
638 |
|
639 |
|
640 |
|
641 |
def process_distribution(self, requirement, dist, deps=True, *info): |
642 |
self.update_pth(dist)
|
643 |
self.package_index.add(dist)
|
644 |
self.local_index.add(dist)
|
645 |
if not self.editable: |
646 |
self.install_egg_scripts(dist)
|
647 |
self.installed_projects[dist.key] = dist
|
648 |
log.info(self.installation_report(requirement, dist, *info))
|
649 |
if (dist.has_metadata('dependency_links.txt') and |
650 |
not self.no_find_links): |
651 |
self.package_index.add_find_links(
|
652 |
dist.get_metadata_lines('dependency_links.txt')
|
653 |
) |
654 |
if not deps and not self.always_copy: |
655 |
return
|
656 |
elif requirement is not None and dist.key != requirement.key: |
657 |
log.warn("Skipping dependencies for %s", dist)
|
658 |
return # XXX this is not the distribution we were looking for |
659 |
elif requirement is None or dist not in requirement: |
660 |
# if we wound up with a different version, resolve what we've got
|
661 |
distreq = dist.as_requirement() |
662 |
requirement = requirement or distreq
|
663 |
requirement = Requirement( |
664 |
distreq.project_name, distreq.specs, requirement.extras |
665 |
) |
666 |
log.info("Processing dependencies for %s", requirement)
|
667 |
try:
|
668 |
distros = WorkingSet([]).resolve( |
669 |
[requirement], self.local_index, self.easy_install |
670 |
) |
671 |
except DistributionNotFound, e:
|
672 |
raise DistutilsError(
|
673 |
"Could not find required distribution %s" % e.args
|
674 |
) |
675 |
except VersionConflict, e:
|
676 |
raise DistutilsError(
|
677 |
"Installed distribution %s conflicts with requirement %s"
|
678 |
% e.args |
679 |
) |
680 |
if self.always_copy or self.always_copy_from: |
681 |
# Force all the relevant distros to be copied or activated
|
682 |
for dist in distros: |
683 |
if dist.key not in self.installed_projects: |
684 |
self.easy_install(dist.as_requirement())
|
685 |
log.info("Finished processing dependencies for %s", requirement)
|
686 |
|
687 |
def should_unzip(self, dist): |
688 |
if self.zip_ok is not None: |
689 |
return not self.zip_ok |
690 |
if dist.has_metadata('not-zip-safe'): |
691 |
return True |
692 |
if not dist.has_metadata('zip-safe'): |
693 |
return True |
694 |
return True |
695 |
|
696 |
def maybe_move(self, spec, dist_filename, setup_base): |
697 |
dst = os.path.join(self.build_directory, spec.key)
|
698 |
if os.path.exists(dst):
|
699 |
log.warn( |
700 |
"%r already exists in %s; build directory %s will not be kept",
|
701 |
spec.key, self.build_directory, setup_base
|
702 |
) |
703 |
return setup_base
|
704 |
if os.path.isdir(dist_filename):
|
705 |
setup_base = dist_filename |
706 |
else:
|
707 |
if os.path.dirname(dist_filename)==setup_base:
|
708 |
os.unlink(dist_filename) # get it out of the tmp dir
|
709 |
contents = os.listdir(setup_base) |
710 |
if len(contents)==1: |
711 |
dist_filename = os.path.join(setup_base,contents[0])
|
712 |
if os.path.isdir(dist_filename):
|
713 |
# if the only thing there is a directory, move it instead
|
714 |
setup_base = dist_filename |
715 |
ensure_directory(dst); shutil.move(setup_base, dst) |
716 |
return dst
|
717 |
|
718 |
def install_wrapper_scripts(self, dist): |
719 |
if not self.exclude_scripts: |
720 |
for args in get_script_args(dist): |
721 |
self.write_script(*args)
|
722 |
|
723 |
|
724 |
|
725 |
def install_script(self, dist, script_name, script_text, dev_path=None): |
726 |
"""Generate a legacy script wrapper and install it"""
|
727 |
spec = str(dist.as_requirement())
|
728 |
is_script = is_python_script(script_text, script_name) |
729 |
|
730 |
if is_script and dev_path: |
731 |
script_text = get_script_header(script_text) + ( |
732 |
"# EASY-INSTALL-DEV-SCRIPT: %(spec)r,%(script_name)r\n"
|
733 |
"__requires__ = %(spec)r\n"
|
734 |
"from pkg_resources import require; require(%(spec)r)\n"
|
735 |
"del require\n"
|
736 |
"__file__ = %(dev_path)r\n"
|
737 |
"execfile(__file__)\n"
|
738 |
) % locals()
|
739 |
elif is_script:
|
740 |
script_text = get_script_header(script_text) + ( |
741 |
"# EASY-INSTALL-SCRIPT: %(spec)r,%(script_name)r\n"
|
742 |
"__requires__ = %(spec)r\n"
|
743 |
"import pkg_resources\n"
|
744 |
"pkg_resources.run_script(%(spec)r, %(script_name)r)\n"
|
745 |
) % locals()
|
746 |
self.write_script(script_name, _to_ascii(script_text), 'b') |
747 |
|
748 |
def write_script(self, script_name, contents, mode="t", blockers=()): |
749 |
"""Write an executable file to the scripts directory"""
|
750 |
self.delete_blockers( # clean up old .py/.pyw w/o a script |
751 |
[os.path.join(self.script_dir,x) for x in blockers]) |
752 |
log.info("Installing %s script to %s", script_name, self.script_dir) |
753 |
target = os.path.join(self.script_dir, script_name)
|
754 |
self.add_output(target)
|
755 |
|
756 |
if not self.dry_run: |
757 |
ensure_directory(target) |
758 |
f = open(target,"w"+mode) |
759 |
f.write(contents) |
760 |
f.close() |
761 |
chmod(target,0755)
|
762 |
|
763 |
|
764 |
|
765 |
|
766 |
def install_eggs(self, spec, dist_filename, tmpdir): |
767 |
# .egg dirs or files are already built, so just return them
|
768 |
if dist_filename.lower().endswith('.egg'): |
769 |
return [self.install_egg(dist_filename, tmpdir)] |
770 |
elif dist_filename.lower().endswith('.exe'): |
771 |
return [self.install_exe(dist_filename, tmpdir)] |
772 |
|
773 |
# Anything else, try to extract and build
|
774 |
setup_base = tmpdir |
775 |
if os.path.isfile(dist_filename) and not dist_filename.endswith('.py'): |
776 |
unpack_archive(dist_filename, tmpdir, self.unpack_progress)
|
777 |
elif os.path.isdir(dist_filename):
|
778 |
setup_base = os.path.abspath(dist_filename) |
779 |
|
780 |
if (setup_base.startswith(tmpdir) # something we downloaded |
781 |
and self.build_directory and spec is not None |
782 |
): |
783 |
setup_base = self.maybe_move(spec, dist_filename, setup_base)
|
784 |
|
785 |
# Find the setup.py file
|
786 |
setup_script = os.path.join(setup_base, 'setup.py')
|
787 |
|
788 |
if not os.path.exists(setup_script): |
789 |
setups = glob(os.path.join(setup_base, '*', 'setup.py')) |
790 |
if not setups: |
791 |
raise DistutilsError(
|
792 |
"Couldn't find a setup script in %s" % os.path.abspath(dist_filename)
|
793 |
) |
794 |
if len(setups)>1: |
795 |
raise DistutilsError(
|
796 |
"Multiple setup scripts in %s" % os.path.abspath(dist_filename)
|
797 |
) |
798 |
setup_script = setups[0]
|
799 |
|
800 |
# Now run it, and return the result
|
801 |
if self.editable: |
802 |
log.info(self.report_editable(spec, setup_script))
|
803 |
return []
|
804 |
else:
|
805 |
return self.build_and_install(setup_script, setup_base) |
806 |
|
807 |
def egg_distribution(self, egg_path): |
808 |
if os.path.isdir(egg_path):
|
809 |
metadata = PathMetadata(egg_path,os.path.join(egg_path,'EGG-INFO'))
|
810 |
else:
|
811 |
metadata = EggMetadata(zipimport.zipimporter(egg_path)) |
812 |
return Distribution.from_filename(egg_path,metadata=metadata)
|
813 |
|
814 |
def install_egg(self, egg_path, tmpdir): |
815 |
destination = os.path.join(self.install_dir,os.path.basename(egg_path))
|
816 |
destination = os.path.abspath(destination) |
817 |
if not self.dry_run: |
818 |
ensure_directory(destination) |
819 |
|
820 |
dist = self.egg_distribution(egg_path)
|
821 |
self.check_conflicts(dist)
|
822 |
if not samefile(egg_path, destination): |
823 |
if os.path.isdir(destination) and not os.path.islink(destination): |
824 |
dir_util.remove_tree(destination, dry_run=self.dry_run)
|
825 |
elif os.path.exists(destination):
|
826 |
self.execute(os.unlink,(destination,),"Removing "+destination) |
827 |
uncache_zipdir(destination) |
828 |
if os.path.isdir(egg_path):
|
829 |
if egg_path.startswith(tmpdir):
|
830 |
f,m = shutil.move, "Moving"
|
831 |
else:
|
832 |
f,m = shutil.copytree, "Copying"
|
833 |
elif self.should_unzip(dist): |
834 |
self.mkpath(destination)
|
835 |
f,m = self.unpack_and_compile, "Extracting" |
836 |
elif egg_path.startswith(tmpdir):
|
837 |
f,m = shutil.move, "Moving"
|
838 |
else:
|
839 |
f,m = shutil.copy2, "Copying"
|
840 |
|
841 |
self.execute(f, (egg_path, destination),
|
842 |
(m+" %s to %s") %
|
843 |
(os.path.basename(egg_path),os.path.dirname(destination))) |
844 |
|
845 |
self.add_output(destination)
|
846 |
return self.egg_distribution(destination) |
847 |
|
848 |
def install_exe(self, dist_filename, tmpdir): |
849 |
# See if it's valid, get data
|
850 |
cfg = extract_wininst_cfg(dist_filename) |
851 |
if cfg is None: |
852 |
raise DistutilsError(
|
853 |
"%s is not a valid distutils Windows .exe" % dist_filename
|
854 |
) |
855 |
# Create a dummy distribution object until we build the real distro
|
856 |
dist = Distribution(None,
|
857 |
project_name=cfg.get('metadata','name'), |
858 |
version=cfg.get('metadata','version'), platform=get_platform() |
859 |
) |
860 |
|
861 |
# Convert the .exe to an unpacked egg
|
862 |
egg_path = dist.location = os.path.join(tmpdir, dist.egg_name()+'.egg')
|
863 |
egg_tmp = egg_path+'.tmp'
|
864 |
egg_info = os.path.join(egg_tmp, 'EGG-INFO')
|
865 |
pkg_inf = os.path.join(egg_info, 'PKG-INFO')
|
866 |
ensure_directory(pkg_inf) # make sure EGG-INFO dir exists
|
867 |
dist._provider = PathMetadata(egg_tmp, egg_info) # XXX
|
868 |
self.exe_to_egg(dist_filename, egg_tmp)
|
869 |
|
870 |
# Write EGG-INFO/PKG-INFO
|
871 |
if not os.path.exists(pkg_inf): |
872 |
f = open(pkg_inf,'w') |
873 |
f.write('Metadata-Version: 1.0\n')
|
874 |
for k,v in cfg.items('metadata'): |
875 |
if k<>'target_version': |
876 |
f.write('%s: %s\n' % (k.replace('_','-').title(), v)) |
877 |
f.close() |
878 |
script_dir = os.path.join(egg_info,'scripts')
|
879 |
self.delete_blockers( # delete entry-point scripts to avoid duping |
880 |
[os.path.join(script_dir,args[0]) for args in get_script_args(dist)] |
881 |
) |
882 |
# Build .egg file from tmpdir
|
883 |
bdist_egg.make_zipfile( |
884 |
egg_path, egg_tmp, verbose=self.verbose, dry_run=self.dry_run |
885 |
) |
886 |
# install the .egg
|
887 |
return self.install_egg(egg_path, tmpdir) |
888 |
|
889 |
def exe_to_egg(self, dist_filename, egg_tmp): |
890 |
"""Extract a bdist_wininst to the directories an egg would use"""
|
891 |
# Check for .pth file and set up prefix translations
|
892 |
prefixes = get_exe_prefixes(dist_filename) |
893 |
to_compile = [] |
894 |
native_libs = [] |
895 |
top_level = {} |
896 |
def process(src,dst): |
897 |
s = src.lower() |
898 |
for old,new in prefixes: |
899 |
if s.startswith(old):
|
900 |
src = new+src[len(old):]
|
901 |
parts = src.split('/')
|
902 |
dst = os.path.join(egg_tmp, *parts) |
903 |
dl = dst.lower() |
904 |
if dl.endswith('.pyd') or dl.endswith('.dll'): |
905 |
parts[-1] = bdist_egg.strip_module(parts[-1]) |
906 |
top_level[os.path.splitext(parts[0])[0]] = 1 |
907 |
native_libs.append(src) |
908 |
elif dl.endswith('.py') and old!='SCRIPTS/': |
909 |
top_level[os.path.splitext(parts[0])[0]] = 1 |
910 |
to_compile.append(dst) |
911 |
return dst
|
912 |
if not src.endswith('.pth'): |
913 |
log.warn("WARNING: can't process %s", src)
|
914 |
return None |
915 |
# extract, tracking .pyd/.dll->native_libs and .py -> to_compile
|
916 |
unpack_archive(dist_filename, egg_tmp, process) |
917 |
stubs = [] |
918 |
for res in native_libs: |
919 |
if res.lower().endswith('.pyd'): # create stubs for .pyd's |
920 |
parts = res.split('/')
|
921 |
resource = parts[-1]
|
922 |
parts[-1] = bdist_egg.strip_module(parts[-1])+'.py' |
923 |
pyfile = os.path.join(egg_tmp, *parts) |
924 |
to_compile.append(pyfile); stubs.append(pyfile) |
925 |
bdist_egg.write_stub(resource, pyfile) |
926 |
self.byte_compile(to_compile) # compile .py's |
927 |
bdist_egg.write_safety_flag(os.path.join(egg_tmp,'EGG-INFO'),
|
928 |
bdist_egg.analyze_egg(egg_tmp, stubs)) # write zip-safety flag
|
929 |
|
930 |
for name in 'top_level','native_libs': |
931 |
if locals()[name]: |
932 |
txt = os.path.join(egg_tmp, 'EGG-INFO', name+'.txt') |
933 |
if not os.path.exists(txt): |
934 |
f = open(txt,'w') |
935 |
f.write('\n'.join(locals()[name])+'\n') |
936 |
f.close() |
937 |
|
938 |
def check_conflicts(self, dist): |
939 |
"""Verify that there are no conflicting "old-style" packages"""
|
940 |
|
941 |
return dist # XXX temporarily disable until new strategy is stable |
942 |
from imp import find_module, get_suffixes |
943 |
from glob import glob |
944 |
|
945 |
blockers = [] |
946 |
names = dict.fromkeys(dist._get_metadata('top_level.txt')) # XXX private attr |
947 |
|
948 |
exts = {'.pyc':1, '.pyo':1} # get_suffixes() might leave one out |
949 |
for ext,mode,typ in get_suffixes(): |
950 |
exts[ext] = 1
|
951 |
|
952 |
for path,files in expand_paths([self.install_dir]+self.all_site_dirs): |
953 |
for filename in files: |
954 |
base,ext = os.path.splitext(filename) |
955 |
if base in names: |
956 |
if not ext: |
957 |
# no extension, check for package
|
958 |
try:
|
959 |
f, filename, descr = find_module(base, [path]) |
960 |
except ImportError: |
961 |
continue
|
962 |
else:
|
963 |
if f: f.close()
|
964 |
if filename not in blockers: |
965 |
blockers.append(filename) |
966 |
elif ext in exts and base!='site': # XXX ugh |
967 |
blockers.append(os.path.join(path,filename)) |
968 |
if blockers:
|
969 |
self.found_conflicts(dist, blockers)
|
970 |
|
971 |
return dist
|
972 |
|
973 |
def found_conflicts(self, dist, blockers): |
974 |
if self.delete_conflicting: |
975 |
log.warn("Attempting to delete conflicting packages:")
|
976 |
return self.delete_blockers(blockers) |
977 |
|
978 |
msg = """\
|
979 |
-------------------------------------------------------------------------
|
980 |
CONFLICT WARNING:
|
981 |
|
982 |
The following modules or packages have the same names as modules or
|
983 |
packages being installed, and will be *before* the installed packages in
|
984 |
Python's search path. You MUST remove all of the relevant files and
|
985 |
directories before you will be able to use the package(s) you are
|
986 |
installing:
|
987 |
|
988 |
%s
|
989 |
|
990 |
""" % '\n '.join(blockers) |
991 |
|
992 |
if self.ignore_conflicts_at_my_risk: |
993 |
msg += """\
|
994 |
(Note: you can run EasyInstall on '%s' with the
|
995 |
--delete-conflicting option to attempt deletion of the above files
|
996 |
and/or directories.)
|
997 |
""" % dist.project_name
|
998 |
else:
|
999 |
msg += """\
|
1000 |
Note: you can attempt this installation again with EasyInstall, and use
|
1001 |
either the --delete-conflicting (-D) option or the
|
1002 |
--ignore-conflicts-at-my-risk option, to either delete the above files
|
1003 |
and directories, or to ignore the conflicts, respectively. Note that if
|
1004 |
you ignore the conflicts, the installed package(s) may not work.
|
1005 |
"""
|
1006 |
msg += """\
|
1007 |
-------------------------------------------------------------------------
|
1008 |
"""
|
1009 |
sys.stderr.write(msg) |
1010 |
sys.stderr.flush() |
1011 |
if not self.ignore_conflicts_at_my_risk: |
1012 |
raise DistutilsError("Installation aborted due to conflicts") |
1013 |
|
1014 |
def installation_report(self, req, dist, what="Installed"): |
1015 |
"""Helpful installation message for display to package users"""
|
1016 |
msg = "\n%(what)s %(eggloc)s%(extras)s"
|
1017 |
if self.multi_version and not self.no_report: |
1018 |
msg += """
|
1019 |
|
1020 |
Because this distribution was installed --multi-version, before you can
|
1021 |
import modules from this package in an application, you will need to
|
1022 |
'import pkg_resources' and then use a 'require()' call similar to one of
|
1023 |
these examples, in order to select the desired version:
|
1024 |
|
1025 |
pkg_resources.require("%(name)s") # latest installed version
|
1026 |
pkg_resources.require("%(name)s==%(version)s") # this exact version
|
1027 |
pkg_resources.require("%(name)s>=%(version)s") # this version or higher
|
1028 |
"""
|
1029 |
if self.install_dir not in map(normalize_path,sys.path): |
1030 |
msg += """
|
1031 |
|
1032 |
Note also that the installation directory must be on sys.path at runtime for
|
1033 |
this to work. (e.g. by being the application's script directory, by being on
|
1034 |
PYTHONPATH, or by being added to sys.path by your code.)
|
1035 |
"""
|
1036 |
eggloc = dist.location |
1037 |
name = dist.project_name |
1038 |
version = dist.version |
1039 |
extras = '' # TODO: self.report_extras(req, dist) |
1040 |
return msg % locals() |
1041 |
|
1042 |
def report_editable(self, spec, setup_script): |
1043 |
dirname = os.path.dirname(setup_script) |
1044 |
python = sys.executable |
1045 |
return """\nExtracted editable version of %(spec)s to %(dirname)s |
1046 |
|
1047 |
If it uses setuptools in its setup script, you can activate it in
|
1048 |
"development" mode by going to that directory and running::
|
1049 |
|
1050 |
%(python)s setup.py develop
|
1051 |
|
1052 |
See the setuptools documentation for the "develop" command for more info.
|
1053 |
""" % locals() |
1054 |
|
1055 |
def run_setup(self, setup_script, setup_base, args): |
1056 |
sys.modules.setdefault('distutils.command.bdist_egg', bdist_egg)
|
1057 |
sys.modules.setdefault('distutils.command.egg_info', egg_info)
|
1058 |
|
1059 |
args = list(args)
|
1060 |
if self.verbose>2: |
1061 |
v = 'v' * (self.verbose - 1) |
1062 |
args.insert(0,'-'+v) |
1063 |
elif self.verbose<2: |
1064 |
args.insert(0,'-q') |
1065 |
if self.dry_run: |
1066 |
args.insert(0,'-n') |
1067 |
log.info( |
1068 |
"Running %s %s", setup_script[len(setup_base)+1:], ' '.join(args) |
1069 |
) |
1070 |
try:
|
1071 |
run_setup(setup_script, args) |
1072 |
except SystemExit, v: |
1073 |
raise DistutilsError("Setup script exited with %s" % (v.args[0],)) |
1074 |
|
1075 |
def build_and_install(self, setup_script, setup_base): |
1076 |
args = ['bdist_egg', '--dist-dir'] |
1077 |
dist_dir = tempfile.mkdtemp( |
1078 |
prefix='egg-dist-tmp-', dir=os.path.dirname(setup_script)
|
1079 |
) |
1080 |
try:
|
1081 |
args.append(dist_dir) |
1082 |
self.run_setup(setup_script, setup_base, args)
|
1083 |
all_eggs = Environment([dist_dir]) |
1084 |
eggs = [] |
1085 |
for key in all_eggs: |
1086 |
for dist in all_eggs[key]: |
1087 |
eggs.append(self.install_egg(dist.location, setup_base))
|
1088 |
if not eggs and not self.dry_run: |
1089 |
log.warn("No eggs found in %s (setup script problem?)",
|
1090 |
dist_dir) |
1091 |
return eggs
|
1092 |
finally:
|
1093 |
rmtree(dist_dir) |
1094 |
log.set_verbosity(self.verbose) # restore our log verbosity |
1095 |
|
1096 |
def update_pth(self,dist): |
1097 |
if self.pth_file is None: |
1098 |
return
|
1099 |
|
1100 |
for d in self.pth_file[dist.key]: # drop old entries |
1101 |
if self.multi_version or d.location != dist.location: |
1102 |
log.info("Removing %s from easy-install.pth file", d)
|
1103 |
self.pth_file.remove(d)
|
1104 |
if d.location in self.shadow_path: |
1105 |
self.shadow_path.remove(d.location)
|
1106 |
|
1107 |
if not self.multi_version: |
1108 |
if dist.location in self.pth_file.paths: |
1109 |
log.info( |
1110 |
"%s is already the active version in easy-install.pth",
|
1111 |
dist |
1112 |
) |
1113 |
else:
|
1114 |
log.info("Adding %s to easy-install.pth file", dist)
|
1115 |
self.pth_file.add(dist) # add new entry |
1116 |
if dist.location not in self.shadow_path: |
1117 |
self.shadow_path.append(dist.location)
|
1118 |
|
1119 |
if not self.dry_run: |
1120 |
|
1121 |
self.pth_file.save()
|
1122 |
if dist.key=='distribute': |
1123 |
# Ensure that setuptools itself never becomes unavailable!
|
1124 |
# XXX should this check for latest version?
|
1125 |
filename = os.path.join(self.install_dir,'setuptools.pth') |
1126 |
if os.path.islink(filename): os.unlink(filename)
|
1127 |
f = open(filename, 'wt') |
1128 |
f.write(self.pth_file.make_relative(dist.location)+'\n') |
1129 |
f.close() |
1130 |
|
1131 |
def unpack_progress(self, src, dst): |
1132 |
# Progress filter for unpacking
|
1133 |
log.debug("Unpacking %s to %s", src, dst)
|
1134 |
return dst # only unpack-and-compile skips files for dry run |
1135 |
|
1136 |
def unpack_and_compile(self, egg_path, destination): |
1137 |
to_compile = []; to_chmod = [] |
1138 |
|
1139 |
def pf(src,dst): |
1140 |
if dst.endswith('.py') and not src.startswith('EGG-INFO/'): |
1141 |
to_compile.append(dst) |
1142 |
to_chmod.append(dst) |
1143 |
elif dst.endswith('.dll') or dst.endswith('.so'): |
1144 |
to_chmod.append(dst) |
1145 |
self.unpack_progress(src,dst)
|
1146 |
return not self.dry_run and dst or None |
1147 |
|
1148 |
unpack_archive(egg_path, destination, pf) |
1149 |
self.byte_compile(to_compile)
|
1150 |
if not self.dry_run: |
1151 |
for f in to_chmod: |
1152 |
mode = ((os.stat(f)[stat.ST_MODE]) | 0555) & 07755 |
1153 |
chmod(f, mode) |
1154 |
|
1155 |
def byte_compile(self, to_compile): |
1156 |
if _dont_write_bytecode:
|
1157 |
self.warn('byte-compiling is disabled, skipping.') |
1158 |
return
|
1159 |
|
1160 |
from distutils.util import byte_compile |
1161 |
try:
|
1162 |
# try to make the byte compile messages quieter
|
1163 |
log.set_verbosity(self.verbose - 1) |
1164 |
|
1165 |
byte_compile(to_compile, optimize=0, force=1, dry_run=self.dry_run) |
1166 |
if self.optimize: |
1167 |
byte_compile( |
1168 |
to_compile, optimize=self.optimize, force=1, |
1169 |
dry_run=self.dry_run
|
1170 |
) |
1171 |
finally:
|
1172 |
log.set_verbosity(self.verbose) # restore original verbosity |
1173 |
|
1174 |
|
1175 |
|
1176 |
|
1177 |
|
1178 |
|
1179 |
|
1180 |
|
1181 |
def no_default_version_msg(self): |
1182 |
return """bad install directory or PYTHONPATH |
1183 |
|
1184 |
You are attempting to install a package to a directory that is not
|
1185 |
on PYTHONPATH and which Python does not read ".pth" files from. The
|
1186 |
installation directory you specified (via --install-dir, --prefix, or
|
1187 |
the distutils default setting) was:
|
1188 |
|
1189 |
%s
|
1190 |
|
1191 |
and your PYTHONPATH environment variable currently contains:
|
1192 |
|
1193 |
%r
|
1194 |
|
1195 |
Here are some of your options for correcting the problem:
|
1196 |
|
1197 |
* You can choose a different installation directory, i.e., one that is
|
1198 |
on PYTHONPATH or supports .pth files
|
1199 |
|
1200 |
* You can add the installation directory to the PYTHONPATH environment
|
1201 |
variable. (It must then also be on PYTHONPATH whenever you run
|
1202 |
Python and want to use the package(s) you are installing.)
|
1203 |
|
1204 |
* You can set up the installation directory to support ".pth" files by
|
1205 |
using one of the approaches described here:
|
1206 |
|
1207 |
http://packages.python.org/distribute/easy_install.html#custom-installation-locations
|
1208 |
|
1209 |
Please make the appropriate changes for your system and try again.""" % (
|
1210 |
self.install_dir, os.environ.get('PYTHONPATH','') |
1211 |
) |
1212 |
|
1213 |
|
1214 |
|
1215 |
|
1216 |
|
1217 |
|
1218 |
|
1219 |
|
1220 |
|
1221 |
|
1222 |
def install_site_py(self): |
1223 |
"""Make sure there's a site.py in the target dir, if needed"""
|
1224 |
|
1225 |
if self.sitepy_installed: |
1226 |
return # already did it, or don't need to |
1227 |
|
1228 |
sitepy = os.path.join(self.install_dir, "site.py") |
1229 |
source = resource_string(Requirement.parse("distribute"), "site.py") |
1230 |
current = ""
|
1231 |
|
1232 |
if os.path.exists(sitepy):
|
1233 |
log.debug("Checking existing site.py in %s", self.install_dir) |
1234 |
f = open(sitepy,'rb') |
1235 |
current = f.read() |
1236 |
# we want str, not bytes
|
1237 |
if sys.version_info >= (3,): |
1238 |
current = current.decode() |
1239 |
|
1240 |
f.close() |
1241 |
if not current.startswith('def __boot():'): |
1242 |
raise DistutilsError(
|
1243 |
"%s is not a setuptools-generated site.py; please"
|
1244 |
" remove it." % sitepy
|
1245 |
) |
1246 |
|
1247 |
if current != source:
|
1248 |
log.info("Creating %s", sitepy)
|
1249 |
if not self.dry_run: |
1250 |
ensure_directory(sitepy) |
1251 |
f = open(sitepy,'wb') |
1252 |
f.write(source) |
1253 |
f.close() |
1254 |
self.byte_compile([sitepy])
|
1255 |
|
1256 |
self.sitepy_installed = True |
1257 |
|
1258 |
|
1259 |
|
1260 |
|
1261 |
def create_home_path(self): |
1262 |
"""Create directories under ~."""
|
1263 |
if not self.user: |
1264 |
return
|
1265 |
home = convert_path(os.path.expanduser("~"))
|
1266 |
for name, path in self.config_vars.iteritems(): |
1267 |
if path.startswith(home) and not os.path.isdir(path): |
1268 |
self.debug_print("os.makedirs('%s', 0700)" % path) |
1269 |
os.makedirs(path, 0700)
|
1270 |
|
1271 |
|
1272 |
|
1273 |
|
1274 |
|
1275 |
|
1276 |
|
1277 |
INSTALL_SCHEMES = dict(
|
1278 |
posix = dict(
|
1279 |
install_dir = '$base/lib/python$py_version_short/site-packages',
|
1280 |
script_dir = '$base/bin',
|
1281 |
), |
1282 |
) |
1283 |
|
1284 |
DEFAULT_SCHEME = dict(
|
1285 |
install_dir = '$base/Lib/site-packages',
|
1286 |
script_dir = '$base/Scripts',
|
1287 |
) |
1288 |
|
1289 |
def _expand(self, *attrs): |
1290 |
config_vars = self.get_finalized_command('install').config_vars |
1291 |
|
1292 |
if self.prefix: |
1293 |
# Set default install_dir/scripts from --prefix
|
1294 |
config_vars = config_vars.copy() |
1295 |
config_vars['base'] = self.prefix |
1296 |
scheme = self.INSTALL_SCHEMES.get(os.name,self.DEFAULT_SCHEME) |
1297 |
for attr,val in scheme.items(): |
1298 |
if getattr(self,attr,None) is None: |
1299 |
setattr(self,attr,val) |
1300 |
|
1301 |
from distutils.util import subst_vars |
1302 |
for attr in attrs: |
1303 |
val = getattr(self, attr) |
1304 |
if val is not None: |
1305 |
val = subst_vars(val, config_vars) |
1306 |
if os.name == 'posix': |
1307 |
val = os.path.expanduser(val) |
1308 |
setattr(self, attr, val) |
1309 |
|
1310 |
|
1311 |
|
1312 |
|
1313 |
|
1314 |
|
1315 |
|
1316 |
|
1317 |
|
1318 |
def get_site_dirs(): |
1319 |
# return a list of 'site' dirs
|
1320 |
sitedirs = filter(None,os.environ.get('PYTHONPATH','').split(os.pathsep)) |
1321 |
prefixes = [sys.prefix] |
1322 |
if sys.exec_prefix != sys.prefix:
|
1323 |
prefixes.append(sys.exec_prefix) |
1324 |
for prefix in prefixes: |
1325 |
if prefix:
|
1326 |
if sys.platform in ('os2emx', 'riscos'): |
1327 |
sitedirs.append(os.path.join(prefix, "Lib", "site-packages")) |
1328 |
elif os.sep == '/': |
1329 |
sitedirs.extend([os.path.join(prefix, |
1330 |
"lib",
|
1331 |
"python" + sys.version[:3], |
1332 |
"site-packages"),
|
1333 |
os.path.join(prefix, "lib", "site-python")]) |
1334 |
else:
|
1335 |
sitedirs.extend( |
1336 |
[prefix, os.path.join(prefix, "lib", "site-packages")] |
1337 |
) |
1338 |
if sys.platform == 'darwin': |
1339 |
# for framework builds *only* we add the standard Apple
|
1340 |
# locations. Currently only per-user, but /Library and
|
1341 |
# /Network/Library could be added too
|
1342 |
if 'Python.framework' in prefix: |
1343 |
home = os.environ.get('HOME')
|
1344 |
if home:
|
1345 |
sitedirs.append( |
1346 |
os.path.join(home, |
1347 |
'Library',
|
1348 |
'Python',
|
1349 |
sys.version[:3],
|
1350 |
'site-packages'))
|
1351 |
for plat_specific in (0,1): |
1352 |
site_lib = get_python_lib(plat_specific) |
1353 |
if site_lib not in sitedirs: sitedirs.append(site_lib) |
1354 |
|
1355 |
if HAS_USER_SITE:
|
1356 |
sitedirs.append(site.USER_SITE) |
1357 |
|
1358 |
sitedirs = map(normalize_path, sitedirs)
|
1359 |
|
1360 |
return sitedirs
|
1361 |
|
1362 |
|
1363 |
def expand_paths(inputs): |
1364 |
"""Yield sys.path directories that might contain "old-style" packages"""
|
1365 |
|
1366 |
seen = {} |
1367 |
|
1368 |
for dirname in inputs: |
1369 |
dirname = normalize_path(dirname) |
1370 |
if dirname in seen: |
1371 |
continue
|
1372 |
|
1373 |
seen[dirname] = 1
|
1374 |
if not os.path.isdir(dirname): |
1375 |
continue
|
1376 |
|
1377 |
files = os.listdir(dirname) |
1378 |
yield dirname, files
|
1379 |
|
1380 |
for name in files: |
1381 |
if not name.endswith('.pth'): |
1382 |
# We only care about the .pth files
|
1383 |
continue
|
1384 |
if name in ('easy-install.pth','setuptools.pth'): |
1385 |
# Ignore .pth files that we control
|
1386 |
continue
|
1387 |
|
1388 |
# Read the .pth file
|
1389 |
f = open(os.path.join(dirname,name))
|
1390 |
lines = list(yield_lines(f))
|
1391 |
f.close() |
1392 |
|
1393 |
# Yield existing non-dupe, non-import directory lines from it
|
1394 |
for line in lines: |
1395 |
if not line.startswith("import"): |
1396 |
line = normalize_path(line.rstrip()) |
1397 |
if line not in seen: |
1398 |
seen[line] = 1
|
1399 |
if not os.path.isdir(line): |
1400 |
continue
|
1401 |
yield line, os.listdir(line)
|
1402 |
|
1403 |
|
1404 |
def extract_wininst_cfg(dist_filename): |
1405 |
"""Extract configuration data from a bdist_wininst .exe
|
1406 |
|
1407 |
Returns a ConfigParser.RawConfigParser, or None
|
1408 |
"""
|
1409 |
f = open(dist_filename,'rb') |
1410 |
try:
|
1411 |
endrec = zipfile._EndRecData(f) |
1412 |
if endrec is None: |
1413 |
return None |
1414 |
|
1415 |
prepended = (endrec[9] - endrec[5]) - endrec[6] |
1416 |
if prepended < 12: # no wininst data here |
1417 |
return None |
1418 |
f.seek(prepended-12)
|
1419 |
|
1420 |
import struct, StringIO, ConfigParser |
1421 |
tag, cfglen, bmlen = struct.unpack("<iii",f.read(12)) |
1422 |
if tag not in (0x1234567A, 0x1234567B): |
1423 |
return None # not a valid tag |
1424 |
|
1425 |
f.seek(prepended-(12+cfglen))
|
1426 |
cfg = ConfigParser.RawConfigParser({'version':'','target_version':''}) |
1427 |
try:
|
1428 |
cfg.readfp(StringIO.StringIO(f.read(cfglen).split(chr(0),1)[0])) |
1429 |
except ConfigParser.Error:
|
1430 |
return None |
1431 |
if not cfg.has_section('metadata') or not cfg.has_section('Setup'): |
1432 |
return None |
1433 |
return cfg
|
1434 |
|
1435 |
finally:
|
1436 |
f.close() |
1437 |
|
1438 |
|
1439 |
|
1440 |
|
1441 |
|
1442 |
|
1443 |
|
1444 |
|
1445 |
def get_exe_prefixes(exe_filename): |
1446 |
"""Get exe->egg path translations for a given .exe file"""
|
1447 |
|
1448 |
prefixes = [ |
1449 |
('PURELIB/', ''), ('PLATLIB/pywin32_system32', ''), |
1450 |
('PLATLIB/', ''), |
1451 |
('SCRIPTS/', 'EGG-INFO/scripts/'), |
1452 |
('DATA/LIB/site-packages', ''), |
1453 |
] |
1454 |
z = zipfile.ZipFile(exe_filename) |
1455 |
try:
|
1456 |
for info in z.infolist(): |
1457 |
name = info.filename |
1458 |
parts = name.split('/')
|
1459 |
if len(parts)==3 and parts[2]=='PKG-INFO': |
1460 |
if parts[1].endswith('.egg-info'): |
1461 |
prefixes.insert(0,('/'.join(parts[:2]), 'EGG-INFO/')) |
1462 |
break
|
1463 |
if len(parts)<>2 or not name.endswith('.pth'): |
1464 |
continue
|
1465 |
if name.endswith('-nspkg.pth'): |
1466 |
continue
|
1467 |
if parts[0].upper() in ('PURELIB','PLATLIB'): |
1468 |
for pth in yield_lines(z.read(name)): |
1469 |
pth = pth.strip().replace('\\','/') |
1470 |
if not pth.startswith('import'): |
1471 |
prefixes.append((('%s/%s/' % (parts[0],pth)), '')) |
1472 |
finally:
|
1473 |
z.close() |
1474 |
prefixes = [(x.lower(),y) for x, y in prefixes] |
1475 |
prefixes.sort(); prefixes.reverse() |
1476 |
return prefixes
|
1477 |
|
1478 |
|
1479 |
def parse_requirement_arg(spec): |
1480 |
try:
|
1481 |
return Requirement.parse(spec)
|
1482 |
except ValueError: |
1483 |
raise DistutilsError(
|
1484 |
"Not a URL, existing file, or requirement spec: %r" % (spec,)
|
1485 |
) |
1486 |
|
1487 |
class PthDistributions(Environment): |
1488 |
"""A .pth file with Distribution paths in it"""
|
1489 |
|
1490 |
dirty = False
|
1491 |
|
1492 |
def __init__(self, filename, sitedirs=()): |
1493 |
self.filename = filename; self.sitedirs=map(normalize_path, sitedirs) |
1494 |
self.basedir = normalize_path(os.path.dirname(self.filename)) |
1495 |
self._load(); Environment.__init__(self, [], None, None) |
1496 |
for path in yield_lines(self.paths): |
1497 |
map(self.add, find_distributions(path, True)) |
1498 |
|
1499 |
def _load(self): |
1500 |
self.paths = []
|
1501 |
saw_import = False
|
1502 |
seen = dict.fromkeys(self.sitedirs) |
1503 |
if os.path.isfile(self.filename): |
1504 |
f = open(self.filename,'rt') |
1505 |
for line in f: |
1506 |
if line.startswith('import'): |
1507 |
saw_import = True
|
1508 |
continue
|
1509 |
path = line.rstrip() |
1510 |
self.paths.append(path)
|
1511 |
if not path.strip() or path.strip().startswith('#'): |
1512 |
continue
|
1513 |
# skip non-existent paths, in case somebody deleted a package
|
1514 |
# manually, and duplicate paths as well
|
1515 |
path = self.paths[-1] = normalize_path( |
1516 |
os.path.join(self.basedir,path)
|
1517 |
) |
1518 |
if not os.path.exists(path) or path in seen: |
1519 |
self.paths.pop() # skip it |
1520 |
self.dirty = True # we cleaned up, so we're dirty now :) |
1521 |
continue
|
1522 |
seen[path] = 1
|
1523 |
f.close() |
1524 |
|
1525 |
if self.paths and not saw_import: |
1526 |
self.dirty = True # ensure anything we touch has import wrappers |
1527 |
while self.paths and not self.paths[-1].strip(): |
1528 |
self.paths.pop()
|
1529 |
|
1530 |
def save(self): |
1531 |
"""Write changed .pth file back to disk"""
|
1532 |
if not self.dirty: |
1533 |
return
|
1534 |
|
1535 |
data = '\n'.join(map(self.make_relative,self.paths)) |
1536 |
if data:
|
1537 |
log.debug("Saving %s", self.filename) |
1538 |
data = ( |
1539 |
"import sys; sys.__plen = len(sys.path)\n"
|
1540 |
"%s\n"
|
1541 |
"import sys; new=sys.path[sys.__plen:];"
|
1542 |
" del sys.path[sys.__plen:];"
|
1543 |
" p=getattr(sys,'__egginsert',0); sys.path[p:p]=new;"
|
1544 |
" sys.__egginsert = p+len(new)\n"
|
1545 |
) % data |
1546 |
|
1547 |
if os.path.islink(self.filename): |
1548 |
os.unlink(self.filename)
|
1549 |
f = open(self.filename,'wt') |
1550 |
f.write(data); f.close() |
1551 |
|
1552 |
elif os.path.exists(self.filename): |
1553 |
log.debug("Deleting empty %s", self.filename) |
1554 |
os.unlink(self.filename)
|
1555 |
|
1556 |
self.dirty = False |
1557 |
|
1558 |
def add(self,dist): |
1559 |
"""Add `dist` to the distribution map"""
|
1560 |
if (dist.location not in self.paths and ( |
1561 |
dist.location not in self.sitedirs or |
1562 |
dist.location == os.getcwd() #account for '.' being in PYTHONPATH
|
1563 |
)): |
1564 |
self.paths.append(dist.location)
|
1565 |
self.dirty = True |
1566 |
Environment.add(self,dist)
|
1567 |
|
1568 |
def remove(self,dist): |
1569 |
"""Remove `dist` from the distribution map"""
|
1570 |
while dist.location in self.paths: |
1571 |
self.paths.remove(dist.location); self.dirty = True |
1572 |
Environment.remove(self,dist)
|
1573 |
|
1574 |
|
1575 |
def make_relative(self,path): |
1576 |
npath, last = os.path.split(normalize_path(path)) |
1577 |
baselen = len(self.basedir) |
1578 |
parts = [last] |
1579 |
sep = os.altsep=='/' and '/' or os.sep |
1580 |
while len(npath)>=baselen: |
1581 |
if npath==self.basedir: |
1582 |
parts.append(os.curdir) |
1583 |
parts.reverse() |
1584 |
return sep.join(parts)
|
1585 |
npath, last = os.path.split(npath) |
1586 |
parts.append(last) |
1587 |
else:
|
1588 |
return path
|
1589 |
|
1590 |
def get_script_header(script_text, executable=sys_executable, wininst=False): |
1591 |
"""Create a #! line, getting options (if any) from script_text"""
|
1592 |
from distutils.command.build_scripts import first_line_re |
1593 |
|
1594 |
# first_line_re in Python >=3.1.4 and >=3.2.1 is a bytes pattern.
|
1595 |
if not isinstance(first_line_re.pattern, str): |
1596 |
first_line_re = re.compile(first_line_re.pattern.decode()) |
1597 |
|
1598 |
first = (script_text+'\n').splitlines()[0] |
1599 |
match = first_line_re.match(first) |
1600 |
options = ''
|
1601 |
if match:
|
1602 |
options = match.group(1) or '' |
1603 |
if options: options = ' '+options |
1604 |
if wininst:
|
1605 |
executable = "python.exe"
|
1606 |
else:
|
1607 |
executable = nt_quote_arg(executable) |
1608 |
hdr = "#!%(executable)s%(options)s\n" % locals() |
1609 |
if not isascii(hdr): |
1610 |
# Non-ascii path to sys.executable, use -x to prevent warnings
|
1611 |
if options:
|
1612 |
if options.strip().startswith('-'): |
1613 |
options = ' -x'+options.strip()[1:] |
1614 |
# else: punt, we can't do it, let the warning happen anyway
|
1615 |
else:
|
1616 |
options = ' -x'
|
1617 |
executable = fix_jython_executable(executable, options) |
1618 |
hdr = "#!%(executable)s%(options)s\n" % locals() |
1619 |
return hdr
|
1620 |
|
1621 |
def auto_chmod(func, arg, exc): |
1622 |
if func is os.remove and os.name=='nt': |
1623 |
chmod(arg, stat.S_IWRITE) |
1624 |
return func(arg)
|
1625 |
exc = sys.exc_info() |
1626 |
raise exc[0], (exc[1][0], exc[1][1] + (" %s %s" % (func,arg))) |
1627 |
|
1628 |
def uncache_zipdir(path): |
1629 |
"""Ensure that the importer caches dont have stale info for `path`"""
|
1630 |
from zipimport import _zip_directory_cache as zdc |
1631 |
_uncache(path, zdc) |
1632 |
_uncache(path, sys.path_importer_cache) |
1633 |
|
1634 |
def _uncache(path, cache): |
1635 |
if path in cache: |
1636 |
del cache[path]
|
1637 |
else:
|
1638 |
path = normalize_path(path) |
1639 |
for p in cache: |
1640 |
if normalize_path(p)==path:
|
1641 |
del cache[p]
|
1642 |
return
|
1643 |
|
1644 |
def is_python(text, filename='<string>'): |
1645 |
"Is this string a valid Python script?"
|
1646 |
try:
|
1647 |
compile(text, filename, 'exec') |
1648 |
except (SyntaxError, TypeError): |
1649 |
return False |
1650 |
else:
|
1651 |
return True |
1652 |
|
1653 |
def is_sh(executable): |
1654 |
"""Determine if the specified executable is a .sh (contains a #! line)"""
|
1655 |
try:
|
1656 |
fp = open(executable)
|
1657 |
magic = fp.read(2)
|
1658 |
fp.close() |
1659 |
except (OSError,IOError): return executable |
1660 |
return magic == '#!' |
1661 |
|
1662 |
def nt_quote_arg(arg): |
1663 |
"""Quote a command line argument according to Windows parsing rules"""
|
1664 |
|
1665 |
result = [] |
1666 |
needquote = False
|
1667 |
nb = 0
|
1668 |
|
1669 |
needquote = (" " in arg) or ("\t" in arg) |
1670 |
if needquote:
|
1671 |
result.append('"')
|
1672 |
|
1673 |
for c in arg: |
1674 |
if c == '\\': |
1675 |
nb += 1
|
1676 |
elif c == '"': |
1677 |
# double preceding backslashes, then add a \"
|
1678 |
result.append('\\' * (nb*2) + '\\"') |
1679 |
nb = 0
|
1680 |
else:
|
1681 |
if nb:
|
1682 |
result.append('\\' * nb)
|
1683 |
nb = 0
|
1684 |
result.append(c) |
1685 |
|
1686 |
if nb:
|
1687 |
result.append('\\' * nb)
|
1688 |
|
1689 |
if needquote:
|
1690 |
result.append('\\' * nb) # double the trailing backslashes |
1691 |
result.append('"')
|
1692 |
|
1693 |
return ''.join(result) |
1694 |
|
1695 |
|
1696 |
|
1697 |
|
1698 |
|
1699 |
|
1700 |
|
1701 |
|
1702 |
|
1703 |
def is_python_script(script_text, filename): |
1704 |
"""Is this text, as a whole, a Python script? (as opposed to shell/bat/etc.
|
1705 |
"""
|
1706 |
if filename.endswith('.py') or filename.endswith('.pyw'): |
1707 |
return True # extension says it's Python |
1708 |
if is_python(script_text, filename):
|
1709 |
return True # it's syntactically valid Python |
1710 |
if script_text.startswith('#!'): |
1711 |
# It begins with a '#!' line, so check if 'python' is in it somewhere
|
1712 |
return 'python' in script_text.splitlines()[0].lower() |
1713 |
|
1714 |
return False # Not any Python I can recognize |
1715 |
|
1716 |
try:
|
1717 |
from os import chmod as _chmod |
1718 |
except ImportError: |
1719 |
# Jython compatibility
|
1720 |
def _chmod(*args): pass |
1721 |
|
1722 |
def chmod(path, mode): |
1723 |
log.debug("changing mode of %s to %o", path, mode)
|
1724 |
try:
|
1725 |
_chmod(path, mode) |
1726 |
except os.error, e:
|
1727 |
log.debug("chmod failed: %s", e)
|
1728 |
|
1729 |
def fix_jython_executable(executable, options): |
1730 |
if sys.platform.startswith('java') and is_sh(executable): |
1731 |
# Workaround Jython's sys.executable being a .sh (an invalid
|
1732 |
# shebang line interpreter)
|
1733 |
if options:
|
1734 |
# Can't apply the workaround, leave it broken
|
1735 |
log.warn("WARNING: Unable to adapt shebang line for Jython,"
|
1736 |
" the following script is NOT executable\n"
|
1737 |
" see http://bugs.jython.org/issue1112 for"
|
1738 |
" more information.")
|
1739 |
else:
|
1740 |
return '/usr/bin/env %s' % executable |
1741 |
return executable
|
1742 |
|
1743 |
|
1744 |
def get_script_args(dist, executable=sys_executable, wininst=False): |
1745 |
"""Yield write_script() argument tuples for a distribution's entrypoints"""
|
1746 |
spec = str(dist.as_requirement())
|
1747 |
header = get_script_header("", executable, wininst)
|
1748 |
for group in 'console_scripts', 'gui_scripts': |
1749 |
for name, ep in dist.get_entry_map(group).items(): |
1750 |
script_text = ( |
1751 |
"# EASY-INSTALL-ENTRY-SCRIPT: %(spec)r,%(group)r,%(name)r\n"
|
1752 |
"__requires__ = %(spec)r\n"
|
1753 |
"import sys\n"
|
1754 |
"from pkg_resources import load_entry_point\n"
|
1755 |
"\n"
|
1756 |
"if __name__ == '__main__':"
|
1757 |
"\n"
|
1758 |
" sys.exit(\n"
|
1759 |
" load_entry_point(%(spec)r, %(group)r, %(name)r)()\n"
|
1760 |
" )\n"
|
1761 |
) % locals()
|
1762 |
if sys.platform=='win32' or wininst: |
1763 |
# On Windows/wininst, add a .py extension and an .exe launcher
|
1764 |
if group=='gui_scripts': |
1765 |
ext, launcher = '-script.pyw', 'gui.exe' |
1766 |
old = ['.pyw']
|
1767 |
new_header = re.sub('(?i)python.exe','pythonw.exe',header) |
1768 |
else:
|
1769 |
ext, launcher = '-script.py', 'cli.exe' |
1770 |
old = ['.py','.pyc','.pyo'] |
1771 |
new_header = re.sub('(?i)pythonw.exe','python.exe',header) |
1772 |
|
1773 |
if os.path.exists(new_header[2:-1]) or sys.platform!='win32': |
1774 |
hdr = new_header |
1775 |
else:
|
1776 |
hdr = header |
1777 |
yield (name+ext, hdr+script_text, 't', [name+x for x in old]) |
1778 |
yield (
|
1779 |
name+'.exe', resource_string('setuptools', launcher), |
1780 |
'b' # write in binary mode |
1781 |
) |
1782 |
else:
|
1783 |
# On other platforms, we assume the right thing to do is to
|
1784 |
# just write the stub with no extension.
|
1785 |
yield (name, header+script_text)
|
1786 |
|
1787 |
def rmtree(path, ignore_errors=False, onerror=auto_chmod): |
1788 |
"""Recursively delete a directory tree.
|
1789 |
|
1790 |
This code is taken from the Python 2.4 version of 'shutil', because
|
1791 |
the 2.3 version doesn't really work right.
|
1792 |
"""
|
1793 |
if ignore_errors:
|
1794 |
def onerror(*args): |
1795 |
pass
|
1796 |
elif onerror is None: |
1797 |
def onerror(*args): |
1798 |
raise
|
1799 |
names = [] |
1800 |
try:
|
1801 |
names = os.listdir(path) |
1802 |
except os.error, err:
|
1803 |
onerror(os.listdir, path, sys.exc_info()) |
1804 |
for name in names: |
1805 |
fullname = os.path.join(path, name) |
1806 |
try:
|
1807 |
mode = os.lstat(fullname).st_mode |
1808 |
except os.error:
|
1809 |
mode = 0
|
1810 |
if stat.S_ISDIR(mode):
|
1811 |
rmtree(fullname, ignore_errors, onerror) |
1812 |
else:
|
1813 |
try:
|
1814 |
os.remove(fullname) |
1815 |
except os.error, err:
|
1816 |
onerror(os.remove, fullname, sys.exc_info()) |
1817 |
try:
|
1818 |
os.rmdir(path) |
1819 |
except os.error:
|
1820 |
onerror(os.rmdir, path, sys.exc_info()) |
1821 |
|
1822 |
def bootstrap(): |
1823 |
# This function is called when setuptools*.egg is run using /bin/sh
|
1824 |
import setuptools; argv0 = os.path.dirname(setuptools.__path__[0]) |
1825 |
sys.argv[0] = argv0; sys.argv.append(argv0); main()
|
1826 |
|
1827 |
def main(argv=None, **kw): |
1828 |
from setuptools import setup |
1829 |
from setuptools.dist import Distribution |
1830 |
import distutils.core |
1831 |
|
1832 |
USAGE = """\
|
1833 |
usage: %(script)s [options] requirement_or_url ...
|
1834 |
or: %(script)s --help
|
1835 |
"""
|
1836 |
|
1837 |
def gen_usage (script_name): |
1838 |
script = os.path.basename(script_name) |
1839 |
return USAGE % vars() |
1840 |
|
1841 |
def with_ei_usage(f): |
1842 |
old_gen_usage = distutils.core.gen_usage |
1843 |
try:
|
1844 |
distutils.core.gen_usage = gen_usage |
1845 |
return f()
|
1846 |
finally:
|
1847 |
distutils.core.gen_usage = old_gen_usage |
1848 |
|
1849 |
class DistributionWithoutHelpCommands(Distribution): |
1850 |
common_usage = ""
|
1851 |
|
1852 |
def _show_help(self,*args,**kw): |
1853 |
with_ei_usage(lambda: Distribution._show_help(self,*args,**kw)) |
1854 |
|
1855 |
def find_config_files(self): |
1856 |
files = Distribution.find_config_files(self)
|
1857 |
if 'setup.cfg' in files: |
1858 |
files.remove('setup.cfg')
|
1859 |
return files
|
1860 |
|
1861 |
if argv is None: |
1862 |
argv = sys.argv[1:]
|
1863 |
|
1864 |
with_ei_usage(lambda:
|
1865 |
setup( |
1866 |
script_args = ['-q','easy_install', '-v']+argv, |
1867 |
script_name = sys.argv[0] or 'easy_install', |
1868 |
distclass=DistributionWithoutHelpCommands, **kw |
1869 |
) |
1870 |
) |
1871 |
|
1872 |
|
1873 |
|
1874 |
|