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`__.
10 __ http://peak.telecommunity.com/DevCenter/EasyInstall
12 import sys, os.path, zipimport, shutil, tempfile, zipfile, re, stat, random
14 from setuptools import Command, _dont_write_bytecode
15 from setuptools import __version__ as setuptools_version
16 from setuptools.sandbox import run_setup
17 from distutils import log, dir_util
18 from distutils.sysconfig import get_python_lib
19 from distutils.errors import DistutilsArgError, DistutilsOptionError, \
21 from setuptools.archive_util import unpack_archive
22 from setuptools.package_index import PackageIndex, parse_bdist_wininst
23 from setuptools.package_index import URL_SCHEME
24 from setuptools.command import bdist_egg, egg_info
25 from pkg_resources import *
26 sys_executable = os.path.normpath(sys.executable)
29 'samefile', 'easy_install', 'PthDistributions', 'extract_wininst_cfg',
30 'main', 'get_exe_prefixes',
34 if hasattr(os.path,'samefile') and (
35 os.path.exists(p1) and os.path.exists(p2)
37 return os.path.samefile(p1,p2)
39 os.path.normpath(os.path.normcase(p1)) ==
40 os.path.normpath(os.path.normcase(p2))
43 class easy_install(Command):
44 """Manage a download/build/install process"""
45 description = "Find/get/install Python packages"
46 command_consumes_arguments = True
49 ('prefix=', None, "installation prefix"),
50 ("zip-ok", "z", "install package as a zipfile"),
51 ("multi-version", "m", "make apps have to require() a version"),
52 ("upgrade", "U", "force upgrade (searches PyPI for latest versions)"),
53 ("install-dir=", "d", "install package to DIR"),
54 ("script-dir=", "s", "install scripts to DIR"),
55 ("exclude-scripts", "x", "Don't install scripts"),
56 ("always-copy", "a", "Copy all needed packages to install dir"),
57 ("index-url=", "i", "base URL of Python Package Index"),
58 ("find-links=", "f", "additional URL(s) to search for packages"),
59 ("delete-conflicting", "D", "no longer needed; don't use this"),
60 ("ignore-conflicts-at-my-risk", None,
61 "no longer needed; don't use this"),
62 ("build-directory=", "b",
63 "download/extract/build in DIR; keep the results"),
65 "also compile with optimization: -O1 for \"python -O\", "
66 "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"),
68 "filename in which to record list of installed files"),
69 ('always-unzip', 'Z', "don't install as a zipfile, no matter what"),
70 ('site-dirs=','S',"list of directories where .pth files work"),
71 ('editable', 'e', "Install specified packages in editable form"),
72 ('no-deps', 'N', "don't install dependencies"),
73 ('allow-hosts=', 'H', "pattern(s) that hostnames must match"),
74 ('local-snapshots-ok', 'l', "allow building eggs from local checkouts"),
77 'zip-ok', 'multi-version', 'exclude-scripts', 'upgrade', 'always-copy',
78 'delete-conflicting', 'ignore-conflicts-at-my-risk', 'editable',
79 'no-deps', 'local-snapshots-ok',
81 negative_opt = {'always-unzip': 'zip-ok'}
82 create_index = PackageIndex
84 def initialize_options(self):
85 self.zip_ok = self.local_snapshots_ok = None
86 self.install_dir = self.script_dir = self.exclude_scripts = None
88 self.find_links = None
89 self.build_directory = None
91 self.optimize = self.record = None
92 self.upgrade = self.always_copy = self.multi_version = None
93 self.editable = self.no_deps = self.allow_hosts = None
94 self.root = self.prefix = self.no_report = None
96 # Options not specifiable via command line
97 self.package_index = None
98 self.pth_file = self.always_copy_from = None
99 self.delete_conflicting = None
100 self.ignore_conflicts_at_my_risk = None
101 self.site_dirs = None
102 self.installed_projects = {}
103 self.sitepy_installed = False
104 # Always read easy_install options, even if we are subclassed, or have
105 # an independent instance created. This ensures that defaults will
106 # always come from the standard configuration file(s)' "easy_install"
107 # section, even if this is a "develop" or "install" command, or some
110 self.verbose = self.distribution.verbose
111 self.distribution._set_command_options(
112 self, self.distribution.get_option_dict('easy_install')
115 def delete_blockers(self, blockers):
116 for filename in blockers:
117 if os.path.exists(filename) or os.path.islink(filename):
118 log.info("Deleting %s", filename)
120 if os.path.isdir(filename) and not os.path.islink(filename):
125 def finalize_options(self):
126 self._expand('install_dir','script_dir','build_directory','site_dirs')
127 # If a non-default installation directory was specified, default the
128 # script directory to match it.
129 if self.script_dir is None:
130 self.script_dir = self.install_dir
132 # Let install_dir get set by install_lib command, which in turn
133 # gets its info from the install command, and takes into account
134 # --prefix and --home and all that other crud.
135 self.set_undefined_options('install_lib',
136 ('install_dir','install_dir')
138 # Likewise, set default script_dir from 'install_scripts.install_dir'
139 self.set_undefined_options('install_scripts',
140 ('install_dir', 'script_dir')
142 # default --record from the install command
143 self.set_undefined_options('install', ('record', 'record'))
144 normpath = map(normalize_path, sys.path)
145 self.all_site_dirs = get_site_dirs()
146 if self.site_dirs is not None:
148 os.path.expanduser(s.strip()) for s in self.site_dirs.split(',')
151 if not os.path.isdir(d):
152 log.warn("%s (in --site-dirs) does not exist", d)
153 elif normalize_path(d) not in normpath:
154 raise DistutilsOptionError(
155 d+" (in --site-dirs) is not on sys.path"
158 self.all_site_dirs.append(normalize_path(d))
159 if not self.editable: self.check_site_dir()
160 self.index_url = self.index_url or "http://pypi.python.org/simple"
161 self.shadow_path = self.all_site_dirs[:]
162 for path_item in self.install_dir, normalize_path(self.script_dir):
163 if path_item not in self.shadow_path:
164 self.shadow_path.insert(0, path_item)
166 if self.allow_hosts is not None:
167 hosts = [s.strip() for s in self.allow_hosts.split(',')]
170 if self.package_index is None:
171 self.package_index = self.create_index(
172 self.index_url, search_path = self.shadow_path+sys.path, hosts=hosts,
174 self.local_index = Environment(self.shadow_path+sys.path)
176 if self.find_links is not None:
177 if isinstance(self.find_links, basestring):
178 self.find_links = self.find_links.split()
181 if self.local_snapshots_ok:
182 self.package_index.scan_egg_links(self.shadow_path+sys.path)
183 self.package_index.add_find_links(self.find_links)
184 self.set_undefined_options('install_lib', ('optimize','optimize'))
185 if not isinstance(self.optimize,int):
187 self.optimize = int(self.optimize)
188 if not (0 <= self.optimize <= 2): raise ValueError
190 raise DistutilsOptionError("--optimize must be 0, 1, or 2")
192 if self.delete_conflicting and self.ignore_conflicts_at_my_risk:
193 raise DistutilsOptionError(
194 "Can't use both --delete-conflicting and "
195 "--ignore-conflicts-at-my-risk at the same time"
197 if self.editable and not self.build_directory:
198 raise DistutilsArgError(
199 "Must specify a build directory (-b) when using --editable"
202 raise DistutilsArgError(
203 "No urls, filenames, or requirements specified (see --help)")
208 if self.verbose!=self.distribution.verbose:
209 log.set_verbosity(self.verbose)
211 for spec in self.args:
212 self.easy_install(spec, not self.no_deps)
214 outputs = self.outputs
215 if self.root: # strip any package prefix
216 root_len = len(self.root)
217 for counter in xrange(len(outputs)):
218 outputs[counter] = outputs[counter][root_len:]
219 from distutils import file_util
221 file_util.write_file, (self.record, outputs),
222 "writing list of installed files to '%s'" %
225 self.warn_deprecated_options()
227 log.set_verbosity(self.distribution.verbose)
229 def pseudo_tempname(self):
230 """Return a pseudo-tempname base in the install directory.
231 This code is intentionally naive; if a malicious party can write to
232 the target directory you're already in deep doodoo.
237 pid = random.randint(0,sys.maxint)
238 return os.path.join(self.install_dir, "test-easy-install-%s" % pid)
240 def warn_deprecated_options(self):
241 if self.delete_conflicting or self.ignore_conflicts_at_my_risk:
243 "Note: The -D, --delete-conflicting and"
244 " --ignore-conflicts-at-my-risk no longer have any purpose"
245 " and should not be used."
248 def check_site_dir(self):
249 """Verify that self.install_dir is .pth-capable dir, if needed"""
250 instdir = normalize_path(self.install_dir)
251 pth_file = os.path.join(instdir,'easy-install.pth')
253 # mkdir it if necessary
257 # Oh well -- hopefully this error simply means that it is already there.
258 # If not the subsequent write test will identify the problem.
260 # add it to site dirs
261 self.all_site_dirs.append(instdir)
263 # Is it a configured, PYTHONPATH, implicit, or explicit site dir?
264 is_site_dir = instdir in self.all_site_dirs
266 if not is_site_dir and not self.multi_version:
267 # No? Then directly test whether it does .pth file processing
268 is_site_dir = self.check_pth_processing()
270 # make sure we can write to target dir
271 testfile = self.pseudo_tempname()+'.write-test'
272 test_exists = os.path.exists(testfile)
274 if test_exists: os.unlink(testfile)
275 open(testfile,'w').close()
277 except (OSError,IOError):
278 self.cant_write_to_target()
280 if not is_site_dir and not self.multi_version:
281 # Can't install non-multi to non-site dir
282 log.warn(self.no_default_version_msg())
285 if self.pth_file is None:
286 self.pth_file = PthDistributions(pth_file, self.all_site_dirs)
290 if self.multi_version and not os.path.exists(pth_file):
291 self.sitepy_installed = True # don't need site.py in this case
292 self.pth_file = None # and don't create a .pth file
293 self.install_dir = instdir
295 def cant_write_to_target(self):
296 msg = """can't create or remove files in install directory
298 The following error occurred while trying to add or remove files in the
299 installation directory:
303 The installation directory you specified (via --install-dir, --prefix, or
304 the distutils default setting) was:
307 """ % (sys.exc_info()[1], self.install_dir,)
309 if not os.path.exists(self.install_dir):
311 This directory does not currently exist. Please create it and try again, or
312 choose a different installation directory (using the -d or --install-dir
317 Perhaps your account does not have write access to this directory? If the
318 installation directory is a system-owned directory, you may need to sign in
319 as the administrator or "root" account. If you do not have administrative
320 access to this machine, you may wish to choose a different installation
321 directory, preferably one that is listed in your PYTHONPATH environment
324 For information on other options, you may wish to consult the
327 http://peak.telecommunity.com/EasyInstall.html
329 Please make the appropriate changes for your system and try again.
331 raise DistutilsError(msg)
336 def check_pth_processing(self):
337 """Empirically verify whether .pth files are supported in inst. dir"""
338 instdir = self.install_dir
339 log.info("Checking .pth file support in %s", instdir)
340 pth_file = self.pseudo_tempname()+".pth"
341 ok_file = pth_file+'.ok'
342 ok_exists = os.path.exists(ok_file)
344 if ok_exists: os.unlink(ok_file)
345 f = open(pth_file,'w')
346 except (OSError,IOError):
347 self.cant_write_to_target()
350 f.write("import os;open(%r,'w').write('OK')\n" % (ok_file,))
352 executable = sys.executable
354 dirname,basename = os.path.split(executable)
355 alt = os.path.join(dirname,'pythonw.exe')
356 if basename.lower()=='python.exe' and os.path.exists(alt):
357 # use pythonw.exe to avoid opening a console window
360 from distutils.spawn import spawn
361 spawn([executable,'-E','-c','pass'],0)
363 if os.path.exists(ok_file):
365 "TEST PASSED: %s appears to support .pth files",
371 if os.path.exists(ok_file): os.unlink(ok_file)
372 if os.path.exists(pth_file): os.unlink(pth_file)
373 if not self.multi_version:
374 log.warn("TEST FAILED: %s does NOT support .pth files", instdir)
377 def install_egg_scripts(self, dist):
378 """Write all the scripts for `dist`, unless scripts are excluded"""
379 if not self.exclude_scripts and dist.metadata_isdir('scripts'):
380 for script_name in dist.metadata_listdir('scripts'):
383 dist.get_metadata('scripts/'+script_name)
385 self.install_wrapper_scripts(dist)
387 def add_output(self, path):
388 if os.path.isdir(path):
389 for base, dirs, files in os.walk(path):
390 for filename in files:
391 self.outputs.append(os.path.join(base,filename))
393 self.outputs.append(path)
395 def not_editable(self, spec):
397 raise DistutilsArgError(
398 "Invalid argument %r: you can't use filenames or URLs "
399 "with --editable (except via the --find-links option)."
403 def check_editable(self,spec):
404 if not self.editable:
407 if os.path.exists(os.path.join(self.build_directory, spec.key)):
408 raise DistutilsArgError(
409 "%r already exists in %s; can't do a checkout there" %
410 (spec.key, self.build_directory)
418 def easy_install(self, spec, deps=False):
419 tmpdir = tempfile.mkdtemp(prefix="easy_install-")
421 if not self.editable: self.install_site_py()
424 if not isinstance(spec,Requirement):
426 # It's a url, download it to tmpdir and process
427 self.not_editable(spec)
428 download = self.package_index.download(spec, tmpdir)
429 return self.install_item(None, download, tmpdir, deps, True)
431 elif os.path.exists(spec):
432 # Existing file or directory, just process it directly
433 self.not_editable(spec)
434 return self.install_item(None, spec, tmpdir, deps, True)
436 spec = parse_requirement_arg(spec)
438 self.check_editable(spec)
439 dist = self.package_index.fetch_distribution(
440 spec, tmpdir, self.upgrade, self.editable, not self.always_copy,
444 msg = "Could not find suitable distribution for %r" % spec
446 msg+=" (--always-copy skips system and development eggs)"
447 raise DistutilsError(msg)
448 elif dist.precedence==DEVELOP_DIST:
449 # .egg-info dists don't need installing, just process deps
450 self.process_distribution(spec, dist, deps, "Using")
453 return self.install_item(spec, dist.location, tmpdir, deps)
456 if os.path.exists(tmpdir):
459 def install_item(self, spec, download, tmpdir, deps, install_needed=False):
461 # Installation is also needed if file in tmpdir or is not an egg
462 install_needed = install_needed or self.always_copy
463 install_needed = install_needed or os.path.dirname(download) == tmpdir
464 install_needed = install_needed or not download.endswith('.egg')
465 install_needed = install_needed or (
466 self.always_copy_from is not None and
467 os.path.dirname(normalize_path(download)) ==
468 normalize_path(self.always_copy_from)
471 if spec and not install_needed:
472 # at this point, we know it's a local .egg, we just don't know if
473 # it's already installed.
474 for dist in self.local_index[spec.project_name]:
475 if dist.location==download:
478 install_needed = True # it's not in the local index
480 log.info("Processing %s", os.path.basename(download))
483 dists = self.install_eggs(spec, download, tmpdir)
485 self.process_distribution(spec, dist, deps)
487 dists = [self.check_conflicts(self.egg_distribution(download))]
488 self.process_distribution(spec, dists[0], deps, "Using")
500 def process_distribution(self, requirement, dist, deps=True, *info):
501 self.update_pth(dist)
502 self.package_index.add(dist)
503 self.local_index.add(dist)
504 self.install_egg_scripts(dist)
505 self.installed_projects[dist.key] = dist
506 log.info(self.installation_report(requirement, dist, *info))
507 if dist.has_metadata('dependency_links.txt'):
508 self.package_index.add_find_links(
509 dist.get_metadata_lines('dependency_links.txt')
511 if not deps and not self.always_copy:
513 elif requirement is not None and dist.key != requirement.key:
514 log.warn("Skipping dependencies for %s", dist)
515 return # XXX this is not the distribution we were looking for
516 elif requirement is None or dist not in requirement:
517 # if we wound up with a different version, resolve what we've got
518 distreq = dist.as_requirement()
519 requirement = requirement or distreq
520 requirement = Requirement(
521 distreq.project_name, distreq.specs, requirement.extras
523 log.info("Processing dependencies for %s", requirement)
525 distros = WorkingSet([]).resolve(
526 [requirement], self.local_index, self.easy_install
528 except DistributionNotFound, e:
529 raise DistutilsError(
530 "Could not find required distribution %s" % e.args
532 except VersionConflict, e:
533 raise DistutilsError(
534 "Installed distribution %s conflicts with requirement %s"
537 if self.always_copy or self.always_copy_from:
538 # Force all the relevant distros to be copied or activated
540 if dist.key not in self.installed_projects:
541 self.easy_install(dist.as_requirement())
542 log.info("Finished processing dependencies for %s", requirement)
544 def should_unzip(self, dist):
545 if self.zip_ok is not None:
546 return not self.zip_ok
547 if dist.has_metadata('not-zip-safe'):
549 if not dist.has_metadata('zip-safe'):
553 def maybe_move(self, spec, dist_filename, setup_base):
554 dst = os.path.join(self.build_directory, spec.key)
555 if os.path.exists(dst):
557 "%r already exists in %s; build directory %s will not be kept",
558 spec.key, self.build_directory, setup_base
561 if os.path.isdir(dist_filename):
562 setup_base = dist_filename
564 if os.path.dirname(dist_filename)==setup_base:
565 os.unlink(dist_filename) # get it out of the tmp dir
566 contents = os.listdir(setup_base)
568 dist_filename = os.path.join(setup_base,contents[0])
569 if os.path.isdir(dist_filename):
570 # if the only thing there is a directory, move it instead
571 setup_base = dist_filename
572 ensure_directory(dst); shutil.move(setup_base, dst)
575 def install_wrapper_scripts(self, dist):
576 if not self.exclude_scripts:
577 for args in get_script_args(dist, script_dir=self.script_dir):
578 self.write_script(*args)
582 def install_script(self, dist, script_name, script_text, dev_path=None):
583 """Generate a legacy script wrapper and install it"""
584 spec = str(dist.as_requirement())
585 is_script = is_python_script(script_text, script_name)
587 requires = [spec] + [str(r) for r in dist.requires()]
588 if is_script and dev_path:
589 script_text = get_script_header(script_text) + (
590 "# EASY-INSTALL-DEV-SCRIPT: %(spec)r,%(script_name)r\n"
591 "__requires__ = %(requires)r\n"
592 "from pkg_resources import require; require(%(spec)r)\n"
594 "__file__ = %(dev_path)r\n"
595 "execfile(__file__)\n"
598 script_text = get_script_header(script_text) + (
599 "# EASY-INSTALL-SCRIPT: %(spec)r,%(script_name)r\n"
600 "__requires__ = %(requires)r\n"
601 "import pkg_resources\n"
602 "pkg_resources.run_script(%(spec)r, %(script_name)r)\n"
604 self.write_script(script_name, script_text, 'b')
606 def write_script(self, script_name, contents, mode="t", blockers=()):
607 """Write an executable file to the scripts directory"""
608 self.delete_blockers( # clean up old .py/.pyw w/o a script
609 [os.path.join(self.script_dir,x) for x in blockers])
610 log.info("Installing %s script to %s", script_name, self.script_dir)
611 target = os.path.join(self.script_dir, script_name)
612 self.add_output(target)
615 ensure_directory(target)
616 f = open(target,"w"+mode)
624 def install_eggs(self, spec, dist_filename, tmpdir):
625 # .egg dirs or files are already built, so just return them
626 if dist_filename.lower().endswith('.egg'):
627 return [self.install_egg(dist_filename, tmpdir)]
628 elif dist_filename.lower().endswith('.exe'):
629 return [self.install_exe(dist_filename, tmpdir)]
631 # Anything else, try to extract and build
633 if os.path.isfile(dist_filename) and not dist_filename.endswith('.py'):
634 unpack_archive(dist_filename, tmpdir, self.unpack_progress)
635 elif os.path.isdir(dist_filename):
636 setup_base = os.path.abspath(dist_filename)
638 if (setup_base.startswith(tmpdir) # something we downloaded
639 and self.build_directory and spec is not None
641 setup_base = self.maybe_move(spec, dist_filename, setup_base)
643 # Find the setup.py file
644 setup_script = os.path.join(setup_base, 'setup.py')
646 if not os.path.exists(setup_script):
647 setups = glob(os.path.join(setup_base, '*', 'setup.py'))
649 raise DistutilsError(
650 "Couldn't find a setup script in %s" % os.path.abspath(dist_filename)
653 raise DistutilsError(
654 "Multiple setup scripts in %s" % os.path.abspath(dist_filename)
656 setup_script = setups[0]
658 # Now run it, and return the result
660 log.info(self.report_editable(spec, setup_script))
663 return self.build_and_install(setup_script, setup_base)
665 def egg_distribution(self, egg_path):
666 if os.path.isdir(egg_path):
667 metadata = PathMetadata(egg_path,os.path.join(egg_path,'EGG-INFO'))
669 metadata = EggMetadata(zipimport.zipimporter(egg_path))
670 return Distribution.from_filename(egg_path,metadata=metadata)
672 def install_egg(self, egg_path, tmpdir):
673 destination = os.path.join(self.install_dir,os.path.basename(egg_path))
674 destination = os.path.abspath(destination)
676 ensure_directory(destination)
678 dist = self.egg_distribution(egg_path)
679 self.check_conflicts(dist)
680 if not samefile(egg_path, destination):
681 if os.path.isdir(destination) and not os.path.islink(destination):
682 dir_util.remove_tree(destination, dry_run=self.dry_run)
683 elif os.path.exists(destination):
684 self.execute(os.unlink,(destination,),"Removing "+destination)
685 uncache_zipdir(destination)
686 if os.path.isdir(egg_path):
687 if egg_path.startswith(tmpdir):
688 f,m = shutil.move, "Moving"
690 f,m = shutil.copytree, "Copying"
691 elif self.should_unzip(dist):
692 self.mkpath(destination)
693 f,m = self.unpack_and_compile, "Extracting"
694 elif egg_path.startswith(tmpdir):
695 f,m = shutil.move, "Moving"
697 f,m = shutil.copy2, "Copying"
699 self.execute(f, (egg_path, destination),
701 (os.path.basename(egg_path),os.path.dirname(destination)))
703 self.add_output(destination)
704 return self.egg_distribution(destination)
706 def install_exe(self, dist_filename, tmpdir):
707 # See if it's valid, get data
708 cfg = extract_wininst_cfg(dist_filename)
710 raise DistutilsError(
711 "%s is not a valid distutils Windows .exe" % dist_filename
713 # Create a dummy distribution object until we build the real distro
714 dist = Distribution(None,
715 project_name=cfg.get('metadata','name'),
716 version=cfg.get('metadata','version'), platform="win32"
719 # Convert the .exe to an unpacked egg
720 egg_path = dist.location = os.path.join(tmpdir, dist.egg_name()+'.egg')
721 egg_tmp = egg_path+'.tmp'
722 egg_info = os.path.join(egg_tmp, 'EGG-INFO')
723 pkg_inf = os.path.join(egg_info, 'PKG-INFO')
724 ensure_directory(pkg_inf) # make sure EGG-INFO dir exists
725 dist._provider = PathMetadata(egg_tmp, egg_info) # XXX
726 self.exe_to_egg(dist_filename, egg_tmp)
728 # Write EGG-INFO/PKG-INFO
729 if not os.path.exists(pkg_inf):
730 f = open(pkg_inf,'w')
731 f.write('Metadata-Version: 1.0\n')
732 for k,v in cfg.items('metadata'):
733 if k!='target_version':
734 f.write('%s: %s\n' % (k.replace('_','-').title(), v))
736 script_dir = os.path.join(egg_info,'scripts')
737 self.delete_blockers( # delete entry-point scripts to avoid duping
738 [os.path.join(script_dir,args[0]) for args in get_script_args(dist)]
740 # Build .egg file from tmpdir
741 bdist_egg.make_zipfile(
742 egg_path, egg_tmp, verbose=self.verbose, dry_run=self.dry_run
745 return self.install_egg(egg_path, tmpdir)
747 def exe_to_egg(self, dist_filename, egg_tmp):
748 """Extract a bdist_wininst to the directories an egg would use"""
749 # Check for .pth file and set up prefix translations
750 prefixes = get_exe_prefixes(dist_filename)
754 def process(src,dst):
756 for old,new in prefixes:
757 if s.startswith(old):
758 src = new+src[len(old):]
759 parts = src.split('/')
760 dst = os.path.join(egg_tmp, *parts)
762 if dl.endswith('.pyd') or dl.endswith('.dll'):
763 parts[-1] = bdist_egg.strip_module(parts[-1])
764 top_level[os.path.splitext(parts[0])[0]] = 1
765 native_libs.append(src)
766 elif dl.endswith('.py') and old!='SCRIPTS/':
767 top_level[os.path.splitext(parts[0])[0]] = 1
768 to_compile.append(dst)
770 if not src.endswith('.pth'):
771 log.warn("WARNING: can't process %s", src)
773 # extract, tracking .pyd/.dll->native_libs and .py -> to_compile
774 unpack_archive(dist_filename, egg_tmp, process)
776 for res in native_libs:
777 if res.lower().endswith('.pyd'): # create stubs for .pyd's
778 parts = res.split('/')
780 parts[-1] = bdist_egg.strip_module(parts[-1])+'.py'
781 pyfile = os.path.join(egg_tmp, *parts)
782 to_compile.append(pyfile); stubs.append(pyfile)
783 bdist_egg.write_stub(resource, pyfile)
784 self.byte_compile(to_compile) # compile .py's
785 bdist_egg.write_safety_flag(os.path.join(egg_tmp,'EGG-INFO'),
786 bdist_egg.analyze_egg(egg_tmp, stubs)) # write zip-safety flag
788 for name in 'top_level','native_libs':
790 txt = os.path.join(egg_tmp, 'EGG-INFO', name+'.txt')
791 if not os.path.exists(txt):
792 open(txt,'w').write('\n'.join(locals()[name])+'\n')
794 def check_conflicts(self, dist):
795 """Verify that there are no conflicting "old-style" packages"""
797 return dist # XXX temporarily disable until new strategy is stable
798 from imp import find_module, get_suffixes
799 from glob import glob
802 names = dict.fromkeys(dist._get_metadata('top_level.txt')) # XXX private attr
804 exts = {'.pyc':1, '.pyo':1} # get_suffixes() might leave one out
805 for ext,mode,typ in get_suffixes():
808 for path,files in expand_paths([self.install_dir]+self.all_site_dirs):
809 for filename in files:
810 base,ext = os.path.splitext(filename)
813 # no extension, check for package
815 f, filename, descr = find_module(base, [path])
820 if filename not in blockers:
821 blockers.append(filename)
822 elif ext in exts and base!='site': # XXX ugh
823 blockers.append(os.path.join(path,filename))
825 self.found_conflicts(dist, blockers)
829 def found_conflicts(self, dist, blockers):
830 if self.delete_conflicting:
831 log.warn("Attempting to delete conflicting packages:")
832 return self.delete_blockers(blockers)
835 -------------------------------------------------------------------------
838 The following modules or packages have the same names as modules or
839 packages being installed, and will be *before* the installed packages in
840 Python's search path. You MUST remove all of the relevant files and
841 directories before you will be able to use the package(s) you are
846 """ % '\n '.join(blockers)
848 if self.ignore_conflicts_at_my_risk:
850 (Note: you can run EasyInstall on '%s' with the
851 --delete-conflicting option to attempt deletion of the above files
853 """ % dist.project_name
856 Note: you can attempt this installation again with EasyInstall, and use
857 either the --delete-conflicting (-D) option or the
858 --ignore-conflicts-at-my-risk option, to either delete the above files
859 and directories, or to ignore the conflicts, respectively. Note that if
860 you ignore the conflicts, the installed package(s) may not work.
863 -------------------------------------------------------------------------
865 sys.stderr.write(msg)
867 if not self.ignore_conflicts_at_my_risk:
868 raise DistutilsError("Installation aborted due to conflicts")
870 def installation_report(self, req, dist, what="Installed"):
871 """Helpful installation message for display to package users"""
872 msg = "\n%(what)s %(eggloc)s%(extras)s"
873 if self.multi_version and not self.no_report:
876 Because this distribution was installed --multi-version, before you can
877 import modules from this package in an application, you will need to
878 'import pkg_resources' and then use a 'require()' call similar to one of
879 these examples, in order to select the desired version:
881 pkg_resources.require("%(name)s") # latest installed version
882 pkg_resources.require("%(name)s==%(version)s") # this exact version
883 pkg_resources.require("%(name)s>=%(version)s") # this version or higher
885 if self.install_dir not in map(normalize_path,sys.path):
888 Note also that the installation directory must be on sys.path at runtime for
889 this to work. (e.g. by being the application's script directory, by being on
890 PYTHONPATH, or by being added to sys.path by your code.)
892 eggloc = dist.location
893 name = dist.project_name
894 version = dist.version
895 extras = '' # TODO: self.report_extras(req, dist)
896 return msg % locals()
898 def report_editable(self, spec, setup_script):
899 dirname = os.path.dirname(setup_script)
900 python = sys.executable
901 return """\nExtracted editable version of %(spec)s to %(dirname)s
903 If it uses setuptools in its setup script, you can activate it in
904 "development" mode by going to that directory and running::
906 %(python)s setup.py develop
908 See the setuptools documentation for the "develop" command for more info.
911 def run_setup(self, setup_script, setup_base, args):
912 sys.modules.setdefault('distutils.command.bdist_egg', bdist_egg)
913 sys.modules.setdefault('distutils.command.egg_info', egg_info)
917 v = 'v' * (self.verbose - 1)
924 "Running %s %s", setup_script[len(setup_base)+1:], ' '.join(args)
927 run_setup(setup_script, args)
928 except SystemExit, v:
929 raise DistutilsError("Setup script exited with %s" % (v.args[0],))
931 def build_and_install(self, setup_script, setup_base):
932 args = ['bdist_egg', '--dist-dir']
933 dist_dir = tempfile.mkdtemp(
934 prefix='egg-dist-tmp-', dir=os.path.dirname(setup_script)
937 args.append(dist_dir)
938 self.run_setup(setup_script, setup_base, args)
939 all_eggs = Environment([dist_dir])
942 for dist in all_eggs[key]:
943 eggs.append(self.install_egg(dist.location, setup_base))
944 if not eggs and not self.dry_run:
945 log.warn("No eggs found in %s (setup script problem?)",
950 log.set_verbosity(self.verbose) # restore our log verbosity
952 def update_pth(self,dist):
953 if self.pth_file is None:
956 for d in self.pth_file[dist.key]: # drop old entries
957 if self.multi_version or d.location != dist.location:
958 log.info("Removing %s from easy-install.pth file", d)
959 self.pth_file.remove(d)
960 if d.location in self.shadow_path:
961 self.shadow_path.remove(d.location)
963 if not self.multi_version:
964 if dist.location in self.pth_file.paths:
966 "%s is already the active version in easy-install.pth",
970 log.info("Adding %s to easy-install.pth file", dist)
971 self.pth_file.add(dist) # add new entry
972 if dist.location not in self.shadow_path:
973 self.shadow_path.append(dist.location)
979 if dist.key=='setuptools':
980 # Ensure that setuptools itself never becomes unavailable!
981 # XXX should this check for latest version?
982 filename = os.path.join(self.install_dir,'setuptools.pth')
983 if os.path.islink(filename): os.unlink(filename)
984 f = open(filename, 'wt')
985 f.write(self.pth_file.make_relative(dist.location)+'\n')
988 def unpack_progress(self, src, dst):
989 # Progress filter for unpacking
990 log.debug("Unpacking %s to %s", src, dst)
991 return dst # only unpack-and-compile skips files for dry run
993 def unpack_and_compile(self, egg_path, destination):
994 to_compile = []; to_chmod = []
997 if dst.endswith('.py') and not src.startswith('EGG-INFO/'):
998 to_compile.append(dst)
999 elif dst.endswith('.dll') or dst.endswith('.so'):
1000 to_chmod.append(dst)
1001 self.unpack_progress(src,dst)
1002 return not self.dry_run and dst or None
1004 unpack_archive(egg_path, destination, pf)
1005 self.byte_compile(to_compile)
1006 if not self.dry_run:
1008 mode = ((os.stat(f)[stat.ST_MODE]) | 0555) & 07755
1011 def byte_compile(self, to_compile):
1012 if _dont_write_bytecode:
1013 self.warn('byte-compiling is disabled, skipping.')
1015 from distutils.util import byte_compile
1017 # try to make the byte compile messages quieter
1018 log.set_verbosity(self.verbose - 1)
1020 byte_compile(to_compile, optimize=0, force=1, dry_run=self.dry_run)
1023 to_compile, optimize=self.optimize, force=1,
1024 dry_run=self.dry_run
1027 log.set_verbosity(self.verbose) # restore original verbosity
1037 def no_default_version_msg(self):
1038 return """bad install directory or PYTHONPATH
1040 You are attempting to install a package to a directory that is not
1041 on PYTHONPATH and which Python does not read ".pth" files from. The
1042 installation directory you specified (via --install-dir, --prefix, or
1043 the distutils default setting) was:
1047 and your PYTHONPATH environment variable currently contains:
1051 Here are some of your options for correcting the problem:
1053 * You can choose a different installation directory, i.e., one that is
1054 on PYTHONPATH or supports .pth files
1056 * You can add the installation directory to the PYTHONPATH environment
1057 variable. (It must then also be on PYTHONPATH whenever you run
1058 Python and want to use the package(s) you are installing.)
1060 * You can set up the installation directory to support ".pth" files by
1061 using one of the approaches described here:
1063 http://peak.telecommunity.com/EasyInstall.html#custom-installation-locations
1065 Proceeding to install. Please remember that unless you make one of
1066 these changes you will not be able to run the installed code.
1068 self.install_dir, os.environ.get('PYTHONPATH','')
1080 def install_site_py(self):
1081 """Make sure there's a site.py in the target dir, if needed"""
1083 if self.sitepy_installed:
1084 return # already did it, or don't need to
1086 sitepy = os.path.join(self.install_dir, "site.py")
1087 source = resource_string("setuptools", "site-patch.py")
1090 if os.path.exists(sitepy):
1091 log.debug("Checking existing site.py in %s", self.install_dir)
1092 current = open(sitepy,'rb').read()
1093 if not current.startswith('def __boot():'):
1095 "***********************************************************************\n"
1096 "Warning: %s is not a\n"
1097 "setuptools-generated site.py. It will not be overwritten.\n"
1098 "***********************************************************************\n"
1100 self.sitepy_installed = True
1103 if current != source:
1104 log.info("Creating %s", sitepy)
1105 if not self.dry_run:
1106 ensure_directory(sitepy)
1107 f = open(sitepy,'wb')
1110 self.byte_compile([sitepy])
1112 self.sitepy_installed = True
1125 INSTALL_SCHEMES = dict(
1127 install_dir = '$base/lib/python$py_version_short/site-packages',
1128 script_dir = '$base/bin',
1132 DEFAULT_SCHEME = dict(
1133 install_dir = '$base/Lib/site-packages',
1134 script_dir = '$base/Scripts',
1137 def _expand(self, *attrs):
1138 config_vars = self.get_finalized_command('install').config_vars
1141 # Set default install_dir/scripts from --prefix
1142 config_vars = config_vars.copy()
1143 config_vars['base'] = self.prefix
1144 scheme = self.INSTALL_SCHEMES.get(os.name,self.DEFAULT_SCHEME)
1145 for attr,val in scheme.items():
1146 if getattr(self,attr,None) is None:
1147 setattr(self,attr,val)
1149 from distutils.util import subst_vars
1151 val = getattr(self, attr)
1153 val = subst_vars(val, config_vars)
1154 if os.name == 'posix':
1155 val = os.path.expanduser(val)
1156 setattr(self, attr, val)
1166 def get_site_dirs():
1167 # return a list of 'site' dirs
1168 sitedirs = filter(None,os.environ.get('PYTHONPATH','').split(os.pathsep))
1169 prefixes = [sys.prefix]
1170 if sys.exec_prefix != sys.prefix:
1171 prefixes.append(sys.exec_prefix)
1172 for prefix in prefixes:
1174 if sys.platform in ('os2emx', 'riscos'):
1175 sitedirs.append(os.path.join(prefix, "Lib", "site-packages"))
1177 sitedirs.extend([os.path.join(prefix,
1179 "python" + sys.version[:3],
1181 os.path.join(prefix, "lib", "site-python")])
1184 [prefix, os.path.join(prefix, "lib", "site-packages")]
1186 if sys.platform == 'darwin':
1187 # for framework builds *only* we add the standard Apple
1188 # locations. Currently only per-user, but /Library and
1189 # /Network/Library could be added too
1190 if 'Python.framework' in prefix:
1191 home = os.environ.get('HOME')
1199 for plat_specific in (0,1):
1200 site_lib = get_python_lib(plat_specific)
1201 if site_lib not in sitedirs: sitedirs.append(site_lib)
1203 sitedirs = map(normalize_path, sitedirs)
1207 def expand_paths(inputs):
1208 """Yield sys.path directories that might contain "old-style" packages"""
1212 for dirname in inputs:
1213 dirname = normalize_path(dirname)
1218 if not os.path.isdir(dirname):
1221 files = os.listdir(dirname)
1222 yield dirname, files
1225 if not name.endswith('.pth'):
1226 # We only care about the .pth files
1228 if name in ('easy-install.pth','setuptools.pth'):
1229 # Ignore .pth files that we control
1232 # Read the .pth file
1233 f = open(os.path.join(dirname,name))
1234 lines = list(yield_lines(f))
1237 # Yield existing non-dupe, non-import directory lines from it
1239 if not line.startswith("import"):
1240 line = normalize_path(line.rstrip())
1241 if line not in seen:
1243 if not os.path.isdir(line):
1245 yield line, os.listdir(line)
1248 def extract_wininst_cfg(dist_filename):
1249 """Extract configuration data from a bdist_wininst .exe
1251 Returns a ConfigParser.RawConfigParser, or None
1253 f = open(dist_filename,'rb')
1255 endrec = zipfile._EndRecData(f)
1259 prepended = (endrec[9] - endrec[5]) - endrec[6]
1260 if prepended < 12: # no wininst data here
1262 f.seek(prepended-12)
1264 import struct, StringIO, ConfigParser
1265 tag, cfglen, bmlen = struct.unpack("<iii",f.read(12))
1266 if tag not in (0x1234567A, 0x1234567B):
1267 return None # not a valid tag
1269 f.seek(prepended-(12+cfglen))
1270 cfg = ConfigParser.RawConfigParser({'version':'','target_version':''})
1272 cfg.readfp(StringIO.StringIO(f.read(cfglen).split(chr(0),1)[0]))
1273 except ConfigParser.Error:
1275 if not cfg.has_section('metadata') or not cfg.has_section('Setup'):
1289 def get_exe_prefixes(exe_filename):
1290 """Get exe->egg path translations for a given .exe file"""
1293 ('PURELIB/', ''), ('PLATLIB/pywin32_system32', ''),
1295 ('SCRIPTS/', 'EGG-INFO/scripts/')
1297 z = zipfile.ZipFile(exe_filename)
1299 for info in z.infolist():
1300 name = info.filename
1301 parts = name.split('/')
1302 if len(parts)==3 and parts[2]=='PKG-INFO':
1303 if parts[1].endswith('.egg-info'):
1304 prefixes.insert(0,('/'.join(parts[:2]), 'EGG-INFO/'))
1306 if len(parts)!=2 or not name.endswith('.pth'):
1308 if name.endswith('-nspkg.pth'):
1310 if parts[0].upper() in ('PURELIB','PLATLIB'):
1311 for pth in yield_lines(z.read(name)):
1312 pth = pth.strip().replace('\\','/')
1313 if not pth.startswith('import'):
1314 prefixes.append((('%s/%s/' % (parts[0],pth)), ''))
1317 prefixes = [(x.lower(),y) for x, y in prefixes]
1318 prefixes.sort(); prefixes.reverse()
1322 def parse_requirement_arg(spec):
1324 return Requirement.parse(spec)
1326 raise DistutilsError(
1327 "Not a URL, existing file, or requirement spec: %r" % (spec,)
1330 class PthDistributions(Environment):
1331 """A .pth file with Distribution paths in it"""
1335 def __init__(self, filename, sitedirs=()):
1336 self.filename = filename; self.sitedirs=map(normalize_path, sitedirs)
1337 self.basedir = normalize_path(os.path.dirname(self.filename))
1338 self._load(); Environment.__init__(self, [], None, None)
1339 for path in yield_lines(self.paths):
1340 map(self.add, find_distributions(path, True))
1345 seen = dict.fromkeys(self.sitedirs)
1346 if os.path.isfile(self.filename):
1347 for line in open(self.filename,'rt'):
1348 if line.startswith('import'):
1351 path = line.rstrip()
1352 self.paths.append(path)
1353 if not path.strip() or path.strip().startswith('#'):
1355 # skip non-existent paths, in case somebody deleted a package
1356 # manually, and duplicate paths as well
1357 path = self.paths[-1] = normalize_path(
1358 os.path.join(self.basedir,path)
1360 if not os.path.exists(path) or path in seen:
1361 self.paths.pop() # skip it
1362 self.dirty = True # we cleaned up, so we're dirty now :)
1366 if self.paths and not saw_import:
1367 self.dirty = True # ensure anything we touch has import wrappers
1368 while self.paths and not self.paths[-1].strip():
1372 """Write changed .pth file back to disk"""
1376 data = '\n'.join(map(self.make_relative,self.paths))
1378 log.debug("Saving %s", self.filename)
1380 "import sys; sys.__plen = len(sys.path)\n"
1382 "import sys; new=sys.path[sys.__plen:];"
1383 " del sys.path[sys.__plen:];"
1384 " p=getattr(sys,'__egginsert',len(os.environ.get('PYTHONPATH','').split(os.pathsep))); sys.path[p:p]=new;"
1385 " sys.__egginsert = p+len(new)\n"
1388 if os.path.islink(self.filename):
1389 os.unlink(self.filename)
1390 f = open(self.filename,'wb')
1391 f.write(data); f.close()
1393 elif os.path.exists(self.filename):
1394 log.debug("Deleting empty %s", self.filename)
1395 os.unlink(self.filename)
1400 """Add `dist` to the distribution map"""
1401 if dist.location not in self.paths and dist.location not in self.sitedirs:
1402 self.paths.append(dist.location); self.dirty = True
1403 Environment.add(self,dist)
1405 def remove(self,dist):
1406 """Remove `dist` from the distribution map"""
1407 while dist.location in self.paths:
1408 self.paths.remove(dist.location); self.dirty = True
1409 Environment.remove(self,dist)
1412 def make_relative(self,path):
1413 npath, last = os.path.split(normalize_path(path))
1414 baselen = len(self.basedir)
1416 sep = os.altsep=='/' and '/' or os.sep
1417 while len(npath)>=baselen:
1418 if npath==self.basedir:
1419 parts.append(os.curdir)
1421 return sep.join(parts)
1422 npath, last = os.path.split(npath)
1427 def get_script_header(script_text, executable=sys_executable, wininst=False):
1428 """Create a #! line, getting options (if any) from script_text"""
1429 from distutils.command.build_scripts import first_line_re
1430 first = (script_text+'\n').splitlines()[0]
1431 match = first_line_re.match(first)
1434 options = match.group(1) or ''
1435 if options: options = ' '+options
1437 executable = "python.exe"
1439 executable = nt_quote_arg(executable)
1440 hdr = "#!%(executable)s%(options)s\n" % locals()
1441 if unicode(hdr,'ascii','ignore').encode('ascii') != hdr:
1442 # Non-ascii path to sys.executable, use -x to prevent warnings
1444 if options.strip().startswith('-'):
1445 options = ' -x'+options.strip()[1:]
1446 # else: punt, we can't do it, let the warning happen anyway
1449 executable = fix_jython_executable(executable, options)
1450 hdr = "#!%(executable)s%(options)s\n" % locals()
1453 def auto_chmod(func, arg, exc):
1454 if func is os.remove and os.name=='nt':
1455 chmod(arg, stat.S_IWRITE)
1457 exc = sys.exc_info()
1458 raise exc[0], (exc[1][0], exc[1][1] + (" %s %s" % (func,arg)))
1460 def uncache_zipdir(path):
1461 """Ensure that the importer caches dont have stale info for `path`"""
1462 from zipimport import _zip_directory_cache as zdc
1464 _uncache(path, sys.path_importer_cache)
1466 def _uncache(path, cache):
1470 path = normalize_path(path)
1472 if normalize_path(p)==path:
1476 def is_python(text, filename='<string>'):
1477 "Is this string a valid Python script?"
1479 compile(text, filename, 'exec')
1480 except (SyntaxError, TypeError):
1485 def is_sh(executable):
1486 """Determine if the specified executable is a .sh (contains a #! line)"""
1488 fp = open(executable)
1491 except (OSError,IOError): return executable
1492 return magic == '#!'
1494 def nt_quote_arg(arg):
1495 """Quote a command line argument according to Windows parsing rules"""
1501 needquote = (" " in arg) or ("\t" in arg)
1509 # double preceding backslashes, then add a \"
1510 result.append('\\' * (nb*2) + '\\"')
1514 result.append('\\' * nb)
1519 result.append('\\' * nb)
1522 result.append('\\' * nb) # double the trailing backslashes
1525 return ''.join(result)
1535 def is_python_script(script_text, filename):
1536 """Is this text, as a whole, a Python script? (as opposed to shell/bat/etc.
1538 if filename.endswith('.py') or filename.endswith('.pyw'):
1539 return True # extension says it's Python
1540 if is_python(script_text, filename):
1541 return True # it's syntactically valid Python
1542 if script_text.startswith('#!'):
1543 # It begins with a '#!' line, so check if 'python' is in it somewhere
1544 return 'python' in script_text.splitlines()[0].lower()
1546 return False # Not any Python I can recognize
1549 from os import chmod as _chmod
1551 # Jython compatibility
1552 def _chmod(*args): pass
1554 def chmod(path, mode):
1555 log.debug("changing mode of %s to %o", path, mode)
1559 log.debug("chmod failed: %s", e)
1561 def fix_jython_executable(executable, options):
1562 if sys.platform.startswith('java') and is_sh(executable):
1563 # Workaround Jython's sys.executable being a .sh (an invalid
1564 # shebang line interpreter)
1566 # Can't apply the workaround, leave it broken
1567 log.warn("WARNING: Unable to adapt shebang line for Jython,"
1568 " the following script is NOT executable\n"
1569 " see http://bugs.jython.org/issue1112 for"
1570 " more information.")
1572 return '/usr/bin/env %s' % executable
1576 def get_script_args(dist, executable=sys_executable, wininst=False, script_dir=None):
1577 """Yield write_script() argument tuples for a distribution's entrypoints"""
1578 spec = str(dist.as_requirement())
1579 requires = [spec] + [str(r) for r in dist.requires()]
1580 header = get_script_header("", executable, wininst)
1581 generated_by = "# generated by zetuptoolz %s" % (setuptools_version,)
1583 for group in 'console_scripts', 'gui_scripts':
1584 for name, ep in dist.get_entry_map(group).items():
1585 script_head, script_tail = ((
1586 "# EASY-INSTALL-ENTRY-SCRIPT: %(spec)r,%(group)r,%(name)r\n"
1587 "%(generated_by)s\n"
1588 "__requires__ = %(requires)r\n"
1590 "from pkg_resources import load_entry_point\n"
1594 " load_entry_point(%(spec)r, %(group)r, %(name)r)()\n"
1598 if wininst or sys.platform == "win32":
1599 # On Windows/wininst, add a .py[w] extension. Delete any existing
1600 # -script.py[w], .exe, and .exe.manifest.
1601 if group=='gui_scripts':
1603 old = ['','.pyw','-script.pyw','.exe','.exe.manifest']
1604 which_python = 'pythonw.exe'
1605 new_header = re.sub('(?i)python.exe', which_python, header)
1608 old = ['','.pyscript','.py','.pyc','.pyo','-script.py','.exe','.exe.manifest']
1609 which_python = 'python.exe'
1610 new_header = re.sub('(?i)pythonw.exe', which_python, header)
1614 "# If this script doesn't work for you, make sure that the %(ext)s\n"
1615 "# extension is included in the PATHEXT environment variable, and is\n"
1616 "# associated with %(which_python)s in the registry.\n"
1618 "if sys.argv[0].endswith(%(ext)r):\n"
1619 " sys.argv[0] = sys.argv[0][:-%(len_ext)r]\n"
1623 if os.path.exists(new_header[2:-1]) or sys.platform != 'win32':
1627 yield (name+ext, hdr + script_head + script_tail, 't', [name+x for x in old])
1629 # Also write a shell script that runs the .pyscript, for cygwin.
1631 # We can't use a Python script, because the Python interpreter that we want
1632 # to use is the native Windows one, which won't understand a cygwin path.
1633 # Windows paths written with forward slashes are universally understood
1634 # (by native Python, cygwin Python, and bash), so we'll use 'cygpath -m' to
1635 # get the directory from which the script was run in that form. This makes
1636 # the cygwin script and .pyscript position-independent, provided they are
1637 # in the same directory.
1640 return "\\'".join("'" + p.replace('\\', '/') + "'" for p in s.split("'"))
1642 pyscript = quote_path("/"+name+ext)
1643 python_path = quote_path(sys.executable)
1644 shell_script_text = (
1646 '%(generated_by)s\n'
1648 'ScriptDir=`cygpath -m "$0/.."`\n'
1649 '%(python_path)s "${ScriptDir}"%(pyscript)s "$@"\n'
1651 yield (name, shell_script_text, 'b')
1653 # On other platforms, we assume the right thing to do is to
1654 # just write the stub with no extension.
1655 yield (name, header + script_head + script_tail)
1658 def rmtree(path, ignore_errors=False, onerror=auto_chmod):
1659 """Recursively delete a directory tree.
1661 This code is taken from the Python 2.4 version of 'shutil', because
1662 the 2.3 version doesn't really work right.
1667 elif onerror is None:
1672 names = os.listdir(path)
1673 except os.error, err:
1674 onerror(os.listdir, path, sys.exc_info())
1676 fullname = os.path.join(path, name)
1678 mode = os.lstat(fullname).st_mode
1681 if stat.S_ISDIR(mode):
1682 rmtree(fullname, ignore_errors, onerror)
1686 except os.error, err:
1687 onerror(os.remove, fullname, sys.exc_info())
1691 onerror(os.rmdir, path, sys.exc_info())
1694 # This function is called when setuptools*.egg is run using /bin/sh
1695 import setuptools; argv0 = os.path.dirname(setuptools.__path__[0])
1696 sys.argv[0] = argv0; sys.argv.append(argv0); main()
1699 def main(argv=None, **kw):
1700 from setuptools import setup
1701 from setuptools.dist import Distribution
1702 import distutils.core
1705 usage: %(script)s [options] requirement_or_url ...
1706 or: %(script)s --help
1709 def gen_usage (script_name):
1710 script = os.path.basename(script_name)
1711 return USAGE % vars()
1713 def with_ei_usage(f):
1714 old_gen_usage = distutils.core.gen_usage
1716 distutils.core.gen_usage = gen_usage
1719 distutils.core.gen_usage = old_gen_usage
1721 class DistributionWithoutHelpCommands(Distribution):
1723 def _show_help(self,*args,**kw):
1724 with_ei_usage(lambda: Distribution._show_help(self,*args,**kw))
1729 with_ei_usage(lambda:
1731 script_args = ['-q','easy_install', '-v']+argv,
1732 script_name = sys.argv[0] or 'easy_install',
1733 distclass=DistributionWithoutHelpCommands, **kw