Commit ca9ccbf6 authored by PJ Eby's avatar PJ Eby

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.

--HG--
branch : setuptools
extra : convert_revision : svn%3A6015fed2-1504-0410-9fe1-9d1591cc4771/sandbox/trunk/setuptools%4042260
parent 48dd1efa
...@@ -589,6 +589,14 @@ Command-Line Options ...@@ -589,6 +589,14 @@ Command-Line Options
from other sys.path directories to the installation directory, unless you from other sys.path directories to the installation directory, unless you
explicitly gave the distribution's filename on the command line. 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) ``--find-links=URL, -f URL`` (Option renamed in 0.4a2)
Scan the specified "download pages" for direct links to downloadable eggs Scan the specified "download pages" for direct links to downloadable eggs
or source distributions. Any usable packages will be downloaded if they or source distributions. Any usable packages will be downloaded if they
...@@ -982,6 +990,11 @@ Known Issues ...@@ -982,6 +990,11 @@ Known Issues
linking to them (e.g. from within their own PyPI page or download links linking to them (e.g. from within their own PyPI page or download links
page). 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 0.6a9
* Fixed ``.pth`` file processing picking up nested eggs (i.e. ones inside * Fixed ``.pth`` file processing picking up nested eggs (i.e. ones inside
"baskets") when they weren't explicitly listed in the ``.pth`` file. "baskets") when they weren't explicitly listed in the ``.pth`` file.
......
...@@ -305,27 +305,27 @@ class easy_install(Command): ...@@ -305,27 +305,27 @@ class easy_install(Command):
spec = parse_requirement_arg(spec) spec = parse_requirement_arg(spec)
self.check_editable(spec) self.check_editable(spec)
download = self.package_index.fetch( dist = self.package_index.fetch_distribution(
spec, tmpdir, self.upgrade, self.editable spec, tmpdir, self.upgrade, self.editable, not self.always_copy
) )
if download is None: if dist is None:
raise DistutilsError( msg = "Could not find suitable distribution for %r" % spec
"Could not find distribution for %r" % spec if self.always_copy:
) msg+=" (--always-copy skips system and development eggs)"
raise DistutilsError(msg)
return self.install_item(spec, download, tmpdir, deps) 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: finally:
if os.path.exists(tmpdir): if os.path.exists(tmpdir):
rmtree(tmpdir) rmtree(tmpdir)
def install_item(self, spec, download, tmpdir, deps, install_needed=False): def install_item(self, spec, download, tmpdir, deps, install_needed=False):
# Installation is also needed if file in tmpdir or is not an egg # Installation is also needed if file in tmpdir or is not an egg
......
...@@ -337,12 +337,12 @@ class PackageIndex(Environment): ...@@ -337,12 +337,12 @@ class PackageIndex(Environment):
automatically created alongside the downloaded file. automatically created alongside the downloaded file.
If `spec` is a ``Requirement`` object or a string containing a If `spec` is a ``Requirement`` object or a string containing a
project/version requirement spec, this method is equivalent to project/version requirement spec, this method returns the location of
the ``fetch()`` method. If `spec` is a local, existing file or a matching distribution (possibly after downloading it to `tmpdir`).
directory name, it is simply returned unchanged. If `spec` is a URL, If `spec` is a locally existing file or directory name, it is simply
it is downloaded to a subpath of `tmpdir`, and the local filename is returned unchanged. If `spec` is a URL, it is downloaded to a subpath
returned. Various errors may be raised if a problem occurs during of `tmpdir`, and the local filename is returned. Various errors may be
downloading. raised if a problem occurs during downloading.
""" """
if not isinstance(spec,Requirement): if not isinstance(spec,Requirement):
scheme = URL_SCHEME(spec) scheme = URL_SCHEME(spec)
...@@ -364,31 +364,49 @@ class PackageIndex(Environment): ...@@ -364,31 +364,49 @@ class PackageIndex(Environment):
"Not a URL, existing file, or requirement spec: %r" % "Not a URL, existing file, or requirement spec: %r" %
(spec,) (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): def fetch_distribution(self,
"""Obtain a file suitable for fulfilling `requirement` 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. `requirement` must be a ``pkg_resources.Requirement`` instance.
If necessary, or if the `force_scan` flag is set, the requirement is 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 searched for in the (online) package index as well as the locally
installed packages. If a distribution matching `requirement` is found, installed packages. If a distribution matching `requirement` is found,
the return value is the same as if you had called the ``download()`` the returned distribution's ``location`` is the value you would have
method with the matching distribution's URL. If no matching gotten from calling the ``download()`` method with the matching
distribution is found, returns ``None``. 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 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 # process a Requirement
self.info("Searching for %s", requirement) self.info("Searching for %s", requirement)
skipped = {}
def find(req): def find(req):
# Find a matching distribution; may be called more than once
for dist in self[req.key]: 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): if dist in req and (dist.precedence<=SOURCE_DIST or not source):
self.info("Best match: %s", dist) self.info("Best match: %s", dist)
return self.download(dist.location, tmpdir) return dist.clone(
location=self.download(dist.location, tmpdir)
)
if force_scan: if force_scan:
self.find_packages(requirement) self.find_packages(requirement)
...@@ -407,6 +425,29 @@ class PackageIndex(Environment): ...@@ -407,6 +425,29 @@ class PackageIndex(Environment):
) )
return dist 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): def gen_setup(self, filename, fragment, tmpdir):
match = EGG_FRAGMENT.match(fragment); #import pdb; pdb.set_trace() match = EGG_FRAGMENT.match(fragment); #import pdb; pdb.set_trace()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment