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
15 from setuptools.sandbox import run_setup
16 from distutils import log, dir_util
17 from distutils.sysconfig import get_python_lib
18 from distutils.errors import DistutilsArgError, DistutilsOptionError, \
20 from setuptools.archive_util import unpack_archive
21 from setuptools.package_index import PackageIndex, parse_bdist_wininst
22 from setuptools.package_index import URL_SCHEME
23 from setuptools.command import bdist_egg, egg_info
24 from pkg_resources import *
25 sys_executable = os.path.normpath(sys.executable)
28 'samefile', 'easy_install', 'PthDistributions', 'extract_wininst_cfg',
29 'main', 'get_exe_prefixes',
33 if hasattr(os.path,'samefile') and (
34 os.path.exists(p1) and os.path.exists(p2)
36 return os.path.samefile(p1,p2)
38 os.path.normpath(os.path.normcase(p1)) ==
39 os.path.normpath(os.path.normcase(p2))
42 class easy_install(Command):
43 """Manage a download/build/install process"""
44 description = "Find/get/install Python packages"
45 command_consumes_arguments = True
48 ('prefix=', None, "installation prefix"),
49 ("zip-ok", "z", "install package as a zipfile"),
50 ("multi-version", "m", "make apps have to require() a version"),
51 ("upgrade", "U", "force upgrade (searches PyPI for latest versions)"),
52 ("install-dir=", "d", "install package to DIR"),
53 ("script-dir=", "s", "install scripts to DIR"),
54 ("exclude-scripts", "x", "Don't install scripts"),
55 ("always-copy", "a", "Copy all needed packages to install dir"),
56 ("index-url=", "i", "base URL of Python Package Index"),
57 ("find-links=", "f", "additional URL(s) to search for packages"),
58 ("delete-conflicting", "D", "no longer needed; don't use this"),
59 ("ignore-conflicts-at-my-risk", None,
60 "no longer needed; don't use this"),
61 ("build-directory=", "b",
62 "download/extract/build in DIR; keep the results"),
64 "also compile with optimization: -O1 for \"python -O\", "
65 "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"),
67 "filename in which to record list of installed files"),
68 ('always-unzip', 'Z', "don't install as a zipfile, no matter what"),
69 ('site-dirs=','S',"list of directories where .pth files work"),
70 ('editable', 'e', "Install specified packages in editable form"),
71 ('no-deps', 'N', "don't install dependencies"),
72 ('allow-hosts=', 'H', "pattern(s) that hostnames must match"),
73 ('local-snapshots-ok', 'l', "allow building eggs from local checkouts"),
76 'zip-ok', 'multi-version', 'exclude-scripts', 'upgrade', 'always-copy',
77 'delete-conflicting', 'ignore-conflicts-at-my-risk', 'editable',
78 'no-deps', 'local-snapshots-ok',
80 negative_opt = {'always-unzip': 'zip-ok'}
81 create_index = PackageIndex
83 def initialize_options(self):
84 self.zip_ok = self.local_snapshots_ok = None
85 self.install_dir = self.script_dir = self.exclude_scripts = None
87 self.find_links = None
88 self.build_directory = None
90 self.optimize = self.record = None
91 self.upgrade = self.always_copy = self.multi_version = None
92 self.editable = self.no_deps = self.allow_hosts = None
93 self.root = self.prefix = self.no_report = None
95 # Options not specifiable via command line
96 self.package_index = None
97 self.pth_file = self.always_copy_from = None
98 self.delete_conflicting = None
99 self.ignore_conflicts_at_my_risk = None
100 self.site_dirs = None
101 self.installed_projects = {}
102 self.sitepy_installed = False
103 # Always read easy_install options, even if we are subclassed, or have
104 # an independent instance created. This ensures that defaults will
105 # always come from the standard configuration file(s)' "easy_install"
106 # section, even if this is a "develop" or "install" command, or some
109 self.verbose = self.distribution.verbose
110 self.distribution._set_command_options(
111 self, self.distribution.get_option_dict('easy_install')
114 def delete_blockers(self, blockers):
115 for filename in blockers:
116 if os.path.exists(filename) or os.path.islink(filename):
117 log.info("Deleting %s", filename)
119 if os.path.isdir(filename) and not os.path.islink(filename):
124 def finalize_options(self):
125 self._expand('install_dir','script_dir','build_directory','site_dirs')
126 # If a non-default installation directory was specified, default the
127 # script directory to match it.
128 if self.script_dir is None:
129 self.script_dir = self.install_dir
131 # Let install_dir get set by install_lib command, which in turn
132 # gets its info from the install command, and takes into account
133 # --prefix and --home and all that other crud.
134 self.set_undefined_options('install_lib',
135 ('install_dir','install_dir')
137 # Likewise, set default script_dir from 'install_scripts.install_dir'
138 self.set_undefined_options('install_scripts',
139 ('install_dir', 'script_dir')
141 # default --record from the install command
142 self.set_undefined_options('install', ('record', 'record'))
143 normpath = map(normalize_path, sys.path)
144 self.all_site_dirs = get_site_dirs()
145 if self.site_dirs is not None:
147 os.path.expanduser(s.strip()) for s in self.site_dirs.split(',')
150 if not os.path.isdir(d):
151 log.warn("%s (in --site-dirs) does not exist", d)
152 elif normalize_path(d) not in normpath:
153 raise DistutilsOptionError(
154 d+" (in --site-dirs) is not on sys.path"
157 self.all_site_dirs.append(normalize_path(d))
158 if not self.editable: self.check_site_dir()
159 self.index_url = self.index_url or "http://pypi.python.org/simple"
160 self.shadow_path = self.all_site_dirs[:]
161 for path_item in self.install_dir, normalize_path(self.script_dir):
162 if path_item not in self.shadow_path:
163 self.shadow_path.insert(0, path_item)
165 if self.allow_hosts is not None:
166 hosts = [s.strip() for s in self.allow_hosts.split(',')]
169 if self.package_index is None:
170 self.package_index = self.create_index(
171 self.index_url, search_path = self.shadow_path+sys.path, hosts=hosts,
173 self.local_index = Environment(self.shadow_path+sys.path)
175 if self.find_links is not None:
176 if isinstance(self.find_links, basestring):
177 self.find_links = self.find_links.split()
180 if self.local_snapshots_ok:
181 self.package_index.scan_egg_links(self.shadow_path+sys.path)
182 self.package_index.add_find_links(self.find_links)
183 self.set_undefined_options('install_lib', ('optimize','optimize'))
184 if not isinstance(self.optimize,int):
186 self.optimize = int(self.optimize)
187 if not (0 <= self.optimize <= 2): raise ValueError
189 raise DistutilsOptionError("--optimize must be 0, 1, or 2")
191 if self.delete_conflicting and self.ignore_conflicts_at_my_risk:
192 raise DistutilsOptionError(
193 "Can't use both --delete-conflicting and "
194 "--ignore-conflicts-at-my-risk at the same time"
196 if self.editable and not self.build_directory:
197 raise DistutilsArgError(
198 "Must specify a build directory (-b) when using --editable"
201 raise DistutilsArgError(
202 "No urls, filenames, or requirements specified (see --help)")
207 if self.verbose!=self.distribution.verbose:
208 log.set_verbosity(self.verbose)
210 for spec in self.args:
211 self.easy_install(spec, not self.no_deps)
213 outputs = self.outputs
214 if self.root: # strip any package prefix
215 root_len = len(self.root)
216 for counter in xrange(len(outputs)):
217 outputs[counter] = outputs[counter][root_len:]
218 from distutils import file_util
220 file_util.write_file, (self.record, outputs),
221 "writing list of installed files to '%s'" %
224 self.warn_deprecated_options()
226 log.set_verbosity(self.distribution.verbose)
228 def pseudo_tempname(self):
229 """Return a pseudo-tempname base in the install directory.
230 This code is intentionally naive; if a malicious party can write to
231 the target directory you're already in deep doodoo.
236 pid = random.randint(0,sys.maxint)
237 return os.path.join(self.install_dir, "test-easy-install-%s" % pid)
239 def warn_deprecated_options(self):
240 if self.delete_conflicting or self.ignore_conflicts_at_my_risk:
242 "Note: The -D, --delete-conflicting and"
243 " --ignore-conflicts-at-my-risk no longer have any purpose"
244 " and should not be used."
247 def check_site_dir(self):
248 """Verify that self.install_dir is .pth-capable dir, if needed"""
249 instdir = normalize_path(self.install_dir)
250 pth_file = os.path.join(instdir,'easy-install.pth')
252 # mkdir it if necessary
256 # Oh well -- hopefully this error simply means that it is already there.
257 # If not the subsequent write test will identify the problem.
259 # add it to site dirs
260 self.all_site_dirs.append(instdir)
262 # Is it a configured, PYTHONPATH, implicit, or explicit site dir?
263 is_site_dir = instdir in self.all_site_dirs
265 if not is_site_dir and not self.multi_version:
266 # No? Then directly test whether it does .pth file processing
267 is_site_dir = self.check_pth_processing()
269 # make sure we can write to target dir
270 testfile = self.pseudo_tempname()+'.write-test'
271 test_exists = os.path.exists(testfile)
273 if test_exists: os.unlink(testfile)
274 open(testfile,'w').close()
276 except (OSError,IOError):
277 self.cant_write_to_target()
279 if not is_site_dir and not self.multi_version:
280 # Can't install non-multi to non-site dir
281 log.warn(self.no_default_version_msg())
284 if self.pth_file is None:
285 self.pth_file = PthDistributions(pth_file, self.all_site_dirs)
289 if self.multi_version and not os.path.exists(pth_file):
290 self.sitepy_installed = True # don't need site.py in this case
291 self.pth_file = None # and don't create a .pth file
292 self.install_dir = instdir
294 def cant_write_to_target(self):
295 msg = """can't create or remove files in install directory
297 The following error occurred while trying to add or remove files in the
298 installation directory:
302 The installation directory you specified (via --install-dir, --prefix, or
303 the distutils default setting) was:
306 """ % (sys.exc_info()[1], self.install_dir,)
308 if not os.path.exists(self.install_dir):
310 This directory does not currently exist. Please create it and try again, or
311 choose a different installation directory (using the -d or --install-dir
316 Perhaps your account does not have write access to this directory? If the
317 installation directory is a system-owned directory, you may need to sign in
318 as the administrator or "root" account. If you do not have administrative
319 access to this machine, you may wish to choose a different installation
320 directory, preferably one that is listed in your PYTHONPATH environment
323 For information on other options, you may wish to consult the
326 http://peak.telecommunity.com/EasyInstall.html
328 Please make the appropriate changes for your system and try again.
330 raise DistutilsError(msg)
335 def check_pth_processing(self):
336 """Empirically verify whether .pth files are supported in inst. dir"""
337 instdir = self.install_dir
338 log.info("Checking .pth file support in %s", instdir)
339 pth_file = self.pseudo_tempname()+".pth"
340 ok_file = pth_file+'.ok'
341 ok_exists = os.path.exists(ok_file)
343 if ok_exists: os.unlink(ok_file)
344 f = open(pth_file,'w')
345 except (OSError,IOError):
346 self.cant_write_to_target()
349 f.write("import os;open(%r,'w').write('OK')\n" % (ok_file,))
351 executable = sys.executable
353 dirname,basename = os.path.split(executable)
354 alt = os.path.join(dirname,'pythonw.exe')
355 if basename.lower()=='python.exe' and os.path.exists(alt):
356 # use pythonw.exe to avoid opening a console window
359 from distutils.spawn import spawn
360 spawn([executable,'-E','-c','pass'],0)
362 if os.path.exists(ok_file):
364 "TEST PASSED: %s appears to support .pth files",
370 if os.path.exists(ok_file): os.unlink(ok_file)
371 if os.path.exists(pth_file): os.unlink(pth_file)
372 if not self.multi_version:
373 log.warn("TEST FAILED: %s does NOT support .pth files", instdir)
376 def install_egg_scripts(self, dist):
377 """Write all the scripts for `dist`, unless scripts are excluded"""
378 if not self.exclude_scripts and dist.metadata_isdir('scripts'):
379 for script_name in dist.metadata_listdir('scripts'):
382 dist.get_metadata('scripts/'+script_name)
384 self.install_wrapper_scripts(dist)
386 def add_output(self, path):
387 if os.path.isdir(path):
388 for base, dirs, files in os.walk(path):
389 for filename in files:
390 self.outputs.append(os.path.join(base,filename))
392 self.outputs.append(path)
394 def not_editable(self, spec):
396 raise DistutilsArgError(
397 "Invalid argument %r: you can't use filenames or URLs "
398 "with --editable (except via the --find-links option)."
402 def check_editable(self,spec):
403 if not self.editable:
406 if os.path.exists(os.path.join(self.build_directory, spec.key)):
407 raise DistutilsArgError(
408 "%r already exists in %s; can't do a checkout there" %
409 (spec.key, self.build_directory)
417 def easy_install(self, spec, deps=False):
418 tmpdir = tempfile.mkdtemp(prefix="easy_install-")
420 if not self.editable: self.install_site_py()
423 if not isinstance(spec,Requirement):
425 # It's a url, download it to tmpdir and process
426 self.not_editable(spec)
427 download = self.package_index.download(spec, tmpdir)
428 return self.install_item(None, download, tmpdir, deps, True)
430 elif os.path.exists(spec):
431 # Existing file or directory, just process it directly
432 self.not_editable(spec)
433 return self.install_item(None, spec, tmpdir, deps, True)
435 spec = parse_requirement_arg(spec)
437 self.check_editable(spec)
438 dist = self.package_index.fetch_distribution(
439 spec, tmpdir, self.upgrade, self.editable, not self.always_copy,
443 msg = "Could not find suitable distribution for %r" % spec
445 msg+=" (--always-copy skips system and development eggs)"
446 raise DistutilsError(msg)
447 elif dist.precedence==DEVELOP_DIST:
448 # .egg-info dists don't need installing, just process deps
449 self.process_distribution(spec, dist, deps, "Using")
452 return self.install_item(spec, dist.location, tmpdir, deps)
455 if os.path.exists(tmpdir):
458 def install_item(self, spec, download, tmpdir, deps, install_needed=False):
460 # Installation is also needed if file in tmpdir or is not an egg
461 install_needed = install_needed or self.always_copy
462 install_needed = install_needed or os.path.dirname(download) == tmpdir
463 install_needed = install_needed or not download.endswith('.egg')
464 install_needed = install_needed or (
465 self.always_copy_from is not None and
466 os.path.dirname(normalize_path(download)) ==
467 normalize_path(self.always_copy_from)
470 if spec and not install_needed:
471 # at this point, we know it's a local .egg, we just don't know if
472 # it's already installed.
473 for dist in self.local_index[spec.project_name]:
474 if dist.location==download:
477 install_needed = True # it's not in the local index
479 log.info("Processing %s", os.path.basename(download))
482 dists = self.install_eggs(spec, download, tmpdir)
484 self.process_distribution(spec, dist, deps)
486 dists = [self.check_conflicts(self.egg_distribution(download))]
487 self.process_distribution(spec, dists[0], deps, "Using")
499 def process_distribution(self, requirement, dist, deps=True, *info):
500 self.update_pth(dist)
501 self.package_index.add(dist)
502 self.local_index.add(dist)
503 self.install_egg_scripts(dist)
504 self.installed_projects[dist.key] = dist
505 log.info(self.installation_report(requirement, dist, *info))
506 if dist.has_metadata('dependency_links.txt'):
507 self.package_index.add_find_links(
508 dist.get_metadata_lines('dependency_links.txt')
510 if not deps and not self.always_copy:
512 elif requirement is not None and dist.key != requirement.key:
513 log.warn("Skipping dependencies for %s", dist)
514 return # XXX this is not the distribution we were looking for
515 elif requirement is None or dist not in requirement:
516 # if we wound up with a different version, resolve what we've got
517 distreq = dist.as_requirement()
518 requirement = requirement or distreq
519 requirement = Requirement(
520 distreq.project_name, distreq.specs, requirement.extras
522 log.info("Processing dependencies for %s", requirement)
524 distros = WorkingSet([]).resolve(
525 [requirement], self.local_index, self.easy_install
527 except DistributionNotFound, e:
528 raise DistutilsError(
529 "Could not find required distribution %s" % e.args
531 except VersionConflict, e:
532 raise DistutilsError(
533 "Installed distribution %s conflicts with requirement %s"
536 if self.always_copy or self.always_copy_from:
537 # Force all the relevant distros to be copied or activated
539 if dist.key not in self.installed_projects:
540 self.easy_install(dist.as_requirement())
541 log.info("Finished processing dependencies for %s", requirement)
543 def should_unzip(self, dist):
544 if self.zip_ok is not None:
545 return not self.zip_ok
546 if dist.has_metadata('not-zip-safe'):
548 if not dist.has_metadata('zip-safe'):
552 def maybe_move(self, spec, dist_filename, setup_base):
553 dst = os.path.join(self.build_directory, spec.key)
554 if os.path.exists(dst):
556 "%r already exists in %s; build directory %s will not be kept",
557 spec.key, self.build_directory, setup_base
560 if os.path.isdir(dist_filename):
561 setup_base = dist_filename
563 if os.path.dirname(dist_filename)==setup_base:
564 os.unlink(dist_filename) # get it out of the tmp dir
565 contents = os.listdir(setup_base)
567 dist_filename = os.path.join(setup_base,contents[0])
568 if os.path.isdir(dist_filename):
569 # if the only thing there is a directory, move it instead
570 setup_base = dist_filename
571 ensure_directory(dst); shutil.move(setup_base, dst)
574 def install_wrapper_scripts(self, dist):
575 if not self.exclude_scripts:
576 for args in get_script_args(dist):
577 self.write_script(*args)
581 def install_script(self, dist, script_name, script_text, dev_path=None):
582 """Generate a legacy script wrapper and install it"""
583 spec = str(dist.as_requirement())
584 is_script = is_python_script(script_text, script_name)
586 if is_script and dev_path:
587 script_text = get_script_header(script_text) + (
588 "# EASY-INSTALL-DEV-SCRIPT: %(spec)r,%(script_name)r\n"
589 "__requires__ = %(spec)r\n"
590 "from pkg_resources import require; require(%(spec)r)\n"
592 "__file__ = %(dev_path)r\n"
593 "execfile(__file__)\n"
596 script_text = get_script_header(script_text) + (
597 "# EASY-INSTALL-SCRIPT: %(spec)r,%(script_name)r\n"
598 "__requires__ = %(spec)r\n"
599 "import pkg_resources\n"
600 "pkg_resources.run_script(%(spec)r, %(script_name)r)\n"
602 self.write_script(script_name, script_text, 'b')
604 def write_script(self, script_name, contents, mode="t", blockers=()):
605 """Write an executable file to the scripts directory"""
606 self.delete_blockers( # clean up old .py/.pyw w/o a script
607 [os.path.join(self.script_dir,x) for x in blockers])
608 log.info("Installing %s script to %s", script_name, self.script_dir)
609 target = os.path.join(self.script_dir, script_name)
610 self.add_output(target)
613 ensure_directory(target)
614 f = open(target,"w"+mode)
622 def install_eggs(self, spec, dist_filename, tmpdir):
623 # .egg dirs or files are already built, so just return them
624 if dist_filename.lower().endswith('.egg'):
625 return [self.install_egg(dist_filename, tmpdir)]
626 elif dist_filename.lower().endswith('.exe'):
627 return [self.install_exe(dist_filename, tmpdir)]
629 # Anything else, try to extract and build
631 if os.path.isfile(dist_filename) and not dist_filename.endswith('.py'):
632 unpack_archive(dist_filename, tmpdir, self.unpack_progress)
633 elif os.path.isdir(dist_filename):
634 setup_base = os.path.abspath(dist_filename)
636 if (setup_base.startswith(tmpdir) # something we downloaded
637 and self.build_directory and spec is not None
639 setup_base = self.maybe_move(spec, dist_filename, setup_base)
641 # Find the setup.py file
642 setup_script = os.path.join(setup_base, 'setup.py')
644 if not os.path.exists(setup_script):
645 setups = glob(os.path.join(setup_base, '*', 'setup.py'))
647 raise DistutilsError(
648 "Couldn't find a setup script in %s" % os.path.abspath(dist_filename)
651 raise DistutilsError(
652 "Multiple setup scripts in %s" % os.path.abspath(dist_filename)
654 setup_script = setups[0]
656 # Now run it, and return the result
658 log.info(self.report_editable(spec, setup_script))
661 return self.build_and_install(setup_script, setup_base)
663 def egg_distribution(self, egg_path):
664 if os.path.isdir(egg_path):
665 metadata = PathMetadata(egg_path,os.path.join(egg_path,'EGG-INFO'))
667 metadata = EggMetadata(zipimport.zipimporter(egg_path))
668 return Distribution.from_filename(egg_path,metadata=metadata)
670 def install_egg(self, egg_path, tmpdir):
671 destination = os.path.join(self.install_dir,os.path.basename(egg_path))
672 destination = os.path.abspath(destination)
674 ensure_directory(destination)
676 dist = self.egg_distribution(egg_path)
677 self.check_conflicts(dist)
678 if not samefile(egg_path, destination):
679 if os.path.isdir(destination) and not os.path.islink(destination):
680 dir_util.remove_tree(destination, dry_run=self.dry_run)
681 elif os.path.exists(destination):
682 self.execute(os.unlink,(destination,),"Removing "+destination)
683 uncache_zipdir(destination)
684 if os.path.isdir(egg_path):
685 if egg_path.startswith(tmpdir):
686 f,m = shutil.move, "Moving"
688 f,m = shutil.copytree, "Copying"
689 elif self.should_unzip(dist):
690 self.mkpath(destination)
691 f,m = self.unpack_and_compile, "Extracting"
692 elif egg_path.startswith(tmpdir):
693 f,m = shutil.move, "Moving"
695 f,m = shutil.copy2, "Copying"
697 self.execute(f, (egg_path, destination),
699 (os.path.basename(egg_path),os.path.dirname(destination)))
701 self.add_output(destination)
702 return self.egg_distribution(destination)
704 def install_exe(self, dist_filename, tmpdir):
705 # See if it's valid, get data
706 cfg = extract_wininst_cfg(dist_filename)
708 raise DistutilsError(
709 "%s is not a valid distutils Windows .exe" % dist_filename
711 # Create a dummy distribution object until we build the real distro
712 dist = Distribution(None,
713 project_name=cfg.get('metadata','name'),
714 version=cfg.get('metadata','version'), platform="win32"
717 # Convert the .exe to an unpacked egg
718 egg_path = dist.location = os.path.join(tmpdir, dist.egg_name()+'.egg')
719 egg_tmp = egg_path+'.tmp'
720 egg_info = os.path.join(egg_tmp, 'EGG-INFO')
721 pkg_inf = os.path.join(egg_info, 'PKG-INFO')
722 ensure_directory(pkg_inf) # make sure EGG-INFO dir exists
723 dist._provider = PathMetadata(egg_tmp, egg_info) # XXX
724 self.exe_to_egg(dist_filename, egg_tmp)
726 # Write EGG-INFO/PKG-INFO
727 if not os.path.exists(pkg_inf):
728 f = open(pkg_inf,'w')
729 f.write('Metadata-Version: 1.0\n')
730 for k,v in cfg.items('metadata'):
731 if k!='target_version':
732 f.write('%s: %s\n' % (k.replace('_','-').title(), v))
734 script_dir = os.path.join(egg_info,'scripts')
735 self.delete_blockers( # delete entry-point scripts to avoid duping
736 [os.path.join(script_dir,args[0]) for args in get_script_args(dist)]
738 # Build .egg file from tmpdir
739 bdist_egg.make_zipfile(
740 egg_path, egg_tmp, verbose=self.verbose, dry_run=self.dry_run
743 return self.install_egg(egg_path, tmpdir)
745 def exe_to_egg(self, dist_filename, egg_tmp):
746 """Extract a bdist_wininst to the directories an egg would use"""
747 # Check for .pth file and set up prefix translations
748 prefixes = get_exe_prefixes(dist_filename)
752 def process(src,dst):
754 for old,new in prefixes:
755 if s.startswith(old):
756 src = new+src[len(old):]
757 parts = src.split('/')
758 dst = os.path.join(egg_tmp, *parts)
760 if dl.endswith('.pyd') or dl.endswith('.dll'):
761 parts[-1] = bdist_egg.strip_module(parts[-1])
762 top_level[os.path.splitext(parts[0])[0]] = 1
763 native_libs.append(src)
764 elif dl.endswith('.py') and old!='SCRIPTS/':
765 top_level[os.path.splitext(parts[0])[0]] = 1
766 to_compile.append(dst)
768 if not src.endswith('.pth'):
769 log.warn("WARNING: can't process %s", src)
771 # extract, tracking .pyd/.dll->native_libs and .py -> to_compile
772 unpack_archive(dist_filename, egg_tmp, process)
774 for res in native_libs:
775 if res.lower().endswith('.pyd'): # create stubs for .pyd's
776 parts = res.split('/')
778 parts[-1] = bdist_egg.strip_module(parts[-1])+'.py'
779 pyfile = os.path.join(egg_tmp, *parts)
780 to_compile.append(pyfile); stubs.append(pyfile)
781 bdist_egg.write_stub(resource, pyfile)
782 self.byte_compile(to_compile) # compile .py's
783 bdist_egg.write_safety_flag(os.path.join(egg_tmp,'EGG-INFO'),
784 bdist_egg.analyze_egg(egg_tmp, stubs)) # write zip-safety flag
786 for name in 'top_level','native_libs':
788 txt = os.path.join(egg_tmp, 'EGG-INFO', name+'.txt')
789 if not os.path.exists(txt):
790 open(txt,'w').write('\n'.join(locals()[name])+'\n')
792 def check_conflicts(self, dist):
793 """Verify that there are no conflicting "old-style" packages"""
795 return dist # XXX temporarily disable until new strategy is stable
796 from imp import find_module, get_suffixes
797 from glob import glob
800 names = dict.fromkeys(dist._get_metadata('top_level.txt')) # XXX private attr
802 exts = {'.pyc':1, '.pyo':1} # get_suffixes() might leave one out
803 for ext,mode,typ in get_suffixes():
806 for path,files in expand_paths([self.install_dir]+self.all_site_dirs):
807 for filename in files:
808 base,ext = os.path.splitext(filename)
811 # no extension, check for package
813 f, filename, descr = find_module(base, [path])
818 if filename not in blockers:
819 blockers.append(filename)
820 elif ext in exts and base!='site': # XXX ugh
821 blockers.append(os.path.join(path,filename))
823 self.found_conflicts(dist, blockers)
827 def found_conflicts(self, dist, blockers):
828 if self.delete_conflicting:
829 log.warn("Attempting to delete conflicting packages:")
830 return self.delete_blockers(blockers)
833 -------------------------------------------------------------------------
836 The following modules or packages have the same names as modules or
837 packages being installed, and will be *before* the installed packages in
838 Python's search path. You MUST remove all of the relevant files and
839 directories before you will be able to use the package(s) you are
844 """ % '\n '.join(blockers)
846 if self.ignore_conflicts_at_my_risk:
848 (Note: you can run EasyInstall on '%s' with the
849 --delete-conflicting option to attempt deletion of the above files
851 """ % dist.project_name
854 Note: you can attempt this installation again with EasyInstall, and use
855 either the --delete-conflicting (-D) option or the
856 --ignore-conflicts-at-my-risk option, to either delete the above files
857 and directories, or to ignore the conflicts, respectively. Note that if
858 you ignore the conflicts, the installed package(s) may not work.
861 -------------------------------------------------------------------------
863 sys.stderr.write(msg)
865 if not self.ignore_conflicts_at_my_risk:
866 raise DistutilsError("Installation aborted due to conflicts")
868 def installation_report(self, req, dist, what="Installed"):
869 """Helpful installation message for display to package users"""
870 msg = "\n%(what)s %(eggloc)s%(extras)s"
871 if self.multi_version and not self.no_report:
874 Because this distribution was installed --multi-version, before you can
875 import modules from this package in an application, you will need to
876 'import pkg_resources' and then use a 'require()' call similar to one of
877 these examples, in order to select the desired version:
879 pkg_resources.require("%(name)s") # latest installed version
880 pkg_resources.require("%(name)s==%(version)s") # this exact version
881 pkg_resources.require("%(name)s>=%(version)s") # this version or higher
883 if self.install_dir not in map(normalize_path,sys.path):
886 Note also that the installation directory must be on sys.path at runtime for
887 this to work. (e.g. by being the application's script directory, by being on
888 PYTHONPATH, or by being added to sys.path by your code.)
890 eggloc = dist.location
891 name = dist.project_name
892 version = dist.version
893 extras = '' # TODO: self.report_extras(req, dist)
894 return msg % locals()
896 def report_editable(self, spec, setup_script):
897 dirname = os.path.dirname(setup_script)
898 python = sys.executable
899 return """\nExtracted editable version of %(spec)s to %(dirname)s
901 If it uses setuptools in its setup script, you can activate it in
902 "development" mode by going to that directory and running::
904 %(python)s setup.py develop
906 See the setuptools documentation for the "develop" command for more info.
909 def run_setup(self, setup_script, setup_base, args):
910 sys.modules.setdefault('distutils.command.bdist_egg', bdist_egg)
911 sys.modules.setdefault('distutils.command.egg_info', egg_info)
915 v = 'v' * (self.verbose - 1)
922 "Running %s %s", setup_script[len(setup_base)+1:], ' '.join(args)
925 run_setup(setup_script, args)
926 except SystemExit, v:
927 raise DistutilsError("Setup script exited with %s" % (v.args[0],))
929 def build_and_install(self, setup_script, setup_base):
930 args = ['bdist_egg', '--dist-dir']
931 dist_dir = tempfile.mkdtemp(
932 prefix='egg-dist-tmp-', dir=os.path.dirname(setup_script)
935 args.append(dist_dir)
936 self.run_setup(setup_script, setup_base, args)
937 all_eggs = Environment([dist_dir])
940 for dist in all_eggs[key]:
941 eggs.append(self.install_egg(dist.location, setup_base))
942 if not eggs and not self.dry_run:
943 log.warn("No eggs found in %s (setup script problem?)",
948 log.set_verbosity(self.verbose) # restore our log verbosity
950 def update_pth(self,dist):
951 if self.pth_file is None:
954 for d in self.pth_file[dist.key]: # drop old entries
955 if self.multi_version or d.location != dist.location:
956 log.info("Removing %s from easy-install.pth file", d)
957 self.pth_file.remove(d)
958 if d.location in self.shadow_path:
959 self.shadow_path.remove(d.location)
961 if not self.multi_version:
962 if dist.location in self.pth_file.paths:
964 "%s is already the active version in easy-install.pth",
968 log.info("Adding %s to easy-install.pth file", dist)
969 self.pth_file.add(dist) # add new entry
970 if dist.location not in self.shadow_path:
971 self.shadow_path.append(dist.location)
977 if dist.key=='setuptools':
978 # Ensure that setuptools itself never becomes unavailable!
979 # XXX should this check for latest version?
980 filename = os.path.join(self.install_dir,'setuptools.pth')
981 if os.path.islink(filename): os.unlink(filename)
982 f = open(filename, 'wt')
983 f.write(self.pth_file.make_relative(dist.location)+'\n')
986 def unpack_progress(self, src, dst):
987 # Progress filter for unpacking
988 log.debug("Unpacking %s to %s", src, dst)
989 return dst # only unpack-and-compile skips files for dry run
991 def unpack_and_compile(self, egg_path, destination):
992 to_compile = []; to_chmod = []
995 if dst.endswith('.py') and not src.startswith('EGG-INFO/'):
996 to_compile.append(dst)
997 elif dst.endswith('.dll') or dst.endswith('.so'):
999 self.unpack_progress(src,dst)
1000 return not self.dry_run and dst or None
1002 unpack_archive(egg_path, destination, pf)
1003 self.byte_compile(to_compile)
1004 if not self.dry_run:
1006 mode = ((os.stat(f)[stat.ST_MODE]) | 0555) & 07755
1009 def byte_compile(self, to_compile):
1010 from distutils.util import byte_compile
1012 # try to make the byte compile messages quieter
1013 log.set_verbosity(self.verbose - 1)
1015 byte_compile(to_compile, optimize=0, force=1, dry_run=self.dry_run)
1018 to_compile, optimize=self.optimize, force=1,
1019 dry_run=self.dry_run
1022 log.set_verbosity(self.verbose) # restore original verbosity
1032 def no_default_version_msg(self):
1033 return """bad install directory or PYTHONPATH
1035 You are attempting to install a package to a directory that is not
1036 on PYTHONPATH and which Python does not read ".pth" files from. The
1037 installation directory you specified (via --install-dir, --prefix, or
1038 the distutils default setting) was:
1042 and your PYTHONPATH environment variable currently contains:
1046 Here are some of your options for correcting the problem:
1048 * You can choose a different installation directory, i.e., one that is
1049 on PYTHONPATH or supports .pth files
1051 * You can add the installation directory to the PYTHONPATH environment
1052 variable. (It must then also be on PYTHONPATH whenever you run
1053 Python and want to use the package(s) you are installing.)
1055 * You can set up the installation directory to support ".pth" files by
1056 using one of the approaches described here:
1058 http://peak.telecommunity.com/EasyInstall.html#custom-installation-locations
1060 Proceeding to install. Please remember that unless you make one of
1061 these changes you will not be able to run the installed code.
1063 self.install_dir, os.environ.get('PYTHONPATH','')
1075 def install_site_py(self):
1076 """Make sure there's a site.py in the target dir, if needed"""
1078 if self.sitepy_installed:
1079 return # already did it, or don't need to
1081 sitepy = os.path.join(self.install_dir, "site.py")
1082 source = resource_string("setuptools", "site-patch.py")
1085 if os.path.exists(sitepy):
1086 log.debug("Checking existing site.py in %s", self.install_dir)
1087 current = open(sitepy,'rb').read()
1088 if not current.startswith('def __boot():'):
1089 raise DistutilsError(
1090 "%s is not a setuptools-generated site.py; please"
1091 " remove it." % sitepy
1094 if current != source:
1095 log.info("Creating %s", sitepy)
1096 if not self.dry_run:
1097 ensure_directory(sitepy)
1098 f = open(sitepy,'wb')
1101 self.byte_compile([sitepy])
1103 self.sitepy_installed = True
1116 INSTALL_SCHEMES = dict(
1118 install_dir = '$base/lib/python$py_version_short/site-packages',
1119 script_dir = '$base/bin',
1123 DEFAULT_SCHEME = dict(
1124 install_dir = '$base/Lib/site-packages',
1125 script_dir = '$base/Scripts',
1128 def _expand(self, *attrs):
1129 config_vars = self.get_finalized_command('install').config_vars
1132 # Set default install_dir/scripts from --prefix
1133 config_vars = config_vars.copy()
1134 config_vars['base'] = self.prefix
1135 scheme = self.INSTALL_SCHEMES.get(os.name,self.DEFAULT_SCHEME)
1136 for attr,val in scheme.items():
1137 if getattr(self,attr,None) is None:
1138 setattr(self,attr,val)
1140 from distutils.util import subst_vars
1142 val = getattr(self, attr)
1144 val = subst_vars(val, config_vars)
1145 if os.name == 'posix':
1146 val = os.path.expanduser(val)
1147 setattr(self, attr, val)
1157 def get_site_dirs():
1158 # return a list of 'site' dirs
1159 sitedirs = filter(None,os.environ.get('PYTHONPATH','').split(os.pathsep))
1160 prefixes = [sys.prefix]
1161 if sys.exec_prefix != sys.prefix:
1162 prefixes.append(sys.exec_prefix)
1163 for prefix in prefixes:
1165 if sys.platform in ('os2emx', 'riscos'):
1166 sitedirs.append(os.path.join(prefix, "Lib", "site-packages"))
1168 sitedirs.extend([os.path.join(prefix,
1170 "python" + sys.version[:3],
1172 os.path.join(prefix, "lib", "site-python")])
1175 [prefix, os.path.join(prefix, "lib", "site-packages")]
1177 if sys.platform == 'darwin':
1178 # for framework builds *only* we add the standard Apple
1179 # locations. Currently only per-user, but /Library and
1180 # /Network/Library could be added too
1181 if 'Python.framework' in prefix:
1182 home = os.environ.get('HOME')
1190 for plat_specific in (0,1):
1191 site_lib = get_python_lib(plat_specific)
1192 if site_lib not in sitedirs: sitedirs.append(site_lib)
1194 sitedirs = map(normalize_path, sitedirs)
1198 def expand_paths(inputs):
1199 """Yield sys.path directories that might contain "old-style" packages"""
1203 for dirname in inputs:
1204 dirname = normalize_path(dirname)
1209 if not os.path.isdir(dirname):
1212 files = os.listdir(dirname)
1213 yield dirname, files
1216 if not name.endswith('.pth'):
1217 # We only care about the .pth files
1219 if name in ('easy-install.pth','setuptools.pth'):
1220 # Ignore .pth files that we control
1223 # Read the .pth file
1224 f = open(os.path.join(dirname,name))
1225 lines = list(yield_lines(f))
1228 # Yield existing non-dupe, non-import directory lines from it
1230 if not line.startswith("import"):
1231 line = normalize_path(line.rstrip())
1232 if line not in seen:
1234 if not os.path.isdir(line):
1236 yield line, os.listdir(line)
1239 def extract_wininst_cfg(dist_filename):
1240 """Extract configuration data from a bdist_wininst .exe
1242 Returns a ConfigParser.RawConfigParser, or None
1244 f = open(dist_filename,'rb')
1246 endrec = zipfile._EndRecData(f)
1250 prepended = (endrec[9] - endrec[5]) - endrec[6]
1251 if prepended < 12: # no wininst data here
1253 f.seek(prepended-12)
1255 import struct, StringIO, ConfigParser
1256 tag, cfglen, bmlen = struct.unpack("<iii",f.read(12))
1257 if tag not in (0x1234567A, 0x1234567B):
1258 return None # not a valid tag
1260 f.seek(prepended-(12+cfglen))
1261 cfg = ConfigParser.RawConfigParser({'version':'','target_version':''})
1263 cfg.readfp(StringIO.StringIO(f.read(cfglen).split(chr(0),1)[0]))
1264 except ConfigParser.Error:
1266 if not cfg.has_section('metadata') or not cfg.has_section('Setup'):
1280 def get_exe_prefixes(exe_filename):
1281 """Get exe->egg path translations for a given .exe file"""
1284 ('PURELIB/', ''), ('PLATLIB/pywin32_system32', ''),
1286 ('SCRIPTS/', 'EGG-INFO/scripts/')
1288 z = zipfile.ZipFile(exe_filename)
1290 for info in z.infolist():
1291 name = info.filename
1292 parts = name.split('/')
1293 if len(parts)==3 and parts[2]=='PKG-INFO':
1294 if parts[1].endswith('.egg-info'):
1295 prefixes.insert(0,('/'.join(parts[:2]), 'EGG-INFO/'))
1297 if len(parts)!=2 or not name.endswith('.pth'):
1299 if name.endswith('-nspkg.pth'):
1301 if parts[0].upper() in ('PURELIB','PLATLIB'):
1302 for pth in yield_lines(z.read(name)):
1303 pth = pth.strip().replace('\\','/')
1304 if not pth.startswith('import'):
1305 prefixes.append((('%s/%s/' % (parts[0],pth)), ''))
1308 prefixes = [(x.lower(),y) for x, y in prefixes]
1309 prefixes.sort(); prefixes.reverse()
1313 def parse_requirement_arg(spec):
1315 return Requirement.parse(spec)
1317 raise DistutilsError(
1318 "Not a URL, existing file, or requirement spec: %r" % (spec,)
1321 class PthDistributions(Environment):
1322 """A .pth file with Distribution paths in it"""
1326 def __init__(self, filename, sitedirs=()):
1327 self.filename = filename; self.sitedirs=map(normalize_path, sitedirs)
1328 self.basedir = normalize_path(os.path.dirname(self.filename))
1329 self._load(); Environment.__init__(self, [], None, None)
1330 for path in yield_lines(self.paths):
1331 map(self.add, find_distributions(path, True))
1336 seen = dict.fromkeys(self.sitedirs)
1337 if os.path.isfile(self.filename):
1338 for line in open(self.filename,'rt'):
1339 if line.startswith('import'):
1342 path = line.rstrip()
1343 self.paths.append(path)
1344 if not path.strip() or path.strip().startswith('#'):
1346 # skip non-existent paths, in case somebody deleted a package
1347 # manually, and duplicate paths as well
1348 path = self.paths[-1] = normalize_path(
1349 os.path.join(self.basedir,path)
1351 if not os.path.exists(path) or path in seen:
1352 self.paths.pop() # skip it
1353 self.dirty = True # we cleaned up, so we're dirty now :)
1357 if self.paths and not saw_import:
1358 self.dirty = True # ensure anything we touch has import wrappers
1359 while self.paths and not self.paths[-1].strip():
1363 """Write changed .pth file back to disk"""
1367 data = '\n'.join(map(self.make_relative,self.paths))
1369 log.debug("Saving %s", self.filename)
1371 "import sys; sys.__plen = len(sys.path)\n"
1373 "import sys; new=sys.path[sys.__plen:];"
1374 " del sys.path[sys.__plen:];"
1375 " p=getattr(sys,'__egginsert',len(os.environ.get('PYTHONPATH','').split(os.pathsep))); sys.path[p:p]=new;"
1376 " sys.__egginsert = p+len(new)\n"
1379 if os.path.islink(self.filename):
1380 os.unlink(self.filename)
1381 f = open(self.filename,'wb')
1382 f.write(data); f.close()
1384 elif os.path.exists(self.filename):
1385 log.debug("Deleting empty %s", self.filename)
1386 os.unlink(self.filename)
1391 """Add `dist` to the distribution map"""
1392 if dist.location not in self.paths and dist.location not in self.sitedirs:
1393 self.paths.append(dist.location); self.dirty = True
1394 Environment.add(self,dist)
1396 def remove(self,dist):
1397 """Remove `dist` from the distribution map"""
1398 while dist.location in self.paths:
1399 self.paths.remove(dist.location); self.dirty = True
1400 Environment.remove(self,dist)
1403 def make_relative(self,path):
1404 npath, last = os.path.split(normalize_path(path))
1405 baselen = len(self.basedir)
1407 sep = os.altsep=='/' and '/' or os.sep
1408 while len(npath)>=baselen:
1409 if npath==self.basedir:
1410 parts.append(os.curdir)
1412 return sep.join(parts)
1413 npath, last = os.path.split(npath)
1418 def get_script_header(script_text, executable=sys_executable, wininst=False):
1419 """Create a #! line, getting options (if any) from script_text"""
1420 from distutils.command.build_scripts import first_line_re
1421 first = (script_text+'\n').splitlines()[0]
1422 match = first_line_re.match(first)
1425 options = match.group(1) or ''
1426 if options: options = ' '+options
1428 executable = "python.exe"
1430 executable = nt_quote_arg(executable)
1431 hdr = "#!%(executable)s%(options)s\n" % locals()
1432 if unicode(hdr,'ascii','ignore').encode('ascii') != hdr:
1433 # Non-ascii path to sys.executable, use -x to prevent warnings
1435 if options.strip().startswith('-'):
1436 options = ' -x'+options.strip()[1:]
1437 # else: punt, we can't do it, let the warning happen anyway
1440 executable = fix_jython_executable(executable, options)
1441 hdr = "#!%(executable)s%(options)s\n" % locals()
1444 def auto_chmod(func, arg, exc):
1445 if func is os.remove and os.name=='nt':
1446 chmod(arg, stat.S_IWRITE)
1448 exc = sys.exc_info()
1449 raise exc[0], (exc[1][0], exc[1][1] + (" %s %s" % (func,arg)))
1451 def uncache_zipdir(path):
1452 """Ensure that the importer caches dont have stale info for `path`"""
1453 from zipimport import _zip_directory_cache as zdc
1455 _uncache(path, sys.path_importer_cache)
1457 def _uncache(path, cache):
1461 path = normalize_path(path)
1463 if normalize_path(p)==path:
1467 def is_python(text, filename='<string>'):
1468 "Is this string a valid Python script?"
1470 compile(text, filename, 'exec')
1471 except (SyntaxError, TypeError):
1476 def is_sh(executable):
1477 """Determine if the specified executable is a .sh (contains a #! line)"""
1479 fp = open(executable)
1482 except (OSError,IOError): return executable
1483 return magic == '#!'
1485 def nt_quote_arg(arg):
1486 """Quote a command line argument according to Windows parsing rules"""
1492 needquote = (" " in arg) or ("\t" in arg)
1500 # double preceding backslashes, then add a \"
1501 result.append('\\' * (nb*2) + '\\"')
1505 result.append('\\' * nb)
1510 result.append('\\' * nb)
1513 result.append('\\' * nb) # double the trailing backslashes
1516 return ''.join(result)
1526 def is_python_script(script_text, filename):
1527 """Is this text, as a whole, a Python script? (as opposed to shell/bat/etc.
1529 if filename.endswith('.py') or filename.endswith('.pyw'):
1530 return True # extension says it's Python
1531 if is_python(script_text, filename):
1532 return True # it's syntactically valid Python
1533 if script_text.startswith('#!'):
1534 # It begins with a '#!' line, so check if 'python' is in it somewhere
1535 return 'python' in script_text.splitlines()[0].lower()
1537 return False # Not any Python I can recognize
1540 from os import chmod as _chmod
1542 # Jython compatibility
1543 def _chmod(*args): pass
1545 def chmod(path, mode):
1546 log.debug("changing mode of %s to %o", path, mode)
1550 log.debug("chmod failed: %s", e)
1552 def fix_jython_executable(executable, options):
1553 if sys.platform.startswith('java') and is_sh(executable):
1554 # Workaround Jython's sys.executable being a .sh (an invalid
1555 # shebang line interpreter)
1557 # Can't apply the workaround, leave it broken
1558 log.warn("WARNING: Unable to adapt shebang line for Jython,"
1559 " the following script is NOT executable\n"
1560 " see http://bugs.jython.org/issue1112 for"
1561 " more information.")
1563 return '/usr/bin/env %s' % executable
1567 def get_script_args(dist, executable=sys_executable, wininst=False):
1568 """Yield write_script() argument tuples for a distribution's entrypoints"""
1569 spec = str(dist.as_requirement())
1570 header = get_script_header("", executable, wininst)
1571 for group in 'console_scripts', 'gui_scripts':
1572 for name,ep in dist.get_entry_map(group).items():
1574 "# EASY-INSTALL-ENTRY-SCRIPT: %(spec)r,%(group)r,%(name)r\n"
1575 "__requires__ = %(spec)r\n"
1577 "from pkg_resources import load_entry_point\n"
1580 " load_entry_point(%(spec)r, %(group)r, %(name)r)()\n"
1583 if sys.platform=='win32' or wininst:
1584 # On Windows/wininst, add a .py extension and an .exe launcher
1585 if group=='gui_scripts':
1586 ext, launcher = '-script.pyw', 'gui.exe'
1588 new_header = re.sub('(?i)python.exe','pythonw.exe',header)
1590 ext, launcher = '-script.py', 'cli.exe'
1591 old = ['.py','.pyc','.pyo']
1592 new_header = re.sub('(?i)pythonw.exe','python.exe',header)
1594 if os.path.exists(new_header[2:-1]) or sys.platform!='win32':
1598 yield (name+ext, hdr+script_text, 't', [name+x for x in old])
1600 name+'.exe', resource_string('setuptools', launcher),
1601 'b') # write in binary mode
1602 yield (name+'.exe.manifest', _launcher_manifest % (name,), 't')
1604 # On other platforms, we assume the right thing to do is to
1605 # just write the stub with no extension.
1606 yield (name, header+script_text)
1608 _launcher_manifest = """
1609 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
1610 <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
1611 <assemblyIdentity version="1.0.0.0"
1612 processorArchitecture="X86"
1616 <!-- Identify the application security requirements. -->
1617 <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
1619 <requestedPrivileges>
1620 <requestedExecutionLevel level="asInvoker" uiAccess="false"/>
1621 </requestedPrivileges>
1649 def rmtree(path, ignore_errors=False, onerror=auto_chmod):
1650 """Recursively delete a directory tree.
1652 This code is taken from the Python 2.4 version of 'shutil', because
1653 the 2.3 version doesn't really work right.
1658 elif onerror is None:
1663 names = os.listdir(path)
1664 except os.error, err:
1665 onerror(os.listdir, path, sys.exc_info())
1667 fullname = os.path.join(path, name)
1669 mode = os.lstat(fullname).st_mode
1672 if stat.S_ISDIR(mode):
1673 rmtree(fullname, ignore_errors, onerror)
1677 except os.error, err:
1678 onerror(os.remove, fullname, sys.exc_info())
1682 onerror(os.rmdir, path, sys.exc_info())
1685 # This function is called when setuptools*.egg is run using /bin/sh
1686 import setuptools; argv0 = os.path.dirname(setuptools.__path__[0])
1687 sys.argv[0] = argv0; sys.argv.append(argv0); main()
1690 def main(argv=None, **kw):
1691 from setuptools import setup
1692 from setuptools.dist import Distribution
1693 import distutils.core
1696 usage: %(script)s [options] requirement_or_url ...
1697 or: %(script)s --help
1700 def gen_usage (script_name):
1701 script = os.path.basename(script_name)
1702 return USAGE % vars()
1704 def with_ei_usage(f):
1705 old_gen_usage = distutils.core.gen_usage
1707 distutils.core.gen_usage = gen_usage
1710 distutils.core.gen_usage = old_gen_usage
1712 class DistributionWithoutHelpCommands(Distribution):
1714 def _show_help(self,*args,**kw):
1715 with_ei_usage(lambda: Distribution._show_help(self,*args,**kw))
1720 with_ei_usage(lambda:
1722 script_args = ['-q','easy_install', '-v']+argv,
1723 script_name = sys.argv[0] or 'easy_install',
1724 distclass=DistributionWithoutHelpCommands, **kw