Permalink
Browse files

factor out get_installed_distributions utility function and add pip u…

…ninstall autocomplete; fixes #76
  • Loading branch information...
1 parent 15d872e commit 107835ec99a9a750d5466c50c275c14aa2e9cf07 @carljm carljm committed Mar 9, 2010
Showing with 50 additions and 15 deletions.
  1. +0 −1 MANIFEST.in
  2. +13 −0 pip/__init__.py
  3. +2 −7 pip/commands/freeze.py
  4. +4 −7 pip/req.py
  5. +31 −0 pip/util.py
View
@@ -2,4 +2,3 @@ recursive-include docs *.txt
recursive-include docs *.html
recursive-exclude docs/_build *.txt
prune docs/_build/_sources
-recursive-include scripts/completion *
View
@@ -9,6 +9,7 @@
from pip.exceptions import InstallationError
from pip.basecommand import command_dict, load_command, load_all_commands
from pip.vcs import vcs, get_src_requirement, import_vcs_support
+from pip.util import get_installed_distributions
def autocomplete():
"""Command and option completion for the main option parser (and options)
@@ -39,6 +40,18 @@ def autocomplete():
# subcommand options
# special case: the 'help' subcommand has no options
elif cwords[0] in subcommands and cwords[0] != 'help':
+ # special case: list locally installed dists for uninstall command
+ if cwords[0] == 'uninstall' and not current.startswith('-'):
+ installed = []
+ lc = current.lower()
+ for dist in get_installed_distributions(local_only=True):
+ if dist.key.startswith(lc) and dist.key not in cwords[1:]:
+ installed.append(dist.key)
+ # if there are no dists installed, fall back to option completion
+ if installed:
+ for dist in installed:
+ print dist
+ sys.exit(1)
subcommand = command_dict.get(cwords[0])
options += [(opt.get_opt_string(), opt.nargs)
for opt in subcommand.parser.option_list
View
@@ -5,7 +5,7 @@
from pip.req import InstallRequirement
from pip.log import logger
from pip.basecommand import Command
-from pip.util import dist_location, is_local
+from pip.util import get_installed_distributions
class FreezeCommand(Command):
name = 'freeze'
@@ -61,12 +61,7 @@ def run(self, options, args):
for link in find_links:
f.write('-f %s\n' % link)
installations = {}
- for dist in pkg_resources.working_set:
- if local_only and not is_local(dist_location(dist)):
- continue
- if dist.key in ('setuptools', 'pip', 'python'):
- ## FIXME: also skip virtualenv?
- continue
+ for dist in get_installed_distributions(local_only=local_only):
req = pip.FrozenRequirement.from_dist(dist, dependency_links, find_tags=find_tags)
installations[req.name] = req
if requirement:
View
@@ -19,7 +19,7 @@
from pip.util import display_path, rmtree, format_size
from pip.util import splitext, ask, backup_dir
from pip.util import url_to_filename, filename_to_url
-from pip.util import is_url, is_filename, is_local
+from pip.util import is_url, is_filename, is_local, dist_is_local
from pip.util import renames, normalize_path, egg_link_path
from pip.util import make_path_relative, is_svn_page, file_contents
from pip.util import has_leading_dir, split_leading_dir
@@ -421,8 +421,6 @@ def uninstall(self, auto_confirm=False):
easy_install_pth = os.path.join(os.path.dirname(develop_egg_link),
'easy-install.pth')
paths_to_remove.add_pth(easy_install_pth, dist.location)
- # fix location (so we can uninstall links to sources outside venv)
- paths_to_remove.location = normalize_path(develop_egg_link)
# find distutils scripts= scripts
if dist.has_metadata('scripts') and dist.metadata_isdir('scripts'):
@@ -1368,20 +1366,19 @@ def __init__(self, dist):
self._refuse = set()
self.pth = {}
self.dist = dist
- self.location = normalize_path(dist.location)
self.save_dir = None
self._moved_paths = []
def _permitted(self, path):
"""
- Return True if the given path is one we are permitted to remove,
- False otherwise.
+ Return True if the given path is one we are permitted to
+ remove/modify, False otherwise.
"""
return is_local(path)
def _can_uninstall(self):
- if not self._permitted(self.location):
+ if not dist_is_local(self.dist):
logger.notify("Not uninstalling %s at %s, outside environment %s"
% (self.dist.project_name, self.location, sys.prefix))
return False
View
@@ -6,6 +6,9 @@
import urllib
import urllib2
import re
+
+import pkg_resources
+
from pip.backwardcompat import WindowsError
from pip.exceptions import InstallationError
from pip.locations import site_packages
@@ -323,6 +326,34 @@ def is_local(path):
return True
return normalize_path(path).startswith(normalize_path(sys.prefix))
+def dist_is_local(dist):
+ """
+ Return True if given Distribution object is installed locally
+ (i.e. within current virtualenv).
+
+ Always True if we're not in a virtualenv.
+
+ """
+ return is_local(dist_location(dist))
+
+def get_installed_distributions(local_only=True, skip=('setuptools', 'pip', 'python')):
+ """
+ Return a list of installed Distribution objects.
+
+ If ``local_only`` is True (default), only return installations
+ local to the current virtualenv, if in a virtualenv.
+
+ ``skip`` argument is an iterable of lower-case project names to
+ ignore; defaults to ('setuptools', 'pip', 'python'). [FIXME also
+ skip virtualenv?]
+
+ """
+ if local_only:
+ local_test = dist_is_local
+ else:
+ local_test = lambda d: True
+ return [d for d in pkg_resources.working_set if local_test(d) and d.key not in skip]
+
def egg_link_path(dist):
"""
Return the path where we'd expect to find a .egg-link file for

0 comments on commit 107835e

Please sign in to comment.