def uninstall_eggs(reqs): """ Remove eggs matching the given requirements. """ # XXX This doesn't do dependencies? dists = [] for i in pkg_resources.parse_requirements(reqs): dist = next((d for d in pkg_resources.working_set if d.project_name == i.project_name), None) if not dist: raise DistutilsOptionError('Cannot remove package, not installed', i.project_name) if not dist.location.endswith('.egg'): raise DistutilsOptionError('Not an egg at %s, chickening out' % dist.location) dists.append(dist) for dist in dists: if is_local(dist.location): log.info("Removing %s (%s)" % (dist, dist.location)) # Clear references to egg - http://trac.edgewall.org/ticket/7014 uncache_zipdir(dist.location) try: os.remove(dist.location) except OSError as ex: if ex.errno == errno.EISDIR: shutil.rmtree(dist.location) else: raise else: log.info("Not uninstalling egg, it's not in our virtualenv: %s", dist.location) dependency.remove_from_ws(pkg_resources.working_set, dist)
def test_remove_from_ws__removes_all_entries(): ws = WorkingSet([]) dist1 = create_dist("a", "1.0", location="a10") dist2 = create_dist("a", "2.0", location="a20") assert dist1 not in ws assert dist2 not in ws ws.add(dist1) assert dist1 in ws assert dist1.location in ws.entries assert dist2 not in ws assert dist2.location not in ws.entries ws.add_entry(dist2.location) assert dist1 in ws assert dist1.location in ws.entries assert dist2 not in ws assert dist2.location in ws.entries dependency.remove_from_ws(ws, dist2) assert dist1 not in ws assert dist2 not in ws assert len([d for d in ws]) == 0
def purge_req(self, req): """ Purge a requirement from all our indexes, used for backtracking""" log.debug(' -- purging %s', req) self.best.pop(req.key, None) self.processed.pop(req, None) for w in self.ws, self.new_dists: if req.key in w.by_key: dependency.remove_from_ws(w, w.by_key[req.key])
def test_remove_from_ws__removes_distribution(): ws = WorkingSet([]) dist = create_dist("a", "1.0") assert dist not in ws ws.add(dist) assert dist in ws dependency.remove_from_ws(ws, dist) assert dist not in ws
def _setup_dist(cmd, dist, install_needed=False, add_to_global=False): if install_needed: with cmdline.TempDir() as tmpdir: dist = cmd.install_egg(dist.location, tmpdir) if dist.location.startswith(pyenv.get_site_packages()): fix_permissions(dist) cmd.process_distribution(None, dist, deps=False) # Add the distributions to the global registry if we asked for it. # This makes the distro importable, and classed as 'already # installed' by the dependency resolution algorithm. if add_to_global: dependency.remove_from_ws(pkg_resources.working_set, dist) pkg_resources.working_set.add(dist) return dist
def install(cmd, reqs, add_to_global=False, prefer_final=True, force_upgrade=False, use_existing=False, eggs=None, reinstall=False): """ Installs a given requirement using buildout's modified easy_install. Parameters ---------- cmd : `setuptools.Command` active setuptools Command class reqs : `list` of `str` list of distutils requirements, eg ['foo==1.2'] eggs : `list` of `str` paths to egg files to use to satisfy requirements add_to_global : `bool` adds installed distribution to the global working_set. This has the effect of making them available for import within this process, used by fetch_build_eggs. prefer_final : `bool` Will prefer released versions of the requirements over dev versions, unless the package is third-party where it always prefers final versions. force_upgrade : `bool` Will force downloads of requirements from PyPI. This is the rough equivalent of ``easy_install -U acme.foo`` use_existing : `bool` Will not update any packages found in the current working set reinstall : `bool` Will reinstall packages that are already installed. Returns ------- ws : `pkg_resources.WorkingSet` Working Set for the distributions that were just installed. """ # Remove anything we're upgrading if force_upgrade: uninstall_eggs(reqs) # Create installer class configured to install into wherever the command # class was setup for installer = Installer(dest=cmd.install_dir, index=cmd.index_url, prefer_final=prefer_final) egg_dists = [egg_distribution(egg) for egg in (eggs or [])] installer._egg_dists = egg_dists # This is a bit nasty - we have to monkey-patch the filter for final # versions so that we can also filter for dev versions as well. # Set prefer_final to True, always, so it enables the filter easy_install.prefer_final(True) # This returns a WorkingSet of the packages we just installed. # NOTE here we pass in the existing stuff - this will prefer installed # packages over ones on the server, eg an installed release # version won't get trumped by a dev version on the server ws = pkg_resources.WorkingSet(pkg_resources.working_set.entries) # We must remove the package we're installing from the 'baseline' ws. # This way we won't get any weird requirement conflicts with new # versions of the package we're trying to set up if cmd.distribution.metadata.name: dist = dependency.get_dist(cmd.distribution.metadata.name) if dist: dependency.remove_from_ws(ws, dist) # There's a chance that there were packages in setup_requires that were # also in install_requires. All packages that were not in the original # environment and were installed during the `setup_requires` resolution # process are tracked by `fetched_setup_requires` field of # `pkglib.setuptools.dist.Distribution`. # Here we ensure that they're re-added for setup along with any of their # own dependencies if they are also part of the package install_requires. for d in getattr(cmd.distribution, "fetched_setup_requires", []): dependency.remove_from_ws(ws, d) # Now run the installer to_setup = installer.install(reqs, working_set=ws, use_existing=use_existing, force_upgrade=force_upgrade, reinstall=reinstall) return setup_dists(cmd, ws, to_setup, egg_dists, add_to_global=add_to_global)