mirror of https://github.com/pypa/pip
merged changes related to PEP 8 from hltbra's fork
This commit is contained in:
parent
7854b2d266
commit
d06c98dc6f
|
@ -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:]
|
||||
|
|
|
@ -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 = []
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 ...'
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
from pip.commands.zip import ZipCommand
|
||||
|
||||
|
||||
class UnzipCommand(ZipCommand):
|
||||
name = 'unzip'
|
||||
summary = 'Unzip individual packages'
|
||||
|
||||
|
||||
UnzipCommand()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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"""
|
||||
|
|
11
pip/index.py
11
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)
|
||||
|
|
|
@ -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:
|
||||
|
|
20
pip/req.py
20
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."""
|
||||
|
|
|
@ -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:
|
||||
|
|
43
pip/util.py
43
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'<title>[^<]*Revision \d+:', html)
|
||||
and re.search(r'Powered by (?:<a[^>]*?>)?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)
|
||||
|
|
|
@ -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__)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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('<?xml'):
|
||||
|
|
|
@ -6,6 +6,7 @@ import subprocess
|
|||
from pip.exceptions import BadCommand
|
||||
from pip.log import logger
|
||||
|
||||
|
||||
def restart_in_venv(venv, base, site_packages, args):
|
||||
"""
|
||||
Restart this script using the interpreter in the given virtual environment
|
||||
|
|
3
setup.py
3
setup.py
|
@ -32,5 +32,4 @@ setup(name='pip',
|
|||
license='MIT',
|
||||
packages=['pip', 'pip.commands', 'pip.vcs'],
|
||||
entry_points=dict(console_scripts=['pip=pip:main']),
|
||||
zip_safe=False
|
||||
)
|
||||
zip_safe=False)
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
import sys, os
|
||||
from subprocess import check_call, PIPE
|
||||
from path import Path
|
||||
import shutil
|
||||
from tempfile import mkdtemp, gettempdir
|
||||
from test_pip import create_virtualenv
|
||||
import sys
|
||||
import os
|
||||
import shutil
|
||||
|
||||
exe = sys.platform == 'win32' and '.EXE' or ''
|
||||
|
||||
|
||||
def rmtree(path):
|
||||
# From pathutils by Michael Foord: http://www.voidspace.org.uk/python/pathutils.html
|
||||
def onerror(func, path, exc_info):
|
||||
|
@ -32,9 +34,11 @@ def rmtree(path):
|
|||
if Path(path).exists:
|
||||
shutil.rmtree(path, onerror=onerror)
|
||||
|
||||
|
||||
def system(*args):
|
||||
check_call(args, stdout=PIPE, shell=(sys.platform=='win32'))
|
||||
|
||||
|
||||
def call(*args):
|
||||
if not '--distribute' in sys.argv:
|
||||
check_call(args)
|
||||
|
@ -43,9 +47,11 @@ def call(*args):
|
|||
env['PIP_TEST_USE_DISTRIBUTE']='1'
|
||||
check_call(args, env=env)
|
||||
|
||||
|
||||
def assert_in_path(exe):
|
||||
system(exe, '--version')
|
||||
|
||||
|
||||
def clean(root):
|
||||
print >> 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)
|
||||
|
|
296
tests/path.py
296
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)
|
||||
|
|
|
@ -12,6 +12,7 @@ def all_projects():
|
|||
projects = [m.group(1) for m in re.finditer(r'<a.*?>(.+)</a>', 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()
|
||||
|
|
|
@ -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 ('..').
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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/.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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():
|
|||
<BLANKLINE>""")
|
||||
_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')
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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("""\
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'])
|
||||
|
|
Loading…
Reference in New Issue