diff --git a/pip/__init__.py b/pip/__init__.py
index 158f56915..6828be17a 100755
--- a/pip/__init__.py
+++ b/pip/__init__.py
@@ -11,6 +11,7 @@ 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)
and its subcommands (and options).
@@ -18,7 +19,7 @@ def autocomplete():
Enable by sourcing one of the completion shell scripts (bash or zsh).
"""
# Don't complete if user hasn't sourced bash_completion file.
- if not os.environ.has_key('PIP_AUTO_COMPLETE'):
+ if 'PIP_AUTO_COMPLETE' not in os.environ:
return
cwords = os.environ['COMP_WORDS'].split()[1:]
cword = int(os.environ['COMP_CWORD'])
@@ -75,6 +76,7 @@ def autocomplete():
print ' '.join(filter(lambda x: x.startswith(current), subcommands))
sys.exit(1)
+
def main(initial_args=None):
if initial_args is None:
initial_args = sys.argv[1:]
diff --git a/pip/basecommand.py b/pip/basecommand.py
index c53d2d293..958d79e84 100644
--- a/pip/basecommand.py
+++ b/pip/basecommand.py
@@ -18,10 +18,12 @@ __all__ = ['command_dict', 'Command', 'load_all_commands',
command_dict = {}
+
class Command(object):
name = None
usage = None
hidden = False
+
def __init__(self):
assert self.name
self.parser = ConfigOptionParser(
@@ -48,7 +50,7 @@ class Command(object):
def setup_logging(self):
pass
-
+
def main(self, complete_args, args, initial_options):
options, args = self.parser.parse_args(args)
self.merge_options(initial_options, options)
@@ -65,7 +67,7 @@ class Command(object):
logger.explicit_levels = True
self.setup_logging()
-
+
if options.require_venv and not options.venv:
# If a venv is required check if it can really be found
if not os.environ.get('VIRTUAL_ENV'):
@@ -141,6 +143,7 @@ class Command(object):
log_fp.close()
return exit
+
## FIXME: should get moved somewhere else:
def setup_proxy_handler(proxystr=''):
"""Set the proxy handler given the option passed on the command
@@ -152,6 +155,7 @@ def setup_proxy_handler(proxystr=''):
opener = urllib2.build_opener(proxy_support, urllib2.CacheFTPHandler)
urllib2.install_opener(opener)
+
def get_proxy(proxystr=''):
"""Get the proxy given the option passed on the command line. If an
empty string is passed it looks at the HTTP_PROXY environment
@@ -174,6 +178,7 @@ def get_proxy(proxystr=''):
else:
return None
+
def format_exc(exc_info=None):
if exc_info is None:
exc_info = sys.exc_info()
@@ -181,6 +186,7 @@ def format_exc(exc_info=None):
traceback.print_exception(*exc_info, **dict(file=out))
return out.getvalue()
+
def open_logfile(filename, mode='a'):
"""Open the named log file in append mode.
@@ -193,13 +199,14 @@ def open_logfile(filename, mode='a'):
if not os.path.exists(dirname):
os.makedirs(dirname)
exists = os.path.exists(filename)
-
+
log_fp = open(filename, mode)
if exists:
print >> log_fp, '-'*60
print >> log_fp, '%s run on %s' % (sys.argv[0], time.strftime('%c'))
return log_fp
+
def load_command(name):
full_name = 'pip.commands.%s' % name
if full_name in sys.modules:
@@ -209,10 +216,12 @@ def load_command(name):
except ImportError:
pass
+
def load_all_commands():
for name in command_names():
load_command(name)
+
def command_names():
dir = os.path.join(os.path.dirname(__file__), 'commands')
names = []
diff --git a/pip/baseparser.py b/pip/baseparser.py
index b04a8639c..928c1e5a4 100644
--- a/pip/baseparser.py
+++ b/pip/baseparser.py
@@ -8,6 +8,7 @@ import os
from distutils.util import strtobool
from pip.locations import default_config_file, default_log_file
+
class UpdatingDefaultsHelpFormatter(optparse.IndentedHelpFormatter):
"""Custom help formatter for use in ConfigOptionParser that updates
the defaults before expanding them, allowing them to show up correctly
diff --git a/pip/commands/bundle.py b/pip/commands/bundle.py
index e506a20a5..fb0f75704 100644
--- a/pip/commands/bundle.py
+++ b/pip/commands/bundle.py
@@ -4,6 +4,7 @@ from pip.log import logger
from pip.exceptions import InstallationError
from pip.commands.install import InstallCommand
+
class BundleCommand(InstallCommand):
name = 'bundle'
usage = '%prog [OPTIONS] BUNDLE_NAME.pybundle PACKAGE_NAMES...'
@@ -28,4 +29,5 @@ class BundleCommand(InstallCommand):
requirement_set = super(BundleCommand, self).run(options, args)
return requirement_set
+
BundleCommand()
diff --git a/pip/commands/completion.py b/pip/commands/completion.py
index 94a10380a..d003b9ae3 100644
--- a/pip/commands/completion.py
+++ b/pip/commands/completion.py
@@ -19,13 +19,13 @@ function _pip_completion {
local words cword
read -Ac words
read -cn cword
- reply=( $( COMP_WORDS="$words[*]" \\
+ reply=( $( COMP_WORDS="$words[*]" \\
COMP_CWORD=$(( cword-1 )) \\
PIP_AUTO_COMPLETE=1 $words[1] ) )
}
compctl -K _pip_completion pip
-"""
-}
+"""}
+
class CompletionCommand(Command):
name = 'completion'
diff --git a/pip/commands/freeze.py b/pip/commands/freeze.py
index 2f6b13164..01b5df934 100644
--- a/pip/commands/freeze.py
+++ b/pip/commands/freeze.py
@@ -7,6 +7,7 @@ from pip.log import logger
from pip.basecommand import Command
from pip.util import get_installed_distributions
+
class FreezeCommand(Command):
name = 'freeze'
usage = '%prog [OPTIONS]'
@@ -37,7 +38,7 @@ class FreezeCommand(Command):
def setup_logging(self):
logger.move_stdout_to_stderr()
-
+
def run(self, options, args):
requirement = options.requirement
find_links = options.find_links or []
@@ -104,4 +105,5 @@ class FreezeCommand(Command):
for installation in sorted(installations.values(), key=lambda x: x.name):
f.write(str(installation))
+
FreezeCommand()
diff --git a/pip/commands/help.py b/pip/commands/help.py
index 571cd94ad..b0b366112 100644
--- a/pip/commands/help.py
+++ b/pip/commands/help.py
@@ -2,6 +2,7 @@ from pip.basecommand import Command, command_dict, load_all_commands
from pip.exceptions import InstallationError
from pip.baseparser import parser
+
class HelpCommand(Command):
name = 'help'
usage = '%prog'
@@ -27,4 +28,5 @@ class HelpCommand(Command):
continue
print ' %s: %s' % (command.name, command.summary)
+
HelpCommand()
diff --git a/pip/commands/install.py b/pip/commands/install.py
index f6f326498..695ca3f64 100644
--- a/pip/commands/install.py
+++ b/pip/commands/install.py
@@ -6,6 +6,7 @@ from pip.locations import build_prefix, src_prefix
from pip.basecommand import Command
from pip.index import PackageFinder
+
class InstallCommand(Command):
name = 'install'
usage = '%prog [OPTIONS] PACKAGE_NAMES...'
@@ -180,4 +181,5 @@ class InstallCommand(Command):
requirement_set.cleanup_files(bundle=self.bundle)
return requirement_set
+
InstallCommand()
diff --git a/pip/commands/search.py b/pip/commands/search.py
index 7f7f98500..785da3931 100644
--- a/pip/commands/search.py
+++ b/pip/commands/search.py
@@ -7,6 +7,7 @@ from pip.util import get_terminal_size
from pip.log import logger
from distutils.version import StrictVersion, LooseVersion
+
class SearchCommand(Command):
name = 'search'
usage = '%prog QUERY'
@@ -42,6 +43,7 @@ class SearchCommand(Command):
hits = pypi.search({'name': query, 'summary': query}, 'or')
return hits
+
def transform_hits(hits):
"""
The list from pypi is really a list of versions. We want a list of
@@ -69,6 +71,7 @@ def transform_hits(hits):
package_list = sorted(packages.values(), lambda x, y: cmp(y['score'], x['score']))
return package_list
+
def print_results(hits, name_column_width=25, terminal_width=None):
installed_packages = [p.project_name for p in pkg_resources.working_set]
for hit in hits:
@@ -96,6 +99,7 @@ def print_results(hits, name_column_width=25, terminal_width=None):
except UnicodeEncodeError:
pass
+
def compare_versions(version1, version2):
try:
return cmp(StrictVersion(version1), StrictVersion(version2))
@@ -103,7 +107,9 @@ def compare_versions(version1, version2):
except ValueError:
return cmp(LooseVersion(version1), LooseVersion(version2))
+
def highest_version(versions):
return reduce((lambda v1, v2: compare_versions(v1, v2) == 1 and v1 or v2), versions)
+
SearchCommand()
diff --git a/pip/commands/uninstall.py b/pip/commands/uninstall.py
index 1cfe70341..2ceb3c38a 100644
--- a/pip/commands/uninstall.py
+++ b/pip/commands/uninstall.py
@@ -2,6 +2,7 @@ from pip.req import InstallRequirement, RequirementSet
from pip.req import parse_requirements
from pip.basecommand import Command
+
class UninstallCommand(Command):
name = 'uninstall'
usage = '%prog [OPTIONS] PACKAGE_NAMES ...'
diff --git a/pip/commands/unzip.py b/pip/commands/unzip.py
index 15ccef072..f83e18205 100644
--- a/pip/commands/unzip.py
+++ b/pip/commands/unzip.py
@@ -1,7 +1,9 @@
from pip.commands.zip import ZipCommand
+
class UnzipCommand(ZipCommand):
name = 'unzip'
summary = 'Unzip individual packages'
+
UnzipCommand()
diff --git a/pip/commands/zip.py b/pip/commands/zip.py
index d2a3a74ac..346fc0519 100644
--- a/pip/commands/zip.py
+++ b/pip/commands/zip.py
@@ -9,6 +9,7 @@ from pip.log import logger
from pip.exceptions import InstallationError
from pip.basecommand import Command
+
class ZipCommand(Command):
name = 'zip'
usage = '%prog [OPTIONS] PACKAGE_NAMES...'
@@ -263,7 +264,7 @@ class ZipCommand(Command):
if not os.path.isdir(path) and zipfile.is_zipfile(path):
zip = zipfile.ZipFile(path, 'r')
try:
- zip.read(os.path.join(package,'__init__.py'))
+ zip.read(os.path.join(package, '__init__.py'))
except KeyError:
pass
else:
@@ -341,4 +342,5 @@ class ZipCommand(Command):
total += len(filenames)
return total
+
ZipCommand()
diff --git a/pip/exceptions.py b/pip/exceptions.py
index 1152cdc37..1ad1a616d 100644
--- a/pip/exceptions.py
+++ b/pip/exceptions.py
@@ -1,13 +1,17 @@
"""Exceptions used throughout package"""
+
class InstallationError(Exception):
"""General exception during installation"""
+
class UninstallationError(Exception):
"""General exception during uninstallation"""
+
class DistributionNotFound(InstallationError):
"""Raised when a distribution cannot be found to satisfy a requirement"""
+
class BadCommand(Exception):
"""Raised when virtualenv or a command is not found"""
diff --git a/pip/index.py b/pip/index.py
index 0fc6e2b8f..c4a9978dc 100644
--- a/pip/index.py
+++ b/pip/index.py
@@ -21,6 +21,7 @@ from pip.backwardcompat import WindowsError
__all__ = ['PackageFinder']
+
class PackageFinder(object):
"""This finds packages.
@@ -77,7 +78,6 @@ class PackageFinder(object):
urls.append(url)
return files, urls
-
def find_requirement(self, req, upgrade):
url_name = req.url_name
# Only check main index if index URL is given:
@@ -89,8 +89,9 @@ class PackageFinder(object):
page = self._get_page(main_index_url, req)
if page is None:
url_name = self._find_url_name(Link(self.index_urls[0]), url_name, req) or req.url_name
+
def mkurl_pypi_url(url):
- loc = posixpath.join(url, url_name)
+ loc = posixpath.join(url, url_name)
# For maximum compatibility with easy_install, ensure the path
# ends in a trailing slash. Although this isn't in the spec
# (and PyPI can handle it without the slash) some other index
@@ -331,6 +332,7 @@ class PageCache(object):
for url in urls:
self._pages[url] = page
+
class HTMLPage(object):
"""Represents one page, along with its URL"""
@@ -385,7 +387,7 @@ class HTMLPage(object):
cache.set_is_archive(url)
return None
logger.debug('Getting page %s' % url)
-
+
# Tack index.html onto file:// URLs that point to directories
(scheme, netloc, path, params, query, fragment) = urlparse.urlparse(url)
if scheme == 'file' and os.path.isdir(urllib.url2pathname(path)):
@@ -517,6 +519,7 @@ class HTMLPage(object):
return self._clean_re.sub(
lambda match: '%%%2x' % ord(match.group(0)), url)
+
class Link(object):
def __init__(self, url, comes_from=None):
@@ -582,6 +585,7 @@ class Link(object):
def show_url(self):
return posixpath.basename(self.url.split('#', 1)[0].split('?', 1)[0])
+
def get_requirement_from_url(url):
"""Get a requirement from the URL, if possible. This looks for #egg
in the URL"""
@@ -591,6 +595,7 @@ def get_requirement_from_url(url):
egg_info = splitext(link.filename)[0]
return package_to_requirement(egg_info)
+
def package_to_requirement(package_name):
"""Translate a name like Foo-1.2 to Foo==1.3"""
match = re.search(r'^(.*?)(-dev|-\d.*)', package_name)
diff --git a/pip/log.py b/pip/log.py
index dafa99c86..0218ab1ae 100644
--- a/pip/log.py
+++ b/pip/log.py
@@ -4,6 +4,7 @@
import sys
import logging
+
class Logger(object):
"""
@@ -30,16 +31,22 @@ class Logger(object):
def debug(self, msg, *args, **kw):
self.log(self.DEBUG, msg, *args, **kw)
+
def info(self, msg, *args, **kw):
self.log(self.INFO, msg, *args, **kw)
+
def notify(self, msg, *args, **kw):
self.log(self.NOTIFY, msg, *args, **kw)
+
def warn(self, msg, *args, **kw):
self.log(self.WARN, msg, *args, **kw)
+
def error(self, msg, *args, **kw):
self.log(self.WARN, msg, *args, **kw)
+
def fatal(self, msg, *args, **kw):
self.log(self.FATAL, msg, *args, **kw)
+
def log(self, level, msg, *args, **kw):
if args:
if kw:
diff --git a/pip/req.py b/pip/req.py
index de4743b16..711a8e84d 100644
--- a/pip/req.py
+++ b/pip/req.py
@@ -30,6 +30,7 @@ from pip import call_subprocess
from pip.backwardcompat import any, md5
from pip.index import Link
+
class InstallRequirement(object):
def __init__(self, req, comes_from, source_dir=None, editable=False,
@@ -695,6 +696,7 @@ execfile(__file__)
assert self.source_dir
return os.path.join(self.source_dir, 'pip-delete-this-directory.txt')
+
DELETE_MARKER_MESSAGE = '''\
This file is placed here by pip to indicate the source was put
here by pip.
@@ -703,6 +705,7 @@ Once this package is successfully installed this source code will be
deleted (unless you remove this file).
'''
+
class RequirementSet(object):
def __init__(self, build_dir, src_dir, download_dir, download_cache=None,
@@ -1334,8 +1337,10 @@ class RequirementSet(object):
name = name.replace(os.path.sep, '/')
return name
+
_scheme_re = re.compile(r'^(http|https|file):', re.I)
+
def parse_requirements(filename, finder=None, comes_from=None, options=None):
skip_match = None
skip_regex = options.skip_requirements_regex
@@ -1372,16 +1377,19 @@ def parse_requirements(filename, finder=None, comes_from=None, options=None):
line = line[len('--find-links'):].strip().lstrip('=')
## FIXME: it would be nice to keep track of the source of
## the find_links:
- if finder: finder.find_links.append(line)
+ if finder:
+ finder.find_links.append(line)
elif line.startswith('-i') or line.startswith('--index-url'):
if line.startswith('-i'):
line = line[2:].strip()
else:
line = line[len('--index-url'):].strip().lstrip('=')
- if finder: finder.index_urls = [line]
+ if finder:
+ finder.index_urls = [line]
elif line.startswith('--extra-index-url'):
line = line[len('--extra-index-url'):].strip().lstrip('=')
- if finder: finder.index_urls.append(line)
+ if finder:
+ finder.index_urls.append(line)
else:
comes_from = '-r %s (line %s)' % (filename, line_number)
if line.startswith('-e') or line.startswith('--editable'):
@@ -1395,6 +1403,7 @@ def parse_requirements(filename, finder=None, comes_from=None, options=None):
req = InstallRequirement.from_line(line, comes_from)
yield req
+
def parse_editable(editable_req, default_vcs=None):
"""Parses svn+http://blahblah@rev#egg=Foobar into a requirement
(Foobar) and a URL"""
@@ -1437,6 +1446,7 @@ def parse_editable(editable_req, default_vcs=None):
req = match.group(1)
return req, url
+
class UninstallPathSet(object):
"""A set of file paths to be removed in the uninstallation of a
requirement."""
@@ -1498,7 +1508,6 @@ class UninstallPathSet(object):
return os.path.join(
self.save_dir, os.path.splitdrive(path)[1].lstrip(os.path.sep))
-
def remove(self, auto_confirm=False):
"""Remove paths in ``self.paths`` with confirmation (unless
``auto_confirm`` is True)."""
@@ -1569,7 +1578,7 @@ class UninstallPthEntries(object):
# paths outside of site-packages, but all the others use forward
# slashes.
if sys.platform == 'win32' and not os.path.splitdrive(entry)[0]:
- entry = entry.replace('\\','/')
+ entry = entry.replace('\\', '/')
self.entries.add(entry)
def remove(self):
@@ -1601,6 +1610,7 @@ class UninstallPthEntries(object):
fh.close()
return True
+
class FakeFile(object):
"""Wrap a list of lines in an object with readline() to make
ConfigParser happy."""
diff --git a/pip/runner.py b/pip/runner.py
index 7f0fa7db8..be830ad9a 100644
--- a/pip/runner.py
+++ b/pip/runner.py
@@ -1,6 +1,7 @@
import sys
import os
+
def run():
base = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
## FIXME: this is kind of crude; if we could create a fake pip
@@ -10,6 +11,7 @@ def run():
import pip
return pip.main()
+
if __name__ == '__main__':
exit = run()
if exit:
diff --git a/pip/util.py b/pip/util.py
index 72834db69..98209ce04 100644
--- a/pip/util.py
+++ b/pip/util.py
@@ -23,10 +23,12 @@ __all__ = ['rmtree', 'display_path', 'backup_dir',
'make_path_relative', 'normalize_path',
'get_file_content', 'renames', 'get_terminal_size']
+
def rmtree(dir):
shutil.rmtree(dir, ignore_errors=True,
onerror=rmtree_errorhandler)
+
def rmtree_errorhandler(func, path, exc_info):
"""On Windows, the files in .svn are read-only, so when rmtree() tries to
remove them, an exception is thrown. We catch that here, remove the
@@ -43,6 +45,7 @@ def rmtree_errorhandler(func, path, exc_info):
# use the original function to repeat the operation
func(path)
+
def display_path(path):
"""Gives the display value for a given path, making it relative to cwd
if possible."""
@@ -51,6 +54,7 @@ def display_path(path):
path = '.' + path[len(os.getcwd()):]
return path
+
def backup_dir(dir, ext='.bak'):
"""Figure out the name of a directory to back up the given dir to
(adding .bak, .bak2, etc)"""
@@ -61,6 +65,7 @@ def backup_dir(dir, ext='.bak'):
extension = ext + str(n)
return dir + extension
+
def splitext(path):
"""Like os.path.splitext, but take off .tar too"""
base, ext = posixpath.splitext(path)
@@ -69,6 +74,7 @@ def splitext(path):
base = base[:-4]
return base, ext
+
def find_command(cmd, paths=None, pathext=None):
"""Searches the PATH for the given command and returns its path"""
if paths is None:
@@ -95,6 +101,7 @@ def find_command(cmd, paths=None, pathext=None):
return cmd_path
return None
+
def ask(message, options):
"""Ask the message interactively, with the given possible responses"""
while 1:
@@ -108,14 +115,17 @@ def ask(message, options):
else:
return response
+
class _Inf(object):
"""I am bigger than everything!"""
def __cmp__(self, a):
if self is a:
return 0
return 1
+
def __repr__(self):
return 'Inf'
+
Inf = _Inf()
del _Inf
@@ -134,9 +144,11 @@ def url_to_path(url):
path = '/' + path
return path
+
_drive_re = re.compile('^([a-z]):', re.I)
_url_drive_re = re.compile('^([a-z])[:|]', re.I)
+
def path_to_url(path):
"""
Convert a path to a file: URL. The path will be made absolute.
@@ -149,6 +161,7 @@ def path_to_url(path):
url = url.lstrip('/')
return 'file:///' + url
+
def path_to_url2(path):
"""
Convert a path to a file: URL. The path will be made absolute and have
@@ -162,11 +175,14 @@ def path_to_url2(path):
url = url.lstrip('/')
return 'file:///' + drive + url
+
_normalize_re = re.compile(r'[^a-z]', re.I)
+
def normalize_name(name):
return _normalize_re.sub('-', name.lower())
+
def format_size(bytes):
if bytes > 1000*1000:
return '%.1fMb' % (bytes/1000.0/1000)
@@ -177,6 +193,7 @@ def format_size(bytes):
else:
return '%ibytes' % bytes
+
def is_url(name):
"""Returns true if the name looks like a URL"""
from pip.vcs import vcs
@@ -185,6 +202,7 @@ def is_url(name):
scheme = name.split(':', 1)[0].lower()
return scheme in ['http', 'https', 'file', 'ftp'] + vcs.all_schemes
+
def is_installable_dir(path):
"""Return True if `path` is a directory containing a setup.py file."""
if not os.path.isdir(path):
@@ -194,6 +212,7 @@ def is_installable_dir(path):
return True
return False
+
def is_archive_file(name):
"""Return True if `name` is a considered as an archive file."""
archives = ('.zip', '.tar.gz', '.tar.bz2', '.tgz', '.tar', '.pybundle')
@@ -202,11 +221,13 @@ def is_archive_file(name):
return True
return False
+
def is_svn_page(html):
"""Returns true if the page appears to be the index page of an svn repository"""
return (re.search(r'
[^<]*Revision \d+:', html)
and re.search(r'Powered by (?:]*?>)?Subversion', html, re.I))
+
def file_contents(filename):
fp = open(filename, 'rb')
try:
@@ -214,6 +235,7 @@ def file_contents(filename):
finally:
fp.close()
+
def split_leading_dir(path):
path = str(path)
path = path.lstrip('/').lstrip('\\')
@@ -225,6 +247,7 @@ def split_leading_dir(path):
else:
return path, ''
+
def has_leading_dir(paths):
"""Returns true if all the paths have the same leading path name
(i.e., everything is in one subdirectory in an archive)"""
@@ -239,6 +262,7 @@ def has_leading_dir(paths):
return False
return True
+
def make_path_relative(path, rel_to):
"""
Make a filename relative, where the filename path, and it is
@@ -267,6 +291,7 @@ def make_path_relative(path, rel_to):
return '.' + os.path.sep
return os.path.sep.join(full_parts)
+
def normalize_path(path):
"""
Convert a path to its canonical, case-normalized, absolute version.
@@ -274,9 +299,11 @@ def normalize_path(path):
"""
return os.path.normcase(os.path.realpath(path))
+
_scheme_re = re.compile(r'^(http|https|file):', re.I)
_url_slash_drive_re = re.compile(r'/*([a-z])\|', re.I)
+
def geturl(urllib2_resp):
"""
Use instead of urllib.addinfourl.geturl(), which appears to have
@@ -293,6 +320,7 @@ def geturl(urllib2_resp):
else:
return '%s//%s' % (scheme, rest)
+
def get_file_content(url, comes_from=None):
"""Gets the content of a file; it may be a filename, file: URL, or
http: URL. Returns (location, content)"""
@@ -323,6 +351,7 @@ def get_file_content(url, comes_from=None):
f.close()
return url, content
+
def renames(old, new):
"""Like os.renames(), but handles renaming across devices."""
# Implementation borrowed from os.renames().
@@ -339,6 +368,7 @@ def renames(old, new):
except OSError:
pass
+
def in_venv():
"""
Return True if we're running inside a virtualenv, False otherwise.
@@ -346,6 +376,7 @@ def in_venv():
"""
return hasattr(sys, 'real_prefix')
+
def is_local(path):
"""
Return True if path is within sys.prefix, if we're running in a virtualenv.
@@ -357,6 +388,7 @@ 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
@@ -367,6 +399,7 @@ def dist_is_local(dist):
"""
return is_local(dist_location(dist))
+
def get_installed_distributions(local_only=True, skip=('setuptools', 'pip', 'python')):
"""
Return a list of installed Distribution objects.
@@ -385,6 +418,7 @@ def get_installed_distributions(local_only=True, skip=('setuptools', 'pip', 'pyt
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
@@ -398,6 +432,7 @@ def egg_link_path(dist):
"""
return os.path.join(site_packages, dist.project_name) + '.egg-link'
+
def dist_location(dist):
"""
Get the site-packages location of this distribution. Generally
@@ -411,12 +446,15 @@ def dist_location(dist):
return egg_link
return dist.location
+
def get_terminal_size():
"""Returns a tuple (x, y) representing the width(x) and the height(x)
in characters of the terminal window."""
def ioctl_GWINSZ(fd):
try:
- import fcntl, termios, struct
+ import fcntl
+ import termios
+ import struct
cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ,
'1234'))
except:
@@ -434,9 +472,10 @@ def get_terminal_size():
cr = (os.environ.get('LINES', 25), os.environ.get('COLUMNS', 80))
return int(cr[1]), int(cr[0])
+
# Insurance against "creative" interpretation of the RFC:
# http://bugs.python.org/issue8732
def urlopen(url):
if isinstance(url, basestring):
- url = urllib2.Request(url, headers={'Accept-encoding':'identity'})
+ url = urllib2.Request(url, headers={'Accept-encoding': 'identity'})
return urllib2.urlopen(url)
diff --git a/pip/vcs/__init__.py b/pip/vcs/__init__.py
index 5a85e2424..40c950841 100644
--- a/pip/vcs/__init__.py
+++ b/pip/vcs/__init__.py
@@ -10,6 +10,7 @@ from pip.log import logger
__all__ = ['vcs', 'get_source_requirement', 'import_vcs_support']
+
class VcsSupport(object):
_registry = {}
schemes = ['ssh', 'git', 'hg', 'bzr', 'sftp']
@@ -75,8 +76,8 @@ class VcsSupport(object):
return self.get_backend(vc_type)
return None
-vcs = VcsSupport()
+vcs = VcsSupport()
class VersionControl(object):
@@ -218,6 +219,7 @@ class VersionControl(object):
def get_src_requirement(self, dist, location, find_tags=False):
raise NotImplementedError
+
def get_src_requirement(dist, location, find_tags):
version_control = vcs.get_backend_from_location(location)
if version_control:
@@ -225,6 +227,7 @@ def get_src_requirement(dist, location, find_tags):
logger.warn('cannot determine version of editable source in %s (is not SVN checkout, Git clone, Mercurial clone or Bazaar branch)' % location)
return dist.as_requirement()
+
def import_vcs_support():
# Import all the version control support modules:
here = os.path.dirname(__file__)
diff --git a/pip/vcs/bazaar.py b/pip/vcs/bazaar.py
index 0793bd41e..8a0deee69 100644
--- a/pip/vcs/bazaar.py
+++ b/pip/vcs/bazaar.py
@@ -7,6 +7,7 @@ from pip.log import logger
from pip.util import rmtree, display_path
from pip.vcs import vcs, VersionControl
+
class Bazaar(VersionControl):
name = 'bzr'
dirname = '.bzr'
@@ -130,4 +131,5 @@ class Bazaar(VersionControl):
full_egg_name = '%s-dev_r%s' % (dist.egg_name(), current_rev)
return '%s@%s#egg=%s' % (repo, current_rev, full_egg_name)
+
vcs.register(Bazaar)
diff --git a/pip/vcs/git.py b/pip/vcs/git.py
index e5ac0000f..67de10648 100644
--- a/pip/vcs/git.py
+++ b/pip/vcs/git.py
@@ -9,6 +9,7 @@ from pip.log import logger
from urllib import url2pathname
from urlparse import urlsplit, urlunsplit
+
class Git(VersionControl):
name = 'git'
dirname = '.git'
@@ -23,15 +24,15 @@ class Git(VersionControl):
# Works around an apparent Git bug
# (see http://article.gmane.org/gmane.comp.version-control.git/146500)
if url:
- scheme,netloc,path,query,fragment = urlsplit(url)
+ scheme, netloc, path, query, fragment = urlsplit(url)
if scheme.endswith('file'):
initial_slashes = path[:-len(path.lstrip('/'))]
- newpath = initial_slashes + url2pathname(path).replace('\\','/').lstrip('/')
+ newpath = initial_slashes + url2pathname(path).replace('\\', '/').lstrip('/')
url = urlunsplit((scheme, netloc, newpath, query, fragment))
after_plus = scheme.find('+')+1
url = scheme[:after_plus]+ urlunsplit((scheme[after_plus:], netloc, newpath, query, fragment))
- super(Git,self).__init__(url, *args, **kwargs)
+ super(Git, self).__init__(url, *args, **kwargs)
def parse_vcs_bundle_file(self, content):
url = rev = None
@@ -86,7 +87,7 @@ class Git(VersionControl):
if rev in revisions:
# if rev is a sha
return [rev]
- inverse_revisions = dict((v,k) for k, v in revisions.iteritems())
+ inverse_revisions = dict((v, k) for k, v in revisions.iteritems())
if rev not in inverse_revisions: # is rev a name or tag?
origin_rev = 'origin/%s' % rev
if origin_rev in inverse_revisions:
@@ -197,9 +198,10 @@ class Git(VersionControl):
self.url = self.url.replace('git+', 'git+ssh://')
url, rev = super(Git, self).get_url_rev()
url = url.replace('ssh://', '')
- else:
+ else:
url, rev = super(Git, self).get_url_rev()
- return url,rev
+ return url, rev
+
vcs.register(Git)
diff --git a/pip/vcs/subversion.py b/pip/vcs/subversion.py
index 0d9503a18..044120d68 100644
--- a/pip/vcs/subversion.py
+++ b/pip/vcs/subversion.py
@@ -11,6 +11,7 @@ _svn_rev_re = re.compile('committed-rev="(\d+)"')
_svn_url_re = re.compile(r'URL: (.+)')
_svn_revision_re = re.compile(r'Revision: (.+)')
+
class Subversion(VersionControl):
name = 'svn'
dirname = '.svn'
@@ -140,7 +141,7 @@ class Subversion(VersionControl):
f.close()
if data.startswith('8') or data.startswith('9') or data.startswith('10'):
- data = map(str.splitlines,data.split('\n\x0c\n'))
+ data = map(str.splitlines, data.split('\n\x0c\n'))
del data[0][0] # get rid of the '8'
dirurl = data[0][3]
revs = [int(d[9]) for d in data if len(d)>9 and d[9]]+[0]
@@ -190,7 +191,7 @@ class Subversion(VersionControl):
data = f.read()
f.close()
if data.startswith('8') or data.startswith('9') or data.startswith('10'):
- data = map(str.splitlines,data.split('\n\x0c\n'))
+ data = map(str.splitlines, data.split('\n\x0c\n'))
del data[0][0] # get rid of the '8'
return data[0][3]
elif data.startswith('> sys.stderr, 'Cleaning ...',
for dirpath, dirnames, filenames in os.walk(root):
@@ -57,8 +63,10 @@ def clean(root):
rmtree(root/'pip.egg-info')
rmtree(root/'tests'/'test-scratch')
rmtree(root/'tests'/'test-cache')
- try: os.unlink(root/'tests'/'packages'/'FSPkg'/'FSPkg.egg-info'/'PKG-INFO')
- except: pass
+ try:
+ os.unlink(root/'tests'/'packages'/'FSPkg'/'FSPkg.egg-info'/'PKG-INFO')
+ except:
+ pass
print >> sys.stderr, 'ok'
@@ -73,7 +81,7 @@ def main(argv):
# Make sure all external tools are set up to be used.
print >> sys.stderr, 'Checking for installed prerequisites in PATH:',
for tool in 'git', 'hg', 'bzr', 'svn':
- print >> sys.stderr, tool,'...',
+ print >> sys.stderr, tool, '...',
assert_in_path(tool)
print >> sys.stderr, 'ok'
@@ -82,8 +90,8 @@ def main(argv):
#
# Delete everything that could lead to stale test results
#
- clean( pip_root )
-
+ clean(pip_root)
+
save_dir = os.getcwd()
temp_dir = mkdtemp('-pip_auto_test')
try:
@@ -99,8 +107,7 @@ def main(argv):
# Make sure it's first in PATH
os.environ['PATH'] = str(
- Path.pathsep.join(( abs_bin, os.environ['PATH'] ))
- )
+ Path.pathsep.join((abs_bin, os.environ['PATH'])))
#
# Install python module testing prerequisites
@@ -108,16 +115,18 @@ def main(argv):
pip = abs_bin/'pip'+exe
download_cache = '--download-cache=' \
+ Path(gettempdir())/'pip-test-download-cache'
+
def pip_install(*pkg):
- print >> sys.stderr, ' pip install',' '.join(pkg), '...',
+ print >> sys.stderr, ' pip install', ' '.join(pkg), '...',
call(pip, 'install', '-q', download_cache, *pkg)
print >> sys.stderr, 'ok'
+
pip_install('virtualenv')
pip_install('--no-index', '-f', 'http://pypi.python.org/packages/source/n/nose/', 'nose')
pip_install('scripttest>=1.0.4')
print >> sys.stderr, 'ok'
nosetests = abs_bin/'nosetests'+exe
- call( nosetests, '-w', pip_root/'tests', *(x for x in argv[1:] if x != '--distribute') )
+ call(nosetests, '-w', pip_root/'tests', *(x for x in argv[1:] if x != '--distribute'))
finally:
os.chdir(save_dir)
@@ -127,4 +136,4 @@ def main(argv):
if __name__ == '__main__':
- main( sys.argv )
+ main(sys.argv)
diff --git a/tests/path.py b/tests/path.py
index 9ab57ec47..5d6fdfed6 100644
--- a/tests/path.py
+++ b/tests/path.py
@@ -1,194 +1,194 @@
# -*- coding: utf-8 -*-
# Author: Aziz Köksal
-import os, shutil, sys
+import os
+import shutil
+import sys
_base = os.path.supports_unicode_filenames and unicode or str
+
class Path(_base):
- """ Models a path in an object oriented way. """
- sep = os.sep # File system path separator: '/' or '\'.
- pathsep = os.pathsep # Separator in the PATH environment variable.
-
- string = _base
+ """ Models a path in an object oriented way. """
- def __new__(cls, *paths):
- if len(paths):
- return _base.__new__(cls, os.path.join(*paths))
- return _base.__new__(cls)
+ sep = os.sep # File system path separator: '/' or '\'.
+ pathsep = os.pathsep # Separator in the PATH environment variable.
+ string = _base
- def __div__(self, path):
- """ Joins this path with another path. """
- """ path_obj / 'bc.d' """
- """ path_obj / path_obj2 """
- return Path(self, path)
+ def __new__(cls, *paths):
+ if len(paths):
+ return _base.__new__(cls, os.path.join(*paths))
+ return _base.__new__(cls)
- def __rdiv__(self, path):
- """ Joins this path with another path. """
- """ "/home/a" / path_obj """
- return Path(path, self)
+ def __div__(self, path):
+ """ Joins this path with another path. """
+ """ path_obj / 'bc.d' """
+ """ path_obj / path_obj2 """
+ return Path(self, path)
- def __idiv__(self, path):
- """ Like __div__ but also assigns to the variable. """
- """ path_obj /= 'bc.d' """
- return Path(self, path)
+ def __rdiv__(self, path):
+ """ Joins this path with another path. """
+ """ "/home/a" / path_obj """
+ return Path(path, self)
- def __floordiv__(self, paths):
- """ Returns a list of paths prefixed with 'self'. """
- """ '/home/a' // [bc.d, ef.g] -> [/home/a/bc.d, /home/a/ef.g] """
- return [Path(self, path) for path in paths]
+ def __idiv__(self, path):
+ """ Like __div__ but also assigns to the variable. """
+ """ path_obj /= 'bc.d' """
+ return Path(self, path)
+ def __floordiv__(self, paths):
+ """ Returns a list of paths prefixed with 'self'. """
+ """ '/home/a' // [bc.d, ef.g] -> [/home/a/bc.d, /home/a/ef.g] """
+ return [Path(self, path) for path in paths]
+ def __sub__(self, path):
+ """ Makes this path relative to another path. """
+ """ path_obj - '/home/a' """
+ """ path_obj - path_obj2 """
+ return Path(os.path.relpath(self, path))
- def __sub__(self, path):
- """ Makes this path relative to another path. """
- """ path_obj - '/home/a' """
- """ path_obj - path_obj2 """
- return Path(os.path.relpath(self, path))
+ def __rsub__(self, path):
+ """ Returns path relative to this path. """
+ """ "/home/a" - path_obj """
+ return Path(os.path.relpath(path, self))
- def __rsub__(self, path):
- """ Returns path relative to this path. """
- """ "/home/a" - path_obj """
- return Path(os.path.relpath(path, self))
+ def __add__(self, path):
+ """ Path('/home/a') + 'bc.d' -> '/home/abc.d' """
+ return Path(_base(self) + path)
+ def __radd__(self, path):
+ """ '/home/a' + Path('bc.d') -> '/home/abc.d' """
+ return Path(path + _base(self))
- def __add__(self, path):
- """ Path('/home/a') + 'bc.d' -> '/home/abc.d' """
- return Path(_base(self) + path)
+ def __repr__(self):
+ return u"Path(%s)" % _base.__repr__(self)
- def __radd__(self, path):
- """ '/home/a' + Path('bc.d') -> '/home/abc.d' """
- return Path(path + _base(self))
+ def __hash__(self):
+ return _base.__hash__(self)
- def __repr__(self):
- return u"Path(%s)" % _base.__repr__(self)
+ @property
+ def name(self):
+ """ '/home/a/bc.d' -> 'bc.d' """
+ return os.path.basename(self)
- def __hash__(self):
- return _base.__hash__(self)
+ @property
+ def namebase(self):
+ """ '/home/a/bc.d' -> 'bc' """
+ return self.noext.name
- @property
- def name(self):
- """ '/home/a/bc.d' -> 'bc.d' """
- return os.path.basename(self)
+ @property
+ def noext(self):
+ """ '/home/a/bc.d' -> '/home/a/bc' """
+ return Path(os.path.splitext(self)[0])
- @property
- def namebase(self):
- """ '/home/a/bc.d' -> 'bc' """
- return self.noext.name
+ @property
+ def ext(self):
+ """ '/home/a/bc.d' -> '.d' """
+ return Path(os.path.splitext(self)[1])
- @property
- def noext(self):
- """ '/home/a/bc.d' -> '/home/a/bc' """
- return Path(os.path.splitext(self)[0])
+ @property
+ def abspath(self):
+ """ './a/bc.d' -> '/home/a/bc.d' """
+ return Path(os.path.abspath(self))
- @property
- def ext(self):
- """ '/home/a/bc.d' -> '.d' """
- return Path(os.path.splitext(self)[1])
+ @property
+ def realpath(self):
+ """ Resolves symbolic links. """
+ return Path(os.path.realpath(self))
- @property
- def abspath(self):
- """ './a/bc.d' -> '/home/a/bc.d' """
- return Path(os.path.abspath(self))
+ @property
+ def normpath(self):
+ """ '/home/x/.././a//bc.d' -> '/home/a/bc.d' """
+ return Path(os.path.normpath(self))
- @property
- def realpath(self):
- """ Resolves symbolic links. """
- return Path(os.path.realpath(self))
+ @property
+ def normcase(self):
+ """ Deals with case-insensitive filesystems """
+ return Path(os.path.normcase(self))
- @property
- def normpath(self):
- """ '/home/x/.././a//bc.d' -> '/home/a/bc.d' """
- return Path(os.path.normpath(self))
+ @property
+ def folder(self):
+ """ Returns the folder of this path. """
+ """ '/home/a/bc.d' -> '/home/a' """
+ """ '/home/a/' -> '/home/a' """
+ """ '/home/a' -> '/home' """
+ return Path(os.path.dirname(self))
- @property
- def normcase(self):
- """ Deals with case-insensitive filesystems """
- return Path(os.path.normcase(self))
+ @property
+ def exists(self):
+ """ Returns True if the path exists. """
+ return os.path.exists(self)
- @property
- def folder(self):
- """ Returns the folder of this path. """
- """ '/home/a/bc.d' -> '/home/a' """
- """ '/home/a/' -> '/home/a' """
- """ '/home/a' -> '/home' """
- return Path(os.path.dirname(self))
+ @property
+ def atime(self):
+ """ Returns last accessed time. """
+ return os.path.getatime(self)
- @property
- def exists(self):
- """ Returns True if the path exists. """
- return os.path.exists(self)
+ @property
+ def mtime(self):
+ """ Returns last modified time. """
+ return os.path.getmtime(self)
- @property
- def atime(self):
- """ Returns last accessed time. """
- return os.path.getatime(self)
+ @property
+ def ctime(self):
+ """ Returns last changed time. """
+ return os.path.getctime(self)
- @property
- def mtime(self):
- """ Returns last modified time. """
- return os.path.getmtime(self)
+ @classmethod
+ def supports_unicode(self):
+ """ Returns True if the system can handle Unicode file names. """
+ return os.path.supports_unicode_filenames()
- @property
- def ctime(self):
- """ Returns last changed time. """
- return os.path.getctime(self)
+ def walk(self, **kwargs):
+ """ Returns a generator that walks through a directory tree. """
+ if "followlinks" in kwargs:
+ from sys import version_info as vi
+ if vi[0]*10+vi[1] < 26: # Only Python 2.6 or newer supports followlinks
+ del kwargs["followlinks"]
+ return os.walk(self, **kwargs)
- @classmethod
- def supports_unicode(self):
- """ Returns True if the system can handle Unicode file names. """
- return os.path.supports_unicode_filenames()
+ def mkdir(self, mode=0777):
+ """ Creates a directory, if it doesn't exist already. """
+ if not self.exists:
+ os.mkdir(self, mode)
- def walk(self, **kwargs):
- """ Returns a generator that walks through a directory tree. """
- if "followlinks" in kwargs:
- from sys import version_info as vi
- if vi[0]*10+vi[1] < 26: # Only Python 2.6 or newer supports followlinks.
- del kwargs["followlinks"]
- return os.walk(self, **kwargs)
+ def makedirs(self, mode=0777):
+ """ Like mkdir(), but also creates parent directories. """
+ if not self.exists:
+ os.makedirs(self, mode)
- def mkdir(self, mode=0777):
- """ Creates a directory, if it doesn't exist already. """
- if not self.exists:
- os.mkdir(self, mode)
+ def remove(self):
+ """ Removes a file. """
+ os.remove(self)
+ rm = remove # Alias.
- def makedirs(self, mode=0777):
- """ Like mkdir(), but also creates parent directories. """
- if not self.exists:
- os.makedirs(self, mode)
+ def rmdir(self):
+ """ Removes a directory. """
+ return os.rmdir(self)
- def remove(self):
- """ Removes a file. """
- os.remove(self)
- rm = remove # Alias.
+ def rmtree(self, noerrors=True):
+ """ Removes a directory tree. Ignores errors by default. """
+ return shutil.rmtree(self, ignore_errors=noerrors)
- def rmdir(self):
- """ Removes a directory. """
- return os.rmdir(self)
+ def copy(self, to):
+ shutil.copy(self, to)
- def rmtree(self, noerrors=True):
- """ Removes a directory tree. Ignores errors by default. """
- return shutil.rmtree(self, ignore_errors=noerrors)
+ def copytree(self, to):
+ """ Copies a directory tree to another path. """
+ shutil.copytree(self, to)
- def copy(self, to):
- shutil.copy(self, to)
+ def move(self, to):
+ """ Moves a file or directory to another path. """
+ shutil.move(self, to)
- def copytree(self, to):
- """ Copies a directory tree to another path. """
- shutil.copytree(self, to)
+ def rename(self, to):
+ """ Renames a file or directory. May throw an OSError. """
+ os.rename(self, to)
- def move(self, to):
- """ Moves a file or directory to another path. """
- shutil.move(self, to)
+ def renames(self, to):
+ os.renames(self, to)
- def rename(self, to):
- """ Renames a file or directory. May throw an OSError. """
- os.rename(self, to)
-
- def renames(self, to):
- os.renames(self, to)
-
- def glob(self, pattern):
- from glob import glob
- return map(Path, glob(_base(self/pattern)))
+ def glob(self, pattern):
+ from glob import glob
+ return map(Path, glob(_base(self/pattern)))
curdir = Path(os.path.curdir)
diff --git a/tests/test_all_pip.py b/tests/test_all_pip.py
index 1090c2456..2d058df07 100644
--- a/tests/test_all_pip.py
+++ b/tests/test_all_pip.py
@@ -12,6 +12,7 @@ def all_projects():
projects = [m.group(1) for m in re.finditer(r'(.+)', data)]
return projects
+
def main(args=None):
if args is None:
args = sys.argv[1:]
@@ -36,6 +37,7 @@ def main(args=None):
_test_packages(output, pending_fn)
print 'Finished all pending!'
+
def _test_packages(output, pending_fn):
package = get_last_item(pending_fn)
print 'Testing package %s' % package
@@ -72,13 +74,15 @@ def _test_packages(output, pending_fn):
add_package(os.path.join(output, 'success.txt'), package)
pop_last_item(pending_fn, package)
shutil.rmtree(dest_dir)
-
+
+
def get_last_item(fn):
f = open(fn, 'r')
lines = f.readlines()
f.close()
return lines[-1].strip()
+
def pop_last_item(fn, line=None):
f = open(fn, 'r')
lines = f.readlines()
@@ -90,10 +94,12 @@ def pop_last_item(fn, line=None):
f.writelines(lines)
f.close()
+
def add_package(filename, package):
f = open(filename, 'a')
f.write(package + '\n')
f.close()
+
if __name__ == '__main__':
main()
diff --git a/tests/test_basic.py b/tests/test_basic.py
index 1661503de..6a6228543 100644
--- a/tests/test_basic.py
+++ b/tests/test_basic.py
@@ -2,10 +2,11 @@ from os.path import abspath, exists, join, dirname, curdir, pardir
from test_pip import here, reset_env, run_pip, pyversion, mkdir
from path import Path
+
def test_correct_pip_version():
"""
Check we are running proper version of pip in run_pip.
-
+
"""
reset_env()
@@ -16,21 +17,23 @@ def test_correct_pip_version():
result = run_pip('--version')
# compare the directory tree of the invoked pip with that of this source distribution
- import re,filecmp
+ import re
+ import filecmp
dir = re.match(r'\s*pip\s\S+\sfrom\s+(.*)\s\([^(]+\)$', result.stdout).group(1)
- diffs = filecmp.dircmp(join(base,'pip'), join(dir,'pip'))
+ diffs = filecmp.dircmp(join(base, 'pip'), join(dir, 'pip'))
# If any non-matching .py files exist, we have a problem: run_pip
# is picking up some other version! N.B. if this project acquires
# primary resources other than .py files, this code will need
# maintenance
mismatch_py = [x for x in diffs.left_only + diffs.right_only + diffs.diff_files if x.endswith('.py')]
- assert not mismatch_py, 'mismatched source files in %r and %r'% (join(base,'pip'), join(dir,'pip'))
+ assert not mismatch_py, 'mismatched source files in %r and %r'% (join(base, 'pip'), join(dir, 'pip'))
+
def test_distutils_configuration_setting():
"""
Test the distutils-configuration-setting command (which is distinct from other commands).
-
+
"""
#print run_pip('-vv', '--distutils-cfg=easy_install:index_url:http://download.zope.org/ppix/', expect_error=True)
#Script result: python ../../poacheggs.py -E .../poacheggs-tests/test-scratch -vv --distutils-cfg=easy_install:index_url:http://download.zope.org/ppix/
@@ -42,20 +45,22 @@ def test_distutils_configuration_setting():
#-- updated: -------------------
# lib/python2.4/distutils/distutils.cfg (346 bytes)
+
def test_install_from_pypi():
"""
Test installing a package from PyPI.
-
+
"""
e = reset_env()
result = run_pip('install', '-vvv', 'INITools==0.2')
assert (e.site_packages / 'INITools-0.2-py%s.egg-info' % pyversion) in result.files_created, str(result)
assert (e.site_packages / 'initools') in result.files_created, str(result)
+
def test_editable_install():
"""
Test editable installation.
-
+
"""
reset_env()
result = run_pip('install', '-e', 'INITools==0.2', expect_error=True)
@@ -63,19 +68,21 @@ def test_editable_install():
assert len(result.files_created) == 1, result.files_created
assert not result.files_updated, result.files_updated
+
def test_install_editable_from_svn():
"""
Test checking out from svn.
-
+
"""
e = reset_env()
result = run_pip('install', '-e', 'svn+http://svn.colorstudy.com/INITools/trunk#egg=initools-dev')
result.assert_installed('INITools', with_files=['.svn'])
+
def test_download_editable_to_custom_path():
"""
Test downloading an editable using a relative custom src folder.
-
+
"""
reset_env()
mkdir('customdl')
@@ -84,14 +91,15 @@ def test_download_editable_to_custom_path():
customsrc = Path('scratch')/'customsrc'/'initools'
assert customsrc in result.files_created, sorted(result.files_created.keys())
assert customsrc/'setup.py' in result.files_created, sorted(result.files_created.keys())
-
+
customdl = Path('scratch')/'customdl'/'initools'
assert [filename for filename in result.files_created.keys() if filename.startswith(customdl)]
+
def test_editable_no_install_followed_by_no_download():
"""
Test installing an editable in two steps (first with --no-install, then with --no-download).
-
+
"""
reset_env()
@@ -100,13 +108,14 @@ def test_editable_no_install_followed_by_no_download():
result.assert_installed('INITools', without_egg_link=True, with_files=['.svn'])
result = run_pip('install', '-e', 'svn+http://svn.colorstudy.com/INITools/trunk#egg=initools-dev',
- '--no-download', expect_error=True)
+ '--no-download', expect_error=True)
result.assert_installed('INITools', without_files=[curdir, '.svn'])
+
def test_no_install_followed_by_no_download():
"""
Test installing in two steps (first with --no-install, then with --no-download).
-
+
"""
env = reset_env()
@@ -117,62 +126,68 @@ def test_no_install_followed_by_no_download():
assert build_dir in result.files_created, result.files_created
assert build_dir/'INITools.egg-info' in result.files_created
- result = run_pip('install', 'INITools==0.2', '--no-download', expect_error=True)
+ result = run_pip('install', 'INITools==0.2', '--no-download', expect_error=True)
assert (env.site_packages/'INITools-0.2-py%s.egg-info' % pyversion) in result.files_created, str(result)
assert (env.site_packages/'initools') in result.files_created, sorted(result.files_created.keys())
assert build_dir not in result.files_created
assert build_dir/'INITools.egg-info' not in result.files_created
+
def test_bad_install_with_no_download():
"""
Test that --no-download behaves sensibly if the package source can't be found.
-
+
"""
reset_env()
- result = run_pip('install', 'INITools==0.2', '--no-download', expect_error=True)
+ result = run_pip('install', 'INITools==0.2', '--no-download', expect_error=True)
assert result.stdout.find("perhaps --no-download was used without first running an equivalent install with --no-install?") > 0
+
def test_install_dev_version_from_pypi():
"""
Test using package==dev.
-
+
"""
e = reset_env()
result = run_pip('install', 'INITools==dev', expect_error=True)
assert (e.site_packages / 'initools') in result.files_created, str(result.stdout)
+
def test_install_editable_from_git():
"""
Test cloning from Git.
-
+
"""
e = reset_env()
result = run_pip('install', '-e', 'git://github.com/jezdez/django-feedutil.git#egg=django-feedutil', expect_error=True)
result.assert_installed('django-feedutil', with_files=['.git'])
+
def test_install_editable_from_hg():
"""
Test cloning from Mercurial.
-
+
"""
e = reset_env()
result = run_pip('install', '-e', 'hg+http://bitbucket.org/ubernostrum/django-registration/#egg=django-registration', expect_error=True)
result.assert_installed('django-registration', with_files=['.hg'])
+
def test_vcs_url_final_slash_normalization():
"""
Test that presence or absence of final slash in VCS URL is normalized.
-
"""
+
reset_env()
result = run_pip('install', '-e', 'hg+http://bitbucket.org/ubernostrum/django-registration#egg=django-registration', expect_error=True)
assert 'pip-log.txt' not in result.files_created, result.files_created['pip-log.txt'].bytes
+
def test_install_editable_from_bazaar():
"""
Test checking out from Bazaar.
-
+
"""
e = reset_env()
result = run_pip('install', '-e', 'bzr+http://bazaar.launchpad.net/%7Edjango-wikiapp/django-wikiapp/release-0.1/@174#egg=django-wikiapp', expect_error=True)
@@ -182,12 +197,13 @@ def test_install_editable_from_bazaar():
def test_vcs_url_urlquote_normalization():
"""
Test that urlquoted characters are normalized for repo URL comparison.
-
+
"""
reset_env()
result = run_pip('install', '-e', 'bzr+http://bazaar.launchpad.net/~django-wikiapp/django-wikiapp/release-0.1#egg=django-wikiapp', expect_error=True)
assert 'pip-log.txt' not in result.files_created, result.files_created['pip-log.txt'].bytes
+
def test_install_from_local_directory():
"""
Test installing from a local directory.
@@ -199,17 +215,19 @@ def test_install_from_local_directory():
assert (env.site_packages/'fspkg') in result.files_created, str(result.stdout)
assert (env.site_packages/'FSPkg-0.1dev-py%s.egg-info' % pyversion) in result.files_created, str(result)
+
def test_install_from_local_directory_with_no_setup_py():
"""
Test installing from a local directory with no 'setup.py'.
-
"""
+
reset_env()
result = run_pip('install', here, expect_error=True)
assert len(result.files_created) == 1, result.files_created
assert 'pip-log.txt' in result.files_created, result.files_created
assert "is not installable. File 'setup.py' not found." in result.stdout
+
def test_install_curdir():
"""
Test installing current directory ('.').
@@ -221,6 +239,7 @@ def test_install_curdir():
assert (env.site_packages/'fspkg') in result.files_created, str(result.stdout)
assert (env.site_packages/'FSPkg-0.1dev-py%s.egg-info' % pyversion) in result.files_created, str(result)
+
def test_install_pardir():
"""
Test installing parent directory ('..').
diff --git a/tests/test_bundle.py b/tests/test_bundle.py
index 77cb5f5f6..8b6052af6 100644
--- a/tests/test_bundle.py
+++ b/tests/test_bundle.py
@@ -1,11 +1,11 @@
-
import zipfile
import textwrap
from os.path import abspath, join, dirname, pardir
-from test_pip import here, reset_env, run_pip, write_file
+from test_pip import here, reset_env, run_pip, write_file
from path import Path
from pip.util import path_to_url2
+
def test_create_bundle():
"""
Test making a bundle. We'll grab one package from the filesystem
diff --git a/tests/test_cleanup.py b/tests/test_cleanup.py
index 6ae3fbca6..20158884d 100644
--- a/tests/test_cleanup.py
+++ b/tests/test_cleanup.py
@@ -1,15 +1,14 @@
-
import zipfile
import textwrap
from os.path import abspath, exists, join
from test_pip import here, reset_env, run_pip, write_file
-from path import Path;
+from path import Path
def test_cleanup_after_install_from_pypi():
"""
Test clean up after installing a package from PyPI.
-
+
"""
env = reset_env()
result = run_pip('install', 'INITools==0.2', expect_error=True)
@@ -18,10 +17,11 @@ def test_cleanup_after_install_from_pypi():
assert not exists(build), "build/ dir still exists: %s" % build
assert not exists(src), "unexpected src/ dir exists: %s" % src
+
def test_cleanup_after_install_editable_from_hg():
"""
Test clean up after cloning from Mercurial.
-
+
"""
env = reset_env()
result = run_pip('install', '-e', 'hg+http://bitbucket.org/ubernostrum/django-registration/#egg=django-registration', expect_error=True)
@@ -30,6 +30,7 @@ def test_cleanup_after_install_editable_from_hg():
assert not exists(build), "build/ dir still exists: %s" % build
assert exists(src), "expected src/ dir doesn't exist: %s" % src
+
def test_cleanup_after_install_from_local_directory():
"""
Test clean up after installing from a local directory.
@@ -43,6 +44,7 @@ def test_cleanup_after_install_from_local_directory():
assert not exists(build), "unexpected build/ dir exists: %s" % build
assert not exists(src), "unexpected src/ dir exist: %s" % src
+
def test_cleanup_after_create_bundle():
"""
Test clean up after making a bundle. Make sure (build|src)-bundle/ dirs are removed but not src/.
diff --git a/tests/test_completion.py b/tests/test_completion.py
index e2d0625e5..d28d287dc 100644
--- a/tests/test_completion.py
+++ b/tests/test_completion.py
@@ -20,7 +20,6 @@ complete -o default -F _pip_completion pip"""
assert bash_completion in result.stdout, 'bash completion is wrong'
-
def test_completion_for_zsh():
"""
Test getting completion for zsh shell
@@ -31,7 +30,7 @@ function _pip_completion {
local words cword
read -Ac words
read -cn cword
- reply=( $( COMP_WORDS="$words[*]" \\
+ reply=( $( COMP_WORDS="$words[*]" \\
COMP_CWORD=$(( cword-1 )) \\
PIP_AUTO_COMPLETE=1 $words[1] ) )
}
@@ -41,7 +40,6 @@ compctl -K _pip_completion pip"""
assert zsh_completion in result.stdout, 'zsh completion is wrong'
-
def test_completion_for_unknown_shell():
"""
Test getting completion for an unknown shell
diff --git a/tests/test_config.py b/tests/test_config.py
index ecddedf3a..bc87e05ee 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -1,13 +1,13 @@
-
import tempfile
import textwrap
from test_pip import here, reset_env, run_pip, clear_environ, write_file
import os
+
def test_options_from_env_vars():
"""
Test if ConfigOptionParser reads env vars (e.g. not using PyPI here)
-
+
"""
environ = clear_environ(os.environ.copy())
environ['PIP_NO_INDEX'] = '1'
@@ -16,10 +16,11 @@ def test_options_from_env_vars():
assert "Ignoring indexes:" in result.stdout, str(result)
assert "DistributionNotFound: No distributions at all found for INITools" in result.stdout
+
def test_command_line_options_override_env_vars():
"""
Test that command line options override environmental variables.
-
+
"""
environ = clear_environ(os.environ.copy())
environ['PIP_INDEX_URL'] = 'http://pypi.appspot.com/'
@@ -31,10 +32,11 @@ def test_command_line_options_override_env_vars():
assert "http://pypi.appspot.com/INITools" not in result.stdout
assert "Getting page http://download.zope.org/ppix" in result.stdout
+
def test_command_line_append_flags():
"""
Test command line flags that append to defaults set by environmental variables.
-
+
"""
environ = clear_environ(os.environ.copy())
environ['PIP_FIND_LINKS'] = 'http://pypi.pinaxproject.com'
@@ -46,11 +48,12 @@ def test_command_line_append_flags():
assert "Analyzing links from page http://pypi.pinaxproject.com" in result.stdout
assert "Analyzing links from page http://example.com" in result.stdout
+
def test_config_file_override_stack():
"""
Test config files (global, overriding a global config with a
local, overriding all with a command line flag).
-
+
"""
f, config_file = tempfile.mkstemp('-pip.cfg', 'test-')
environ = clear_environ(os.environ.copy())
@@ -76,10 +79,11 @@ def test_config_file_override_stack():
assert "Getting page http://pypi.appspot.com/INITools" not in result.stdout
assert "Getting page http://pypi.python.org/simple/INITools" in result.stdout
+
def test_log_file_no_directory():
"""
Test opening a log file with no directory name.
-
+
"""
from pip.basecommand import open_logfile
fp = open_logfile('testpip.log')
diff --git a/tests/test_download.py b/tests/test_download.py
index 661b82da1..5adf9c297 100644
--- a/tests/test_download.py
+++ b/tests/test_download.py
@@ -1,23 +1,26 @@
from os import makedirs
from os.path import join
import textwrap
-from test_pip import here, reset_env, run_pip, pyversion, write_file
+from test_pip import here, reset_env, run_pip, pyversion, write_file
from path import Path
+
def test_download_if_requested():
"""
It should download (in the scratch path) and not install if requested.
-
"""
+
env = reset_env()
result = run_pip('install', 'INITools==0.1', '-d', '.', expect_error=True)
assert Path('scratch')/ 'INITools-0.1.tar.gz' in result.files_created
assert env.site_packages/ 'initools' not in result.files_created
+
def test_single_download_from_requirements_file():
"""
It should support download (in the scratch path) from PyPi from a requirements file
"""
+
env = reset_env()
write_file('test-req.txt', textwrap.dedent("""
INITools==0.1
diff --git a/tests/test_file_scheme_index.py b/tests/test_file_scheme_index.py
index c5cecae3d..f7f8f8c3e 100644
--- a/tests/test_file_scheme_index.py
+++ b/tests/test_file_scheme_index.py
@@ -5,6 +5,7 @@ from path import Path
index_url = 'file://' + urllib2.quote(str(Path(here).abspath/'in dex').replace('\\', '/'))
+
def test_install():
"""
Test installing from a local index.
diff --git a/tests/test_freeze.py b/tests/test_freeze.py
index f725754d4..955c7459d 100644
--- a/tests/test_freeze.py
+++ b/tests/test_freeze.py
@@ -1,11 +1,13 @@
-
-import os, sys, re
+import os
+import sys
+import re
import textwrap
from doctest import OutputChecker, ELLIPSIS
-from test_pip import reset_env, run_pip, pyversion, write_file, get_env
+from test_pip import reset_env, run_pip, pyversion, write_file, get_env
distribute_re = re.compile('^distribute==[0-9.]+\n', re.MULTILINE)
+
def _check_output(result, expected):
checker = OutputChecker()
actual = str(result)
@@ -19,15 +21,17 @@ def _check_output(result, expected):
## thing to do in the end is probably to find out how to report
## the proper fully-cased package name in our error message.
if sys.platform == 'win32':
- actual = actual.replace('initools','INITools')
+ actual = actual.replace('initools', 'INITools')
# This allows our existing tests to work when run in a context
# with distribute installed.
actual = distribute_re.sub('', actual)
- def banner(msg): return '\n========== %s ==========\n'%msg
+ def banner(msg):
+ return '\n========== %s ==========\n' % msg
assert checker.check_output(expected, actual, ELLIPSIS), banner('EXPECTED')+expected+banner('ACTUAL')+actual+banner(6*'=')
+
def test_freeze():
"""
Some tests of freeze, first we have to install some stuff. Note that
@@ -38,7 +42,7 @@ def test_freeze():
TODO: refactor this test into multiple tests? (and maybe different
test style instead of using doctest output checker)
-
+
"""
env = reset_env()
write_file('initools-req.txt', textwrap.dedent("""\
@@ -96,15 +100,16 @@ def test_freeze():
""")
_check_output(result, expected)
+
def test_freeze_git_clone():
"""
Test freezing a Git clone.
-
+
"""
env = reset_env()
result = env.run('git', 'clone', 'git://github.com/jezdez/django-pagination.git', 'django-pagination')
result = env.run('git', 'checkout', '1df6507872d73ee387eb375428eafbfc253dfcd8',
- cwd= env.scratch_path/ 'django-pagination', expect_stderr=True)
+ cwd=env.scratch_path/'django-pagination', expect_stderr=True)
result = env.run('python', 'setup.py', 'develop',
cwd=env.scratch_path / 'django-pagination')
result = run_pip('freeze', expect_stderr=True)
@@ -124,10 +129,11 @@ def test_freeze_git_clone():
...""")
_check_output(result, expected)
+
def test_freeze_mercurial_clone():
"""
Test freezing a Mercurial clone.
-
+
"""
reset_env()
env = get_env()
@@ -151,10 +157,11 @@ def test_freeze_mercurial_clone():
...""")
_check_output(result, expected)
+
def test_freeze_bazaar_clone():
"""
Test freezing a Bazaar clone.
-
+
"""
reset_env()
env = get_env()
@@ -178,10 +185,11 @@ def test_freeze_bazaar_clone():
...""")
_check_output(result, expected)
+
def test_freeze_with_local_option():
"""
Test that wsgiref (from global site-packages) is reported normally, but not with --local.
-
+
"""
reset_env()
result = run_pip('install', 'initools==0.2')
diff --git a/tests/test_pip.py b/tests/test_pip.py
index ff990709d..c2e43d220 100644
--- a/tests/test_pip.py
+++ b/tests/test_pip.py
@@ -1,5 +1,11 @@
#!/usr/bin/env python
-import os, sys, tempfile, shutil, glob, atexit, textwrap
+import os
+import sys
+import tempfile
+import shutil
+import glob
+import atexit
+import textwrap
from path import *
from scripttest import TestFileEnvironment
@@ -10,32 +16,35 @@ pyversion = sys.version[:3]
here = Path(__file__).abspath.folder
# the root of this pip source distribution
-src = os.path.dirname(here)
+src = os.path.dirname(here)
download_cache = os.path.join(tempfile.mkdtemp(), 'pip-test-cache')
+
def demand_dirs(path):
- if not os.path.exists(path):
+ if not os.path.exists(path):
os.makedirs(path)
-
+
demand_dirs(download_cache)
# Tweak the path so we can find up-to-date pip sources
# (http://bitbucket.org/ianb/pip/issue/98)
sys.path = [src] + sys.path
+
def create_virtualenv(where, distribute=False):
save_argv = sys.argv
-
+
try:
import virtualenv
distribute_opt = distribute and ['--distribute'] or []
sys.argv = ['virtualenv', '--quiet'] + distribute_opt + ['--no-site-packages', '--unzip-setuptools', where]
virtualenv.main()
- finally:
+ finally:
sys.argv = save_argv
return virtualenv.path_locations(where)
+
def relpath(root, other):
"""a poor man's os.path.relpath, since we may not have Python 2.6"""
prefix = root+Path.sep
@@ -45,6 +54,7 @@ def relpath(root, other):
if 'PYTHONPATH' in os.environ:
del os.environ['PYTHONPATH']
+
try:
any
except NameError:
@@ -54,16 +64,18 @@ except NameError:
return True
return False
+
def clear_environ(environ):
return dict(((k, v) for k, v in environ.iteritems()
if not k.lower().startswith('pip_')))
+
def install_setuptools(env):
easy_install = os.path.join(env.bin_path, 'easy_install')
version = 'setuptools==0.6c11'
if sys.platform != 'win32':
return env.run(easy_install, version)
-
+
tempdir = tempfile.mkdtemp()
try:
for f in glob.glob(easy_install+'*'):
@@ -72,17 +84,19 @@ def install_setuptools(env):
finally:
shutil.rmtree(tempdir)
-def reset_env(environ = None):
+
+def reset_env(environ=None):
global env
env = TestPipEnvironment(environ)
-
+
return env
env = None
+
class TestFailure(AssertionError):
"""
-
+
An "assertion" failed during testing.
"""
@@ -101,11 +115,12 @@ def _cleanup():
atexit.register(_cleanup)
+
class TestPipResult(object):
def __init__(self, impl, verbose=False):
self._impl = impl
-
+
if verbose:
print self.stdout
if self.stderr:
@@ -114,7 +129,7 @@ class TestPipResult(object):
print '======================='
def __getattr__(self, attr):
- return getattr(self._impl,attr)
+ return getattr(self._impl, attr)
if sys.platform == 'win32':
@property
@@ -124,9 +139,9 @@ class TestPipResult(object):
@property
def stderr(self):
return self._impl.stderr.replace('\r\n', '\n')
-
+
def __str__(self):
- return str(self._impl).replace('\r\n','\n')
+ return str(self._impl).replace('\r\n', '\n')
else:
# Python doesn't automatically forward __str__ through __getattr__
def __str__(self):
@@ -140,49 +155,54 @@ class TestPipResult(object):
egg_link_path = e.site_packages / pkg_name + '.egg-link'
if without_egg_link:
if egg_link_path in self.files_created:
- raise TestFailure, 'unexpected egg link file created: %r\n%s' % (egg_link_path, self)
+ raise TestFailure('unexpected egg link file created: '\
+ '%r\n%s' % (egg_link_path, self))
else:
if not egg_link_path in self.files_created:
- raise TestFailure, 'expected egg link file missing: %r\n%s' % (egg_link_path, self)
+ raise TestFailure('expected egg link file missing: '\
+ '%r\n%s' % (egg_link_path, self))
egg_link_file = self.files_created[egg_link_path]
if not (# FIXME: I don't understand why there's a trailing . here
egg_link_file.bytes.endswith('.')
and egg_link_file.bytes[:-1].strip().endswith(pkg_dir)):
- raise TestFailure, textwrap.dedent(u'''\
+ raise TestFailure(textwrap.dedent(u'''\
Incorrect egg_link file %r
Expected ending: %r
------- Actual contents -------
%s
-------------------------------''' % (
- egg_link_file,
+ egg_link_file,
pkg_dir + u'\n.',
- egg_link_file.bytes))
+ egg_link_file.bytes)))
pth_file = Path.string(e.site_packages / 'easy-install.pth')
if (pth_file in self.files_updated) == without_egg_link:
- raise TestFailure, '%r unexpectedly %supdated by install' % (
- pth_file, (not without_egg_link and 'not ' or ''))
+ raise TestFailure('%r unexpectedly %supdated by install' % (
+ pth_file, (not without_egg_link and 'not ' or '')))
if (pkg_dir in self.files_created) == (curdir in without_files):
- raise TestFailure, textwrap.dedent('''\
+ raise TestFailure(textwrap.dedent('''\
expected package directory %r %sto be created
actually created:
%s
''') % (
- Path.string(pkg_dir),
- (curdir in without_files and 'not ' or ''),
- sorted(self.files_created.keys()))
+ Path.string(pkg_dir),
+ (curdir in without_files and 'not ' or ''),
+ sorted(self.files_created.keys())))
for f in with_files:
if not (pkg_dir/f).normpath in self.files_created:
- raise TestFailure, 'Package directory %r missing expected content %f' % (pkg_dir,f)
+ raise TestFailure('Package directory %r missing '\
+ 'expected content %f' % (pkg_dir, f))
for f in without_files:
if (pkg_dir/f).normpath in self.files_created:
- raise TestFailure, 'Package directory %r has unexpected content %f' % (pkg_dir,f)
+ raise TestFailure('Package directory %r has '\
+ 'unexpected content %f' % (pkg_dir, f))
+
class TestPipEnvironment(TestFileEnvironment):
"""A specialized TestFileEnvironment for testing pip"""
@@ -190,7 +210,7 @@ class TestPipEnvironment(TestFileEnvironment):
#
# Attribute naming convention
# ---------------------------
- #
+ #
# Instances of this class have many attributes representing paths
# in the filesystem. To keep things straight, absolute paths have
# a name of the form xxxx_path and relative paths have a name that
@@ -204,7 +224,7 @@ class TestPipEnvironment(TestFileEnvironment):
#
# Named with a leading dot to reduce the chance of spurious
# results due to being mistaken for the virtualenv package.
- venv = Path('.virtualenv')
+ venv = Path('.virtualenv')
# The root of a directory tree to be used arbitrarily by tests
scratch = Path('scratch')
@@ -214,10 +234,10 @@ class TestPipEnvironment(TestFileEnvironment):
verbose = False
def __init__(self, environ=None):
-
+
self.root_path = Path(tempfile.mkdtemp('-piptest'))
- # We will set up a virtual environment at root_path.
+ # We will set up a virtual environment at root_path.
self.scratch_path = self.root_path / self.scratch
self.venv_path = self.root_path / self.venv
@@ -230,11 +250,10 @@ class TestPipEnvironment(TestFileEnvironment):
environ['PIP_NO_INPUT'] = '1'
environ['PIP_LOG_FILE'] = str(self.root_path/'pip-log.txt')
- super(TestPipEnvironment,self).__init__(
- self.root_path, ignore_hidden=False,
+ super(TestPipEnvironment, self).__init__(
+ self.root_path, ignore_hidden=False,
environ=environ, split_cmd=False, start_clear=False,
- cwd=self.scratch_path, capture_temp=True, assert_no_temp=True
- )
+ cwd=self.scratch_path, capture_temp=True, assert_no_temp=True)
demand_dirs(self.venv_path)
demand_dirs(self.scratch_path)
@@ -246,16 +265,16 @@ class TestPipEnvironment(TestFileEnvironment):
assert self.venv_path == virtualenv_paths[0] # sanity check
- for id,path in zip(('venv', 'lib', 'include', 'bin'), virtualenv_paths):
+ for id, path in zip(('venv', 'lib', 'include', 'bin'), virtualenv_paths):
setattr(self, id+'_path', Path(path))
- setattr(self, id, relpath(self.root_path,path))
-
+ setattr(self, id, relpath(self.root_path, path))
+
assert self.venv == TestPipEnvironment.venv # sanity check
self.site_packages = self.lib/'site-packages'
# put the test-scratch virtualenv's bin dir first on the PATH
- self.environ['PATH'] = Path.pathsep.join( (self.bin_path, self.environ['PATH']) )
+ self.environ['PATH'] = Path.pathsep.join((self.bin_path, self.environ['PATH']))
# test that test-scratch virtualenv creation produced sensible venv python
result = self.run('python', '-c', 'import sys; print sys.executable')
@@ -263,7 +282,7 @@ class TestPipEnvironment(TestFileEnvironment):
if Path(pythonbin).noext != self.bin_path/'python':
raise RuntimeError(
- "Oops! 'python' in our test environment runs %r"
+ "Oops! 'python' in our test environment runs %r"
" rather than expected %r" % (pythonbin, self.bin_path/'python'))
# make sure we have current setuptools to avoid svn incompatibilities
@@ -273,8 +292,8 @@ class TestPipEnvironment(TestFileEnvironment):
# Uninstall whatever version of pip came with the virtualenv.
# Earlier versions of pip were incapable of
# self-uninstallation on Windows, so we use the one we're testing.
- self.run('python', '-c',
- 'import sys;sys.path.insert(0, %r);import pip;sys.exit(pip.main());' % os.path.dirname(here),
+ self.run('python', '-c',
+ 'import sys;sys.path.insert(0, %r);import pip;sys.exit(pip.main());' % os.path.dirname(here),
'uninstall', '-vvv', '-y', 'pip')
# Install this version instead
@@ -284,21 +303,23 @@ class TestPipEnvironment(TestFileEnvironment):
if self.verbose:
print '>> running', args, kw
cwd = kw.pop('cwd', None)
- run_from = kw.pop('run_from',None)
+ run_from = kw.pop('run_from', None)
assert not cwd or not run_from, "Don't use run_from; it's going away"
cwd = Path.string(cwd or run_from or self.cwd)
- assert not isinstance(cwd,Path)
- return TestPipResult( super(TestPipEnvironment,self).run(cwd=cwd,*args,**kw), verbose=self.verbose )
+ assert not isinstance(cwd, Path)
+ return TestPipResult(super(TestPipEnvironment, self).run(cwd=cwd, *args, **kw), verbose=self.verbose)
def __del__(self):
shutil.rmtree(self.root_path, ignore_errors=True)
+
def run_pip(*args, **kw):
return env.run('pip', *args, **kw)
+
def write_file(filename, text, dest=None):
"""Write a file in the dest (default=env.scratch_path)
-
+
"""
env = get_env()
if dest:
@@ -309,14 +330,17 @@ def write_file(filename, text, dest=None):
f.write(text)
f.close()
+
def mkdir(dirname):
os.mkdir(os.path.join(get_env().scratch_path, dirname))
+
def get_env():
if env is None:
reset_env()
return env
+
# FIXME ScriptTest does something similar, but only within a single
# ProcResult; this generalizes it so states can be compared across
# multiple commands. Maybe should be rolled into ScriptTest?
@@ -345,12 +369,13 @@ def diff_states(start, end, ignore=None):
"""
ignore = ignore or []
+
def prefix_match(path, prefix):
- if path == prefix:
+ if path == prefix:
return True
prefix = prefix.rstrip(os.path.sep) + os.path.sep
return path.startswith(prefix)
-
+
start_keys = set([k for k in start.keys()
if not any([prefix_match(k, i) for i in ignore])])
end_keys = set([k for k in end.keys()
@@ -363,10 +388,11 @@ def diff_states(start, end, ignore=None):
updated[k] = end[k]
return dict(deleted=deleted, created=created, updated=updated)
-def assert_all_changes( start_state, end_state, expected_changes ):
+
+def assert_all_changes(start_state, end_state, expected_changes):
"""
Fails if anything changed that isn't listed in the
- expected_changes.
+ expected_changes.
start_state is either a dict mapping paths to
scripttest.[FoundFile|FoundDir] objects or a TestPipResult whose
@@ -383,15 +409,16 @@ def assert_all_changes( start_state, end_state, expected_changes ):
if isinstance(end_state, TestPipResult):
end_files = end_state.files_after
- diff = diff_states( start_files, end_files, ignore=expected_changes )
- if diff.values() != [{},{},{}]:
+ diff = diff_states(start_files, end_files, ignore=expected_changes)
+ if diff.values() != [{}, {}, {}]:
import pprint
- raise TestFailure, 'Unexpected changes:\n' + '\n'.join(
- [k + ': ' + ', '.join(v.keys()) for k,v in diff.items()])
+ raise TestFailure('Unexpected changes:\n' + '\n'.join(
+ [k + ': ' + ', '.join(v.keys()) for k, v in diff.items()]))
# Don't throw away this potentially useful information
return diff
+
if __name__ == '__main__':
sys.stderr.write("Run pip's tests using nosetests. Requires virtualenv, ScriptTest, and nose.\n")
sys.exit(1)
diff --git a/tests/test_proxy.py b/tests/test_proxy.py
index 9790e8aa1..b8e47679b 100644
--- a/tests/test_proxy.py
+++ b/tests/test_proxy.py
@@ -4,7 +4,9 @@ Tests for the proxy support in pip.
TODO shouldn't need to hack sys.path in here.
"""
-import os, sys
+
+import os
+import sys
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
import os
@@ -13,22 +15,25 @@ import getpass
from pip.basecommand import get_proxy
from test_pip import here
+
def new_getpass(prompt, answer='passwd'):
print '%s%s' % (prompt, answer)
return answer
+
def test_correct_pip_version():
"""
Check we are importing pip from the right place.
-
+
"""
base = os.path.dirname(here)
assert pip.__file__.startswith(base), pip.__file__
+
def test_remove_proxy():
"""
Test removing proxy from environ.
-
+
"""
if 'HTTP_PROXY' in os.environ:
del os.environ['HTTP_PROXY']
@@ -40,10 +45,11 @@ def test_remove_proxy():
assert get_proxy('server.com:80') == 'server.com:80'
assert get_proxy('user:passwd@server.com:3128') == 'user:passwd@server.com:3128'
+
def test_get_proxy():
"""
Test get_proxy returns correct proxy info.
-
+
"""
# monkeypatch getpass.getpass, to avoid asking for a password
old_getpass = getpass.getpass
diff --git a/tests/test_requirements.py b/tests/test_requirements.py
index 705262236..3063a7be6 100644
--- a/tests/test_requirements.py
+++ b/tests/test_requirements.py
@@ -3,10 +3,11 @@ import os
import textwrap
from test_pip import reset_env, run_pip, write_file, pyversion
+
def test_requirements_file():
"""
Test installing from a requirements file.
-
+
"""
env = reset_env()
write_file('initools-req.txt', textwrap.dedent("""\
@@ -20,10 +21,11 @@ def test_requirements_file():
assert result.files_created[env.site_packages/'simplejson'].dir
assert result.files_created[env.site_packages/'simplejson-1.7.4-py%s.egg-info' % pyversion].dir
+
def test_multiple_requirements_files():
"""
Test installing from multiple nested requirements files.
-
+
"""
env = reset_env()
write_file('initools-req.txt', textwrap.dedent("""\
diff --git a/tests/test_search.py b/tests/test_search.py
index b04c913a8..f9c80d5d6 100644
--- a/tests/test_search.py
+++ b/tests/test_search.py
@@ -1,5 +1,6 @@
-import os, sys
+import os
+import sys
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
from pip.commands.search import compare_versions, highest_version, transform_hits
@@ -9,7 +10,7 @@ from test_pip import run_pip, reset_env
def test_version_compare():
"""
Test version comparison.
-
+
"""
assert compare_versions('1.0', '1.1') == -1
assert compare_versions('1.1', '1.0') == 1
@@ -17,10 +18,11 @@ def test_version_compare():
assert highest_version(['1.0', '2.0', '0.1']) == '2.0'
assert highest_version(['1.0a1', '1.0']) == '1.0'
+
def test_pypi_xml_transformation():
"""
Test transformation of data structures (pypi xmlrpc to custom list).
-
+
"""
pypi_hits = [{'_pypi_ordering': 100, 'name': 'foo', 'summary': 'foo summary', 'version': '1.0'},
{'_pypi_ordering': 200, 'name': 'foo', 'summary': 'foo summary v2', 'version': '2.0'},
@@ -29,10 +31,11 @@ def test_pypi_xml_transformation():
{'score': 50, 'versions': ['1.0'], 'name': 'bar', 'summary': 'bar summary'}]
assert expected == transform_hits(pypi_hits)
+
def test_search():
"""
End to end test of search command.
-
+
"""
reset_env()
output = run_pip('search', 'pip', expect_error=True)
diff --git a/tests/test_uninstall.py b/tests/test_uninstall.py
index 9c956cc24..160db8d75 100644
--- a/tests/test_uninstall.py
+++ b/tests/test_uninstall.py
@@ -1,15 +1,17 @@
-import textwrap, sys
+import textwrap
+import sys
from os.path import join
from tempfile import mkdtemp
from test_pip import here, reset_env, run_pip, get_env, assert_all_changes, write_file
from path import Path
import pprint
+
def test_simple_uninstall():
"""
Test simple install and uninstall.
-
+
"""
env = reset_env()
result = run_pip('install', 'INITools==0.2', expect_error=True)
@@ -17,14 +19,11 @@ def test_simple_uninstall():
result2 = run_pip('uninstall', 'INITools', '-y', expect_error=True)
assert_all_changes(result, result2, [env.venv/'build', 'cache'])
+
def test_uninstall_with_scripts():
"""
Uninstall an easy_installed package with scripts.
-
- """
- """
- Uninstall an easy_installed package with scripts.
-
+
"""
env = reset_env()
result = env.run('easy_install', 'PyLogo')
@@ -34,11 +33,12 @@ def test_uninstall_with_scripts():
result2 = run_pip('uninstall', 'pylogo', '-y', expect_error=True)
assert_all_changes(result, result2, [env.venv/'build', 'cache'])
+
def test_uninstall_namespace_package():
"""
Uninstall a distribution with a namespace package without clobbering
the namespace and everything in it.
-
+
"""
env = reset_env()
result = run_pip('install', 'pd.requires==0.0.3', expect_error=True)
@@ -47,10 +47,11 @@ def test_uninstall_namespace_package():
assert join(env.site_packages, 'pd') not in result2.files_deleted, sorted(result2.files_deleted.keys())
assert join(env.site_packages, 'pd', 'find') in result2.files_deleted, sorted(result2.files_deleted.keys())
+
def test_uninstall_console_scripts():
"""
Test uninstalling a package with more files (console_script entry points, extra directories).
-
+
"""
env = reset_env()
result = run_pip('install', 'virtualenv', expect_error=True)
@@ -58,10 +59,11 @@ def test_uninstall_console_scripts():
result2 = run_pip('uninstall', 'virtualenv', '-y', expect_error=True)
assert_all_changes(result, result2, [env.venv/'build', 'cache'])
+
def test_uninstall_easy_installed_console_scripts():
"""
Test uninstalling package with console_scripts that is easy_installed.
-
+
"""
env = reset_env()
result = env.run('easy_install', 'virtualenv')
@@ -69,10 +71,11 @@ def test_uninstall_easy_installed_console_scripts():
result2 = run_pip('uninstall', 'virtualenv', '-y')
assert_all_changes(result, result2, [env.venv/'build', 'cache'])
+
def test_uninstall_editable_from_svn():
"""
Test uninstalling an editable installation from svn.
-
+
"""
env = reset_env()
result = run_pip('install', '-e', 'svn+http://svn.colorstudy.com/INITools/trunk#egg=initools-dev')
@@ -81,11 +84,11 @@ def test_uninstall_editable_from_svn():
assert (env.venv/'src'/'initools' in result2.files_after), 'oh noes, pip deleted my sources!'
assert_all_changes(result, result2, [env.venv/'src', env.venv/'build'])
-
+
def test_uninstall_editable_with_source_outside_venv():
"""
Test uninstalling editable install from existing source outside the venv.
-
+
"""
tmpdir = join(mkdtemp(), 'virtualenv')
env = reset_env()
@@ -94,11 +97,12 @@ def test_uninstall_editable_with_source_outside_venv():
assert (join(env.site_packages, 'virtualenv.egg-link') in result2.files_created), result2.files_created.keys()
result3 = run_pip('uninstall', '-y', 'virtualenv', expect_error=True)
assert_all_changes(result, result3, [env.venv/'build'])
-
+
+
def test_uninstall_from_reqs_file():
"""
Test uninstall from a requirements file.
-
+
"""
env = reset_env()
write_file('test-req.txt', textwrap.dedent("""\
@@ -112,7 +116,7 @@ def test_uninstall_from_reqs_file():
-f http://www.example.com
-i http://www.example.com
--extra-index-url http://www.example.com
-
+
-e svn+http://svn.colorstudy.com/INITools/trunk#egg=initools-dev
# and something else to test out:
PyLogo<0.4
diff --git a/tests/test_upgrade.py b/tests/test_upgrade.py
index 0bff6c9ae..33787b97e 100644
--- a/tests/test_upgrade.py
+++ b/tests/test_upgrade.py
@@ -3,6 +3,7 @@ from os.path import join
import textwrap
from test_pip import here, reset_env, run_pip, get_env, assert_all_changes, write_file
+
def test_no_upgrade_unless_requested():
"""
No upgrade if not specifically requested.
@@ -13,6 +14,7 @@ def test_no_upgrade_unless_requested():
result2 = run_pip('install', 'INITools', expect_error=True)
assert not result2.files_created, 'pip install INITools upgraded when it should not have'
+
def test_upgrade_to_specific_version():
"""
It does upgrade to specific version requested.
@@ -23,6 +25,7 @@ def test_upgrade_to_specific_version():
result2 = run_pip('install', 'INITools==0.2', expect_error=True)
assert result2.files_created, 'pip install with specific version did not upgrade'
+
def test_upgrade_if_requested():
"""
And it does upgrade if requested.
@@ -33,6 +36,7 @@ def test_upgrade_if_requested():
result2 = run_pip('install', '--upgrade', 'INITools', expect_error=True)
assert result2.files_created, 'pip install --upgrade did not upgrade'
+
def test_uninstall_before_upgrade():
"""
Automatic uninstall-before-upgrade.
@@ -46,6 +50,7 @@ def test_uninstall_before_upgrade():
result3 = run_pip('uninstall', 'initools', '-y', expect_error=True)
assert_all_changes(result, result3, [env.venv/'build', 'cache'])
+
def test_upgrade_from_reqs_file():
"""
Upgrade from a requirements file.
@@ -67,6 +72,7 @@ def test_upgrade_from_reqs_file():
result3 = run_pip('uninstall', '-r', env.scratch_path/ 'test-req.txt', '-y')
assert_all_changes(result, result3, [env.venv/'build', 'cache', env.scratch/'test-req.txt'])
+
def test_uninstall_rollback():
"""
Test uninstall-rollback (using test package with a setup.py
@@ -79,6 +85,6 @@ def test_uninstall_rollback():
assert env.site_packages / 'broken.py' in result.files_created, result.files_created.keys()
result2 = run_pip('install', '-f', find_links, '--no-index', 'broken==0.2broken', expect_error=True)
assert result2.returncode == 1, str(result2)
- env.run( 'python', '-c', "import broken; print broken.VERSION").stdout
+ env.run('python', '-c', "import broken; print broken.VERSION").stdout
'0.1\n'
assert_all_changes(result.files_after, result2, [env.venv/'build', 'pip-log.txt'])