diff options
-rwxr-xr-x | EasyInstall.txt | 13 | ||||
-rwxr-xr-x | setuptools/command/easy_install.py | 26 | ||||
-rwxr-xr-x | setuptools/package_index.py | 69 |
3 files changed, 81 insertions, 27 deletions
diff --git a/EasyInstall.txt b/EasyInstall.txt index eb5925f4..9886e8fb 100755 --- a/EasyInstall.txt +++ b/EasyInstall.txt @@ -589,6 +589,14 @@ Command-Line Options from other sys.path directories to the installation directory, unless you explicitly gave the distribution's filename on the command line. + Note that as of 0.6a10, using this option excludes "system" and + "development" eggs from consideration because they can't be reliably + copied. This may cause EasyInstall to choose an older version of a package + than what you expected, or it may cause downloading and installation of a + fresh copy of something that's already installed. You will see warning + messages for any eggs that EasyInstall skips, before it falls back to an + older version or attempts to download a fresh copy. + ``--find-links=URL, -f URL`` (Option renamed in 0.4a2) Scan the specified "download pages" for direct links to downloadable eggs or source distributions. Any usable packages will be downloaded if they @@ -982,6 +990,11 @@ Known Issues linking to them (e.g. from within their own PyPI page or download links page). + * The ``--always-copy`` option now skips "system" and "development" eggs since + they can't be reliably copied. Note that this may cause EasyInstall to + choose an older version of a package than what you expected, or it may cause + downloading and installation of a fresh version of what's already installed. + 0.6a9 * Fixed ``.pth`` file processing picking up nested eggs (i.e. ones inside "baskets") when they weren't explicitly listed in the ``.pth`` file. diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 71fe46bb..31975f63 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -305,27 +305,27 @@ class easy_install(Command): spec = parse_requirement_arg(spec) self.check_editable(spec) - download = self.package_index.fetch( - spec, tmpdir, self.upgrade, self.editable + dist = self.package_index.fetch_distribution( + spec, tmpdir, self.upgrade, self.editable, not self.always_copy ) - if download is None: - raise DistutilsError( - "Could not find distribution for %r" % spec - ) - - return self.install_item(spec, download, tmpdir, deps) + if dist is None: + msg = "Could not find suitable distribution for %r" % spec + if self.always_copy: + msg+=" (--always-copy skips system and development eggs)" + raise DistutilsError(msg) + elif dist.precedence==DEVELOP_DIST: + # .egg-info dists don't need installing, just process deps + self.process_distribution(spec, dist, deps, "Using") + return dist + else: + return self.install_item(spec, dist.location, tmpdir, deps) finally: if os.path.exists(tmpdir): rmtree(tmpdir) - - - - - def install_item(self, spec, download, tmpdir, deps, install_needed=False): # Installation is also needed if file in tmpdir or is not an egg diff --git a/setuptools/package_index.py b/setuptools/package_index.py index 2813631e..669692b6 100755 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -337,12 +337,12 @@ class PackageIndex(Environment): automatically created alongside the downloaded file. If `spec` is a ``Requirement`` object or a string containing a - project/version requirement spec, this method is equivalent to - the ``fetch()`` method. If `spec` is a local, existing file or - directory name, it is simply returned unchanged. If `spec` is a URL, - it is downloaded to a subpath of `tmpdir`, and the local filename is - returned. Various errors may be raised if a problem occurs during - downloading. + project/version requirement spec, this method returns the location of + a matching distribution (possibly after downloading it to `tmpdir`). + If `spec` is a locally existing file or directory name, it is simply + returned unchanged. If `spec` is a URL, it is downloaded to a subpath + of `tmpdir`, and the local filename is returned. Various errors may be + raised if a problem occurs during downloading. """ if not isinstance(spec,Requirement): scheme = URL_SCHEME(spec) @@ -364,31 +364,49 @@ class PackageIndex(Environment): "Not a URL, existing file, or requirement spec: %r" % (spec,) ) - return self.fetch(spec, tmpdir) + return getattr(self.fetch_distribution(spec, tmpdir),'location',None) - def fetch(self, requirement, tmpdir, force_scan=False, source=False): - """Obtain a file suitable for fulfilling `requirement` + def fetch_distribution(self, + requirement, tmpdir, force_scan=False, source=False, develop_ok=False + ): + """Obtain a distribution suitable for fulfilling `requirement` `requirement` must be a ``pkg_resources.Requirement`` instance. If necessary, or if the `force_scan` flag is set, the requirement is searched for in the (online) package index as well as the locally installed packages. If a distribution matching `requirement` is found, - the return value is the same as if you had called the ``download()`` - method with the matching distribution's URL. If no matching - distribution is found, returns ``None``. + the returned distribution's ``location`` is the value you would have + gotten from calling the ``download()`` method with the matching + distribution's URL or filename. If no matching distribution is found, + ``None`` is returned. If the `source` flag is set, only source distributions and source - checkout links will be considered. + checkout links will be considered. Unless the `develop_ok` flag is + set, development and system eggs (i.e., those using the ``.egg-info`` + format) will be ignored. """ + # process a Requirement self.info("Searching for %s", requirement) + skipped = {} def find(req): + # Find a matching distribution; may be called more than once + for dist in self[req.key]: + + if dist.precedence==DEVELOP_DIST and not develop_ok: + if dist not in skipped: + self.warn("Skipping development or system egg: %s",dist) + skipped[dist] = 1 + continue + if dist in req and (dist.precedence<=SOURCE_DIST or not source): self.info("Best match: %s", dist) - return self.download(dist.location, tmpdir) + return dist.clone( + location=self.download(dist.location, tmpdir) + ) if force_scan: self.find_packages(requirement) @@ -407,6 +425,29 @@ class PackageIndex(Environment): ) return dist + def fetch(self, requirement, tmpdir, force_scan=False, source=False): + """Obtain a file suitable for fulfilling `requirement` + + DEPRECATED; use the ``fetch_distribution()`` method now instead. For + backward compatibility, this routine is identical but returns the + ``location`` of the downloaded distribution instead of a distribution + object. + """ + dist = self.fetch_dist(requirement,tmpdir,force_scan,source) + if dist is not None: + return dist.location + return None + + + + + + + + + + + def gen_setup(self, filename, fragment, tmpdir): match = EGG_FRAGMENT.match(fragment); #import pdb; pdb.set_trace() |