mirror of https://github.com/pypa/pip
Updated to upstream to make pull request build
This commit is contained in:
commit
b4a3133ef8
|
@ -21,3 +21,5 @@ build/*
|
|||
pip-log.txt
|
||||
pip.log
|
||||
*.~
|
||||
.tox
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ python:
|
|||
- 2.7
|
||||
- 3.1
|
||||
- 3.2
|
||||
- pypy
|
||||
before_install:
|
||||
- sudo apt-get install subversion bzr mercurial
|
||||
- echo -e "[web]\ncacerts = /etc/ssl/certs/ca-certificates.crt" >> ~/.hgrc
|
||||
|
@ -15,5 +16,7 @@ notifications:
|
|||
branches:
|
||||
only:
|
||||
- develop
|
||||
matrix:
|
||||
allow_failures:
|
||||
env:
|
||||
- PIP_USE_MIRRORS=true
|
||||
|
|
|
@ -1,15 +1,20 @@
|
|||
Alex Grönholm
|
||||
Alex Morega
|
||||
Alexandre Conrad
|
||||
Andrey Bulgakov
|
||||
Antti Kaihola
|
||||
Armin Ronacher
|
||||
Aziz Köksal
|
||||
Ben Rosser
|
||||
Brian Rosner
|
||||
Carl Meyer
|
||||
Chris McDonough
|
||||
Christian Oudard
|
||||
Clay McClure
|
||||
Cody Soyland
|
||||
Daniel Holth
|
||||
Dave Abrahams
|
||||
Donald Stufft
|
||||
Francesco
|
||||
Hugo Lopes Tavares
|
||||
Ian Bicking
|
||||
|
@ -36,12 +41,15 @@ Nowell Strite
|
|||
Oliver Tonnhofer
|
||||
Olivier Girardot
|
||||
Patrick Jenkins
|
||||
Paul Moore
|
||||
Paul Nasrat
|
||||
Paul Oswald
|
||||
Paul van der Linden
|
||||
Peter Waller
|
||||
Phil Whelan
|
||||
Piet Delport
|
||||
Qiangning Hong
|
||||
Rafael Caricio
|
||||
Rene Dudfield
|
||||
Ronny Pfannschmidt
|
||||
Rory McCann
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2008-2011 The pip developers (see AUTHORS.txt file)
|
||||
Copyright (c) 2008-2012 The pip developers (see AUTHORS.txt file)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
pip
|
||||
===
|
||||
|
||||
.. image:: https://secure.travis-ci.org/pypa/pip.png?branch=develop
|
||||
:target: http://travis-ci.org/pypa/pip
|
||||
|
||||
For documentation, see http://www.pip-installer.org
|
17
docs/conf.py
17
docs/conf.py
|
@ -11,12 +11,13 @@
|
|||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
import sys, os
|
||||
import os
|
||||
import sys
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#sys.path.append(os.path.abspath('.'))
|
||||
sys.path.insert(0, os.path.abspath(os.pardir))
|
||||
#sys.path.append(os.path.join(os.path.dirname(__file__), '../'))
|
||||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
|
@ -40,15 +41,21 @@ master_doc = 'index'
|
|||
|
||||
# General information about the project.
|
||||
project = 'pip'
|
||||
copyright = '2008-2011, The pip developers'
|
||||
copyright = '2008-2012, The pip developers'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
release = "1.1.post2"
|
||||
version = '.'.join(release.split('.')[:2])
|
||||
try:
|
||||
from pip import __version__
|
||||
# The short X.Y version.
|
||||
version = '.'.join(__version__.split('.')[:2])
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = __version__
|
||||
except ImportError:
|
||||
version = release = 'dev'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
|
|
@ -60,10 +60,10 @@ Before sending us a pull request, please, be sure all tests pass.
|
|||
Supported Python versions
|
||||
-------------------------
|
||||
|
||||
Pip supports Python versions 2.4, 2.5, 2.6, 2.7, 3.1, and 3.2, from a single
|
||||
Pip supports Python versions 2.5, 2.6, 2.7, 3.1, and 3.2, from a single
|
||||
codebase (without use of 2to3 translation). Untested contributions frequently
|
||||
break Python 2.4 or 3.x compatibility. Please run the tests on at least 2.4 and
|
||||
3.2 and report your results when sending a pull request.
|
||||
break Python 3.x compatibility. Please run the tests on at least 3.2 and
|
||||
report your results when sending a pull request.
|
||||
|
||||
Continuous Integration server
|
||||
-----------------------------
|
||||
|
|
|
@ -5,13 +5,49 @@ News
|
|||
Changelog
|
||||
=========
|
||||
|
||||
Next release (1.2) schedule
|
||||
Next release (1.3) schedule
|
||||
---------------------------
|
||||
|
||||
Beta and final releases planned for the second half of 2012.
|
||||
Beta and final releases planned for the end of 2012.
|
||||
|
||||
|
||||
develop (unreleased)
|
||||
-------------------
|
||||
--------------------
|
||||
|
||||
* --user/--upgrade install options now work together; thanks eevee.
|
||||
|
||||
* Added check in ``install --download`` to prevent re-downloading if the target
|
||||
file already exists. Thanks Andrey Bulgakov.
|
||||
|
||||
* Added support for bare paths (including relative paths) as argument to
|
||||
`--find-links`. Thanks Paul Moore for draft patch.
|
||||
|
||||
* Added support for --no-index in requirements files.
|
||||
|
||||
* Added "pip show" command to get information about an installed
|
||||
package. Fixes #131. Thanks Kelsey Hightower and Rafael Caricio.
|
||||
|
||||
1.2.1 (2012-09-06)
|
||||
------------------
|
||||
|
||||
* Fixed a regression introduced in 1.2 about raising an exception when
|
||||
not finding any files to uninstall in the current environment. Thanks for
|
||||
the fix, Marcus Smith.
|
||||
|
||||
1.2 (2012-09-01)
|
||||
----------------
|
||||
|
||||
* **Dropped support for Python 2.4** The minimum supported Python version is
|
||||
now Python 2.5.
|
||||
|
||||
* Fixed issue #605 - pypi mirror support broken on some DNS responses. Thanks
|
||||
philwhin.
|
||||
|
||||
* Fixed issue #355 - pip uninstall removes files it didn't install. Thanks
|
||||
pjdelport.
|
||||
|
||||
* Fixed issues #493, #494, #440, and #573 related to improving support for the
|
||||
user installation scheme. Thanks Marcus Smith.
|
||||
|
||||
* Write failure log to temp file if default location is not writable. Thanks
|
||||
andreigc.
|
||||
|
@ -38,9 +74,6 @@ develop (unreleased)
|
|||
* Fixed issue #504 - allow package URLS to have querystrings. Thanks W.
|
||||
Trevor King.
|
||||
|
||||
* Dropped support for Python 2.4. The minimum supported Python version is
|
||||
now Python 2.5.
|
||||
|
||||
* Fixed issue #58 - pip freeze now falls back to non-editable format rather
|
||||
than blowing up if it can't determine the origin repository of an editable.
|
||||
Thanks Rory McCann.
|
||||
|
@ -57,6 +90,21 @@ develop (unreleased)
|
|||
* Fixed issue #427 - clearer error message on a malformed VCS url. Thanks
|
||||
Thomas Fenzl.
|
||||
|
||||
* Added support for using any of the built in guaranteed algorithms in
|
||||
``hashlib`` as a checksum hash.
|
||||
|
||||
* Fixed issue #321 - Raise an exception if current working directory can't be
|
||||
found or accessed.
|
||||
|
||||
* Fixed issue #82 - Removed special casing of the user directory and use the
|
||||
Python default instead.
|
||||
|
||||
* Fixed #436 - Only warn about version conflicts if there is actually one.
|
||||
This re-enables using ``==dev`` in requirements files.
|
||||
|
||||
* Moved tests to be run on Travis CI: http://travis-ci.org/pypa/pip
|
||||
|
||||
* Added a better help formatter.
|
||||
|
||||
1.1 (2012-02-16)
|
||||
----------------
|
||||
|
|
|
@ -26,8 +26,8 @@ local or remote::
|
|||
.. _setuptools extras: http://peak.telecommunity.com/DevCenter/setuptools#declaring-extras-optional-features-with-their-own-dependencies
|
||||
|
||||
|
||||
Edit mode
|
||||
*********
|
||||
Editable mode
|
||||
*************
|
||||
|
||||
Packages normally_ install under ``site-packages``, but when you're
|
||||
making changes, it makes more sense to run the package straight from the
|
||||
|
@ -106,6 +106,16 @@ within a :ref:`requirements file <requirements-files>` in addition to on the
|
|||
command line directly.
|
||||
|
||||
|
||||
Package Checksum Hashes
|
||||
'''''''''''''''''''''''
|
||||
|
||||
:term:`PyPI` provides a md5 hash of a package by having the link to the
|
||||
package include a #md5=<hash>. pip supports this, as well as any of the
|
||||
guaranteed hashlib algorithms (sha1, sha224, sha384, sha256, sha512, md5).
|
||||
|
||||
The hash fragment is case sensitive (i.e. sha1 not SHA1).
|
||||
|
||||
|
||||
Uninstall packages
|
||||
------------------
|
||||
|
||||
|
@ -137,9 +147,23 @@ packages. With the ``--index`` option you can search in a different
|
|||
repository.
|
||||
|
||||
|
||||
Checking installed package status
|
||||
---------------------------------
|
||||
|
||||
To get info about an installed package, including its location and included
|
||||
files, run ``pip show ProjectName``.
|
||||
|
||||
|
||||
Bundles
|
||||
-------
|
||||
|
||||
.. note::
|
||||
|
||||
Pip bundles are poorly supported, poorly tested, not widely used, and
|
||||
unnecessary (the same goals can be achieved by distributing a directory of
|
||||
sdists and using `--find-links` to reference it). The feature will likely be
|
||||
removed in a future version of pip.
|
||||
|
||||
Another way to distribute a set of libraries is a bundle format (specific to
|
||||
pip). This format is not stable at this time (there simply hasn't been
|
||||
any feedback, nor a great deal of thought). A bundle file contains all the
|
||||
|
|
|
@ -10,8 +10,12 @@ from pip.basecommand import command_dict, load_command, load_all_commands, comma
|
|||
from pip.baseparser import parser
|
||||
from pip.exceptions import InstallationError
|
||||
from pip.log import logger
|
||||
from pip.util import get_installed_distributions
|
||||
from pip.vcs import git, mercurial, subversion, bazaar
|
||||
from pip.util import get_installed_distributions, get_prog
|
||||
from pip.vcs import git, mercurial, subversion, bazaar # noqa
|
||||
|
||||
|
||||
# The version as used in the setup.py and the docs conf.py
|
||||
__version__ = "1.2.1.post1"
|
||||
|
||||
|
||||
def autocomplete():
|
||||
|
@ -26,7 +30,7 @@ def autocomplete():
|
|||
cwords = os.environ['COMP_WORDS'].split()[1:]
|
||||
cword = int(os.environ['COMP_CWORD'])
|
||||
try:
|
||||
current = cwords[cword-1]
|
||||
current = cwords[cword - 1]
|
||||
except IndexError:
|
||||
current = ''
|
||||
load_all_commands()
|
||||
|
@ -59,7 +63,7 @@ def autocomplete():
|
|||
for opt in subcommand.parser.option_list
|
||||
if opt.help != optparse.SUPPRESS_HELP]
|
||||
# filter out previously specified options from available options
|
||||
prev_opts = [x.split('=')[0] for x in cwords[1:cword-1]]
|
||||
prev_opts = [x.split('=')[0] for x in cwords[1:cword - 1]]
|
||||
options = [(x, v) for (x, v) in options if x not in prev_opts]
|
||||
# filter options by current input
|
||||
options = [(k, v) for k, v in options if k.startswith(current)]
|
||||
|
@ -87,7 +91,8 @@ def main(initial_args=None):
|
|||
if options.help and not args:
|
||||
args = ['help']
|
||||
if not args:
|
||||
parser.error('You must give a command (use "pip help" to see a list of commands)')
|
||||
parser.error('You must give a command '
|
||||
'(use "%s help" to see a list of commands)' % get_prog())
|
||||
command = args[0].lower()
|
||||
load_command(command)
|
||||
if command not in command_dict:
|
||||
|
@ -184,7 +189,7 @@ class FrozenRequirement(object):
|
|||
req = self.req
|
||||
if self.editable:
|
||||
req = '-e %s' % req
|
||||
return '\n'.join(list(self.comments)+[str(req)])+'\n'
|
||||
return '\n'.join(list(self.comments) + [str(req)]) + '\n'
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
if __name__ == '__main__':
|
||||
import sys
|
||||
from . import main
|
||||
import sys
|
||||
from .runner import run
|
||||
|
||||
exit = main()
|
||||
if __name__ == '__main__':
|
||||
exit = run()
|
||||
if exit:
|
||||
sys.exit(exit)
|
|
@ -1,10 +1,14 @@
|
|||
"""Stuff that differs in different Python versions"""
|
||||
|
||||
import os
|
||||
import imp
|
||||
import sys
|
||||
import site
|
||||
|
||||
__all__ = ['WindowsError']
|
||||
|
||||
uses_pycache = hasattr(imp,'cache_from_source')
|
||||
|
||||
try:
|
||||
WindowsError = WindowsError
|
||||
except NameError:
|
||||
|
@ -12,6 +16,7 @@ except NameError:
|
|||
"""this exception should never be raised"""
|
||||
WindowsError = NeverUsedException
|
||||
|
||||
|
||||
console_encoding = sys.__stdout__.encoding
|
||||
|
||||
if sys.version_info >= (3,):
|
||||
|
@ -97,3 +102,11 @@ def product(*args, **kwds):
|
|||
result = [x+[y] for x in result for y in pool]
|
||||
for prod in result:
|
||||
yield tuple(prod)
|
||||
|
||||
def home_lib(home):
|
||||
"""Return the lib dir under the 'home' installation scheme"""
|
||||
if hasattr(sys, 'pypy_version_info'):
|
||||
lib = 'site-packages'
|
||||
else:
|
||||
lib = os.path.join('lib', 'python')
|
||||
return os.path.join(home, lib)
|
||||
|
|
|
@ -4,6 +4,7 @@ import os
|
|||
from pkgutil import walk_packages
|
||||
import socket
|
||||
import sys
|
||||
import tempfile
|
||||
import traceback
|
||||
import time
|
||||
|
||||
|
@ -15,6 +16,7 @@ from pip.exceptions import (BadCommand, InstallationError, UninstallationError,
|
|||
CommandError)
|
||||
from pip.backwardcompat import StringIO
|
||||
from pip.status_codes import SUCCESS, ERROR, UNKNOWN_ERROR, VIRTUALENV_NOT_FOUND
|
||||
from pip.util import get_prog
|
||||
|
||||
|
||||
__all__ = ['command_dict', 'Command', 'load_all_commands',
|
||||
|
@ -35,7 +37,7 @@ class Command(object):
|
|||
assert self.name
|
||||
self.parser = ConfigOptionParser(
|
||||
usage=self.usage,
|
||||
prog='%s %s' % (sys.argv[0], self.name),
|
||||
prog='%s %s' % (get_prog(), self.name),
|
||||
version=parser.version,
|
||||
formatter=UpdatingDefaultsHelpFormatter(),
|
||||
name=self.name)
|
||||
|
@ -144,7 +146,7 @@ class Command(object):
|
|||
temp = tempfile.NamedTemporaryFile(delete=False)
|
||||
log_fn = temp.name
|
||||
log_fp = open_logfile(log_fn, 'w')
|
||||
logger.fatal('Storing complete log in %s' % log_fn)
|
||||
logger.fatal('Storing complete log in %s' % log_fn)
|
||||
log_fp.write(text)
|
||||
log_fp.close()
|
||||
return exit
|
||||
|
|
|
@ -7,22 +7,17 @@ import os
|
|||
from distutils.util import strtobool
|
||||
from pip.backwardcompat import ConfigParser, string_types
|
||||
from pip.locations import default_config_file, default_log_file
|
||||
from pip.util import get_terminal_size, get_prog
|
||||
|
||||
|
||||
class PipPrettyHelpFormatter(optparse.IndentedHelpFormatter):
|
||||
class PrettyHelpFormatter(optparse.IndentedHelpFormatter):
|
||||
"""A prettier/less verbose help formatter for optparse."""
|
||||
|
||||
def __init__(self, *args, **kw):
|
||||
kw['max_help_position'] = 23
|
||||
kw['indent_increment'] = 1
|
||||
|
||||
# do as argparse does
|
||||
try:
|
||||
kw['width'] = int(os.environ['COLUMNS']) - 2
|
||||
except:
|
||||
kw['width'] = 78
|
||||
|
||||
optparse.IndentedHelpFormatter.__init__(self, *args, **kw)
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs['max_help_position'] = 30
|
||||
kwargs['indent_increment'] = 1
|
||||
kwargs['width'] = get_terminal_size()[0] - 2
|
||||
optparse.IndentedHelpFormatter.__init__(self, *args, **kwargs)
|
||||
|
||||
def format_option_strings(self, option):
|
||||
return self._format_option_strings(option, ' <%s>', ', ')
|
||||
|
@ -35,31 +30,34 @@ class PipPrettyHelpFormatter(optparse.IndentedHelpFormatter):
|
|||
:param mvarfmt: metavar format string - evaluated as mvarfmt % metavar
|
||||
:param optsep: separator
|
||||
"""
|
||||
|
||||
opts = []
|
||||
|
||||
if option._short_opts: opts.append(option._short_opts[0])
|
||||
if option._long_opts: opts.append(option._long_opts[0])
|
||||
if len(opts) > 1: opts.insert(1, optsep)
|
||||
if option._short_opts:
|
||||
opts.append(option._short_opts[0])
|
||||
if option._long_opts:
|
||||
opts.append(option._long_opts[0])
|
||||
if len(opts) > 1:
|
||||
opts.insert(1, optsep)
|
||||
|
||||
if option.takes_value():
|
||||
metavar = option.metavar or option.dest.lower()
|
||||
opts.append(mvarfmt % metavar)
|
||||
opts.append(mvarfmt % metavar.upper())
|
||||
|
||||
return ''.join(opts)
|
||||
|
||||
def format_heading(self, heading):
|
||||
if heading == 'Options': return ''
|
||||
if heading == 'Options':
|
||||
return ''
|
||||
return heading + ':\n'
|
||||
|
||||
def format_usage(self, usage):
|
||||
# ensure there is only one newline between usage and the first heading
|
||||
# if there is no description
|
||||
|
||||
"""
|
||||
ensure there is only one newline between usage and the first heading
|
||||
if there is no description
|
||||
"""
|
||||
msg = 'Usage: %s' % usage
|
||||
if self.parser.description:
|
||||
msg += '\n'
|
||||
|
||||
return msg
|
||||
|
||||
def format_description(self, description):
|
||||
|
@ -77,7 +75,7 @@ class PipPrettyHelpFormatter(optparse.IndentedHelpFormatter):
|
|||
return ''
|
||||
|
||||
|
||||
class UpdatingDefaultsHelpFormatter(PipPrettyHelpFormatter):
|
||||
class UpdatingDefaultsHelpFormatter(PrettyHelpFormatter):
|
||||
"""Custom help formatter for use in ConfigOptionParser that updates
|
||||
the defaults before expanding them, allowing them to show up correctly
|
||||
in the help listing"""
|
||||
|
@ -148,7 +146,7 @@ class ConfigOptionParser(optparse.OptionParser):
|
|||
for key, val in items:
|
||||
key = key.replace('_', '-')
|
||||
if not key.startswith('--'):
|
||||
key = '--%s' % key # only prefer long opts
|
||||
key = '--%s' % key # only prefer long opts
|
||||
normalized[key] = val
|
||||
return normalized
|
||||
|
||||
|
@ -171,7 +169,7 @@ class ConfigOptionParser(optparse.OptionParser):
|
|||
# Old, pre-Optik 1.5 behaviour.
|
||||
return optparse.Values(self.defaults)
|
||||
|
||||
defaults = self.update_defaults(self.defaults.copy()) # ours
|
||||
defaults = self.update_defaults(self.defaults.copy()) # ours
|
||||
for option in self._get_all_options():
|
||||
default = defaults.get(option.dest)
|
||||
if isinstance(default, string_types):
|
||||
|
@ -179,20 +177,27 @@ class ConfigOptionParser(optparse.OptionParser):
|
|||
defaults[option.dest] = option.check_value(opt_str, default)
|
||||
return optparse.Values(defaults)
|
||||
|
||||
def error(self, msg):
|
||||
self.print_usage(sys.stderr)
|
||||
self.exit(2, "%s\n" % msg)
|
||||
|
||||
|
||||
try:
|
||||
pip_dist = pkg_resources.get_distribution('pip')
|
||||
version = '%s from %s (python %s)' % (
|
||||
pip_dist, pip_dist.location, sys.version[:3])
|
||||
except pkg_resources.DistributionNotFound:
|
||||
# when running pip.py without installing
|
||||
version=None
|
||||
version = None
|
||||
|
||||
|
||||
parser = ConfigOptionParser(
|
||||
usage='%prog COMMAND [OPTIONS]',
|
||||
version=version,
|
||||
add_help_option=False,
|
||||
formatter=UpdatingDefaultsHelpFormatter(),
|
||||
name='global')
|
||||
name='global',
|
||||
prog=get_prog())
|
||||
|
||||
parser.add_option(
|
||||
'-h', '--help',
|
||||
|
@ -253,7 +258,7 @@ parser.add_option(
|
|||
default='',
|
||||
help="Specify a proxy in the form user:passwd@proxy.server:port. "
|
||||
"Note that the user:password@ is optional and required only if you "
|
||||
"are behind an authenticated proxy. If you provide "
|
||||
"are behind an authenticated proxy. If you provide "
|
||||
"user@proxy.server:port then you will be prompted for a password.")
|
||||
parser.add_option(
|
||||
'--timeout', '--default-timeout',
|
||||
|
@ -285,10 +290,10 @@ parser.add_option(
|
|||
choices=['s', 'i', 'w', 'b'],
|
||||
default=[],
|
||||
action='append',
|
||||
help="Default action when a path already exists."
|
||||
"Use this option more then one time to specify "
|
||||
help="Default action when a path already exists. "
|
||||
"Use this option more than one time to specify "
|
||||
"another action if a certain option is not "
|
||||
"available, choices: "
|
||||
"available. Choices: "
|
||||
"(s)witch, (i)gnore, (w)ipe, (b)ackup")
|
||||
|
||||
parser.disable_interspersed_args()
|
||||
|
|
|
@ -9,6 +9,7 @@ from pip.locations import build_prefix, src_prefix, virtualenv_no_global
|
|||
from pip.basecommand import Command
|
||||
from pip.index import PackageFinder
|
||||
from pip.exceptions import InstallationError, CommandError
|
||||
from pip.backwardcompat import home_lib
|
||||
|
||||
|
||||
class InstallCommand(Command):
|
||||
|
@ -36,7 +37,7 @@ class InstallCommand(Command):
|
|||
action='append',
|
||||
default=[],
|
||||
metavar='FILENAME',
|
||||
help='Install all the packages listed in the given requirements file. '
|
||||
help='Install all the packages listed in the given requirements file. '
|
||||
'This option can be used multiple times.')
|
||||
self.parser.add_option(
|
||||
'-f', '--find-links',
|
||||
|
@ -148,15 +149,15 @@ class InstallCommand(Command):
|
|||
dest='install_options',
|
||||
action='append',
|
||||
help="Extra arguments to be supplied to the setup.py install "
|
||||
"command (use like --install-option=\"--install-scripts=/usr/local/bin\"). "
|
||||
"Use multiple --install-option options to pass multiple options to setup.py install. "
|
||||
"command (use like --install-option=\"--install-scripts=/usr/local/bin\"). "
|
||||
"Use multiple --install-option options to pass multiple options to setup.py install. "
|
||||
"If you are using an option with a directory path, be sure to use absolute path.")
|
||||
|
||||
self.parser.add_option(
|
||||
'--global-option',
|
||||
dest='global_options',
|
||||
action='append',
|
||||
help="Extra global options to be supplied to the setup.py"
|
||||
help="Extra global options to be supplied to the setup.py "
|
||||
"call before the install command")
|
||||
|
||||
self.parser.add_option(
|
||||
|
@ -276,7 +277,7 @@ class InstallCommand(Command):
|
|||
if options.target_dir:
|
||||
if not os.path.exists(options.target_dir):
|
||||
os.makedirs(options.target_dir)
|
||||
lib_dir = os.path.join(temp_target_dir, "lib/python/")
|
||||
lib_dir = home_lib(temp_target_dir)
|
||||
for item in os.listdir(lib_dir):
|
||||
shutil.move(
|
||||
os.path.join(lib_dir, item),
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
import os
|
||||
import pkg_resources
|
||||
from pip.basecommand import Command
|
||||
from pip.log import logger
|
||||
|
||||
|
||||
class ShowCommand(Command):
|
||||
name = 'show'
|
||||
usage = '%prog QUERY'
|
||||
summary = 'Output installed distributions (exact versions, files) to stdout'
|
||||
|
||||
def __init__(self):
|
||||
super(ShowCommand, self).__init__()
|
||||
self.parser.add_option(
|
||||
'-f', '--files',
|
||||
dest='files',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='Show the full list of installed files for each package')
|
||||
|
||||
def run(self, options, args):
|
||||
if not args:
|
||||
logger.warn('ERROR: Please provide a project name or names.')
|
||||
return
|
||||
query = args
|
||||
|
||||
results = search_packages_info(query)
|
||||
print_results(results, options.files)
|
||||
|
||||
|
||||
def search_packages_info(query):
|
||||
"""
|
||||
Gather details from installed distributions. Print distribution name,
|
||||
version, location, and installed files. Installed files requires a
|
||||
pip generated 'installed-files.txt' in the distributions '.egg-info'
|
||||
directory.
|
||||
"""
|
||||
installed_packages = dict(
|
||||
[(p.project_name.lower(), p) for p in pkg_resources.working_set])
|
||||
for name in query:
|
||||
normalized_name = name.lower()
|
||||
if normalized_name in installed_packages:
|
||||
dist = installed_packages[normalized_name]
|
||||
package = {
|
||||
'name': dist.project_name,
|
||||
'version': dist.version,
|
||||
'location': dist.location,
|
||||
'requires': [dep.project_name for dep in dist.requires()],
|
||||
}
|
||||
filelist = os.path.join(
|
||||
dist.location,
|
||||
dist.egg_name() + '.egg-info',
|
||||
'installed-files.txt')
|
||||
if os.path.isfile(filelist):
|
||||
package['files'] = filelist
|
||||
yield package
|
||||
|
||||
|
||||
def print_results(distributions, list_all_files):
|
||||
"""
|
||||
Print the informations from installed distributions found.
|
||||
"""
|
||||
for dist in distributions:
|
||||
logger.notify("---")
|
||||
logger.notify("Name: %s" % dist['name'])
|
||||
logger.notify("Version: %s" % dist['version'])
|
||||
logger.notify("Location: %s" % dist['location'])
|
||||
logger.notify("Requires: %s" % ', '.join(dist['requires']))
|
||||
if list_all_files:
|
||||
logger.notify("Files:")
|
||||
if 'files' in dist:
|
||||
for line in open(dist['files']):
|
||||
logger.notify(" %s" % line.strip())
|
||||
else:
|
||||
logger.notify("Cannot locate installed-files.txt")
|
||||
|
||||
|
||||
ShowCommand()
|
|
@ -231,7 +231,7 @@ class ZipCommand(Command):
|
|||
|
||||
def add_filename_to_pth(self, filename):
|
||||
path = os.path.dirname(filename)
|
||||
dest = os.path.join(path, filename + '.pth')
|
||||
dest = filename + '.pth'
|
||||
if path not in self.paths():
|
||||
logger.warn('Adding .pth file %s, but it is not on sys.path' % display_path(dest))
|
||||
if not self.simulate:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import cgi
|
||||
import getpass
|
||||
from hashlib import md5
|
||||
import hashlib
|
||||
import mimetypes
|
||||
import os
|
||||
import re
|
||||
|
@ -322,16 +322,24 @@ def is_file_url(link):
|
|||
return link.url.lower().startswith('file:')
|
||||
|
||||
|
||||
def _check_md5(download_hash, link):
|
||||
download_hash = download_hash.hexdigest()
|
||||
if download_hash != link.md5_hash:
|
||||
logger.fatal("MD5 hash of the package %s (%s) doesn't match the expected hash %s!"
|
||||
% (link, download_hash, link.md5_hash))
|
||||
raise InstallationError('Bad MD5 hash for package %s' % link)
|
||||
def _check_hash(download_hash, link):
|
||||
if download_hash.digest_size != hashlib.new(link.hash_name).digest_size:
|
||||
logger.fatal("Hash digest size of the package %d (%s) doesn't match the expected hash name %s!"
|
||||
% (download_hash.digest_size, link, link.hash_name))
|
||||
raise InstallationError('Hash name mismatch for package %s' % link)
|
||||
if download_hash.hexdigest() != link.hash:
|
||||
logger.fatal("Hash of the package %s (%s) doesn't match the expected hash %s!"
|
||||
% (link, download_hash, link.hash))
|
||||
raise InstallationError('Bad %s hash for package %s' % (link.hash_name, link))
|
||||
|
||||
|
||||
def _get_md5_from_file(target_file, link):
|
||||
download_hash = md5()
|
||||
def _get_hash_from_file(target_file, link):
|
||||
try:
|
||||
download_hash = hashlib.new(link.hash_name)
|
||||
except (ValueError, TypeError):
|
||||
logger.warn("Unsupported hash name %s for package %s" % (link.hash_name, link))
|
||||
return None
|
||||
|
||||
fp = open(target_file, 'rb')
|
||||
while True:
|
||||
chunk = fp.read(4096)
|
||||
|
@ -345,8 +353,11 @@ def _get_md5_from_file(target_file, link):
|
|||
def _download_url(resp, link, temp_location):
|
||||
fp = open(temp_location, 'wb')
|
||||
download_hash = None
|
||||
if link.md5_hash:
|
||||
download_hash = md5()
|
||||
if link.hash and link.hash_name:
|
||||
try:
|
||||
download_hash = hashlib.new(link.hash_name)
|
||||
except ValueError:
|
||||
logger.warn("Unsupported hash name %s for package %s" % (link.hash_name, link))
|
||||
try:
|
||||
total_length = int(resp.info()['content-length'])
|
||||
except (ValueError, KeyError, TypeError):
|
||||
|
@ -363,7 +374,7 @@ def _download_url(resp, link, temp_location):
|
|||
logger.start_progress('Downloading %s (unknown size): ' % show_url)
|
||||
else:
|
||||
logger.notify('Downloading %s' % show_url)
|
||||
logger.debug('Downloading from URL %s' % link)
|
||||
logger.info('Downloading from URL %s' % link)
|
||||
|
||||
while True:
|
||||
chunk = resp.read(4096)
|
||||
|
@ -375,7 +386,7 @@ def _download_url(resp, link, temp_location):
|
|||
logger.show_progress('%s' % format_size(downloaded))
|
||||
else:
|
||||
logger.show_progress('%3i%% %s' % (100*downloaded/total_length, format_size(downloaded)))
|
||||
if link.md5_hash:
|
||||
if download_hash is not None:
|
||||
download_hash.update(chunk)
|
||||
fp.write(chunk)
|
||||
fp.close()
|
||||
|
@ -418,16 +429,29 @@ def unpack_http_url(link, location, download_cache, download_dir=None):
|
|||
urllib.quote(target_url, ''))
|
||||
if not os.path.isdir(download_cache):
|
||||
create_download_cache_folder(download_cache)
|
||||
|
||||
already_downloaded = None
|
||||
if download_dir:
|
||||
already_downloaded = os.path.join(download_dir, link.filename)
|
||||
if not os.path.exists(already_downloaded):
|
||||
already_downloaded = None
|
||||
|
||||
if (target_file
|
||||
and os.path.exists(target_file)
|
||||
and os.path.exists(target_file + '.content-type')):
|
||||
fp = open(target_file+'.content-type')
|
||||
content_type = fp.read().strip()
|
||||
fp.close()
|
||||
if link.md5_hash:
|
||||
download_hash = _get_md5_from_file(target_file, link)
|
||||
if link.hash and link.hash_name:
|
||||
download_hash = _get_hash_from_file(target_file, link)
|
||||
temp_location = target_file
|
||||
logger.notify('Using download cache from %s' % target_file)
|
||||
elif already_downloaded:
|
||||
temp_location = already_downloaded
|
||||
content_type = mimetypes.guess_type(already_downloaded)
|
||||
if link.hash:
|
||||
download_hash = _get_hash_from_file(temp_location, link)
|
||||
logger.notify('File was already downloaded %s' % already_downloaded)
|
||||
else:
|
||||
resp = _get_response_from_url(target_url, link)
|
||||
content_type = resp.info()['content-type']
|
||||
|
@ -450,14 +474,14 @@ def unpack_http_url(link, location, download_cache, download_dir=None):
|
|||
filename += ext
|
||||
temp_location = os.path.join(temp_dir, filename)
|
||||
download_hash = _download_url(resp, link, temp_location)
|
||||
if link.md5_hash:
|
||||
_check_md5(download_hash, link)
|
||||
if download_dir:
|
||||
if link.hash and link.hash_name:
|
||||
_check_hash(download_hash, link)
|
||||
if download_dir and not already_downloaded:
|
||||
_copy_file(temp_location, download_dir, content_type, link)
|
||||
unpack_file(temp_location, location, content_type, link)
|
||||
if target_file and target_file != temp_location:
|
||||
cache_download(target_file, temp_location, content_type)
|
||||
if target_file is None:
|
||||
if target_file is None and not already_downloaded:
|
||||
os.unlink(temp_location)
|
||||
os.rmdir(temp_dir)
|
||||
|
||||
|
|
122
pip/index.py
122
pip/index.py
|
@ -20,7 +20,7 @@ from pip.util import Inf
|
|||
from pip.util import normalize_name, splitext
|
||||
from pip.exceptions import DistributionNotFound, BestVersionAlreadyInstalled
|
||||
from pip.backwardcompat import (WindowsError, BytesIO,
|
||||
Queue, httplib, urlparse,
|
||||
Queue, urlparse,
|
||||
URLError, HTTPError, u,
|
||||
product, url2pathname)
|
||||
from pip.backwardcompat import Empty as QueueEmpty
|
||||
|
@ -29,7 +29,7 @@ from pip.download import urlopen, path_to_url2, url_to_path, geturl, Urllib2Head
|
|||
__all__ = ['PackageFinder']
|
||||
|
||||
|
||||
DEFAULT_MIRROR_URL = "last.pypi.python.org"
|
||||
DEFAULT_MIRROR_HOSTNAME = "last.pypi.python.org"
|
||||
|
||||
|
||||
class PackageFinder(object):
|
||||
|
@ -60,8 +60,7 @@ class PackageFinder(object):
|
|||
## FIXME: also, we should track comes_from (i.e., use Link)
|
||||
self.dependency_links.extend(links)
|
||||
|
||||
@staticmethod
|
||||
def _sort_locations(locations):
|
||||
def _sort_locations(self, locations):
|
||||
"""
|
||||
Sort locations into "files" (archives) and "urls", and return
|
||||
a pair of lists (files,urls)
|
||||
|
@ -69,8 +68,7 @@ class PackageFinder(object):
|
|||
files = []
|
||||
urls = []
|
||||
|
||||
# puts the url for the given file path into the appropriate
|
||||
# list
|
||||
# puts the url for the given file path into the appropriate list
|
||||
def sort_path(path):
|
||||
url = path_to_url2(path)
|
||||
if mimetypes.guess_type(url, strict=False)[0] == 'text/html':
|
||||
|
@ -79,34 +77,30 @@ class PackageFinder(object):
|
|||
files.append(url)
|
||||
|
||||
for url in locations:
|
||||
if url.startswith('file:'):
|
||||
path = url_to_path(url)
|
||||
if os.path.isdir(path):
|
||||
|
||||
is_local_path = os.path.exists(url)
|
||||
is_file_url = url.startswith('file:')
|
||||
is_find_link = url in self.find_links
|
||||
|
||||
if is_local_path or is_file_url:
|
||||
if is_local_path:
|
||||
path = url
|
||||
else:
|
||||
path = url_to_path(url)
|
||||
if is_find_link and os.path.isdir(path):
|
||||
path = os.path.realpath(path)
|
||||
for item in os.listdir(path):
|
||||
sort_path(os.path.join(path, item))
|
||||
elif is_file_url and os.path.isdir(path):
|
||||
urls.append(url)
|
||||
elif os.path.isfile(path):
|
||||
sort_path(path)
|
||||
else:
|
||||
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:
|
||||
main_index_url = None
|
||||
if self.index_urls:
|
||||
# Check that we have the url_name correctly spelled:
|
||||
main_index_url = Link(posixpath.join(self.index_urls[0], url_name))
|
||||
# This will also cache the page, so it's okay that we get it again later:
|
||||
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
|
||||
|
||||
# Combine index URLs with mirror URLs here to allow
|
||||
# adding more index URLs from requirements files
|
||||
all_index_urls = self.index_urls + self.mirror_urls
|
||||
|
||||
def mkurl_pypi_url(url):
|
||||
loc = posixpath.join(url, url_name)
|
||||
# For maximum compatibility with easy_install, ensure the path
|
||||
|
@ -116,6 +110,22 @@ class PackageFinder(object):
|
|||
if not loc.endswith('/'):
|
||||
loc = loc + '/'
|
||||
return loc
|
||||
|
||||
url_name = req.url_name
|
||||
# Only check main index if index URL is given:
|
||||
main_index_url = None
|
||||
if self.index_urls:
|
||||
# Check that we have the url_name correctly spelled:
|
||||
main_index_url = Link(mkurl_pypi_url(self.index_urls[0]))
|
||||
# This will also cache the page, so it's okay that we get it again later:
|
||||
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
|
||||
|
||||
# Combine index URLs with mirror URLs here to allow
|
||||
# adding more index URLs from requirements files
|
||||
all_index_urls = self.index_urls + self.mirror_urls
|
||||
|
||||
if url_name is not None:
|
||||
locations = [
|
||||
mkurl_pypi_url(url)
|
||||
|
@ -156,7 +166,7 @@ class PackageFinder(object):
|
|||
logger.fatal('Could not find any downloads that satisfy the requirement %s' % req)
|
||||
raise DistributionNotFound('No distributions at all found for %s' % req)
|
||||
if req.satisfied_by is not None:
|
||||
found_versions.append((req.satisfied_by.parsed_version, Inf, req.satisfied_by.version))
|
||||
found_versions.append((req.satisfied_by.parsed_version, InfLink, req.satisfied_by.version))
|
||||
if file_versions:
|
||||
file_versions.sort(reverse=True)
|
||||
logger.info('Local files found: %s' % ', '.join([url_to_path(link.url) for parsed, link, version in file_versions]))
|
||||
|
@ -168,31 +178,31 @@ class PackageFinder(object):
|
|||
logger.info("Ignoring link %s, version %s doesn't match %s"
|
||||
% (link, version, ','.join([''.join(s) for s in req.req.specs])))
|
||||
continue
|
||||
applicable_versions.append((link, version))
|
||||
applicable_versions = sorted(applicable_versions, key=lambda v: pkg_resources.parse_version(v[1]), reverse=True)
|
||||
existing_applicable = bool([link for link, version in applicable_versions if link is Inf])
|
||||
applicable_versions.append((parsed_version, link, version))
|
||||
applicable_versions = sorted(applicable_versions, reverse=True)
|
||||
existing_applicable = bool([link for parsed_version, link, version in applicable_versions if link is InfLink])
|
||||
if not upgrade and existing_applicable:
|
||||
if applicable_versions[0][1] is Inf:
|
||||
if applicable_versions[0][1] is InfLink:
|
||||
logger.info('Existing installed version (%s) is most up-to-date and satisfies requirement'
|
||||
% req.satisfied_by.version)
|
||||
raise BestVersionAlreadyInstalled
|
||||
else:
|
||||
logger.info('Existing installed version (%s) satisfies requirement (most up-to-date version is %s)'
|
||||
% (req.satisfied_by.version, applicable_versions[0][1]))
|
||||
% (req.satisfied_by.version, applicable_versions[0][2]))
|
||||
return None
|
||||
if not applicable_versions:
|
||||
logger.fatal('Could not find a version that satisfies the requirement %s (from versions: %s)'
|
||||
% (req, ', '.join([version for parsed_version, link, version in found_versions])))
|
||||
raise DistributionNotFound('No distributions matching the version for %s' % req)
|
||||
if applicable_versions[0][0] is Inf:
|
||||
if applicable_versions[0][1] is InfLink:
|
||||
# We have an existing version, and its the best version
|
||||
logger.info('Installed version (%s) is most up-to-date (past versions: %s)'
|
||||
% (req.satisfied_by.version, ', '.join([version for link, version in applicable_versions[1:]]) or 'none'))
|
||||
% (req.satisfied_by.version, ', '.join([version for parsed_version, link, version in applicable_versions[1:]]) or 'none'))
|
||||
raise BestVersionAlreadyInstalled
|
||||
if len(applicable_versions) > 1:
|
||||
logger.info('Using version %s (newest of versions: %s)' %
|
||||
(applicable_versions[0][1], ', '.join([version for link, version in applicable_versions])))
|
||||
return applicable_versions[0][0]
|
||||
(applicable_versions[0][2], ', '.join([version for parsed_version, link, version in applicable_versions])))
|
||||
return applicable_versions[0][1]
|
||||
|
||||
|
||||
def _find_url_name(self, index_url, url_name, req):
|
||||
"""Finds the true URL name of a package, when the given name isn't quite correct.
|
||||
|
@ -586,7 +596,7 @@ class Link(object):
|
|||
if self.comes_from:
|
||||
return '%s (from %s)' % (self.url, self.comes_from)
|
||||
else:
|
||||
return self.url
|
||||
return str(self.url)
|
||||
|
||||
def __repr__(self):
|
||||
return '<Link %s>' % self
|
||||
|
@ -594,6 +604,21 @@ class Link(object):
|
|||
def __eq__(self, other):
|
||||
return self.url == other.url
|
||||
|
||||
def __ne__(self, other):
|
||||
return self.url != other.url
|
||||
|
||||
def __lt__(self, other):
|
||||
return self.url < other.url
|
||||
|
||||
def __le__(self, other):
|
||||
return self.url <= other.url
|
||||
|
||||
def __gt__(self, other):
|
||||
return self.url > other.url
|
||||
|
||||
def __ge__(self, other):
|
||||
return self.url >= other.url
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.url)
|
||||
|
||||
|
@ -629,11 +654,18 @@ class Link(object):
|
|||
return None
|
||||
return match.group(1)
|
||||
|
||||
_md5_re = re.compile(r'md5=([a-f0-9]+)')
|
||||
_hash_re = re.compile(r'(sha1|sha224|sha384|sha256|sha512|md5)=([a-f0-9]+)')
|
||||
|
||||
@property
|
||||
def md5_hash(self):
|
||||
match = self._md5_re.search(self.url)
|
||||
def hash(self):
|
||||
match = self._hash_re.search(self.url)
|
||||
if match:
|
||||
return match.group(2)
|
||||
return None
|
||||
|
||||
@property
|
||||
def hash_name(self):
|
||||
match = self._hash_re.search(self.url)
|
||||
if match:
|
||||
return match.group(1)
|
||||
return None
|
||||
|
@ -642,6 +674,9 @@ class Link(object):
|
|||
def show_url(self):
|
||||
return posixpath.basename(self.url.split('#', 1)[0].split('?', 1)[0])
|
||||
|
||||
#An "Infinite Link" that compares greater than other links
|
||||
InfLink = Link(Inf)
|
||||
|
||||
|
||||
def get_requirement_from_url(url):
|
||||
"""Get a requirement from the URL, if possible. This looks for #egg
|
||||
|
@ -680,14 +715,17 @@ def get_mirrors(hostname=None):
|
|||
Originally written for the distutils2 project by Alexis Metaireau.
|
||||
"""
|
||||
if hostname is None:
|
||||
hostname = DEFAULT_MIRROR_URL
|
||||
hostname = DEFAULT_MIRROR_HOSTNAME
|
||||
|
||||
# return the last mirror registered on PyPI.
|
||||
last_mirror_hostname = None
|
||||
try:
|
||||
hostname = socket.gethostbyname_ex(hostname)[0]
|
||||
last_mirror_hostname = socket.gethostbyname_ex(hostname)[0]
|
||||
except socket.gaierror:
|
||||
return []
|
||||
end_letter = hostname.split(".", 1)
|
||||
if not last_mirror_hostname or last_mirror_hostname == DEFAULT_MIRROR_HOSTNAME:
|
||||
last_mirror_hostname = "z.pypi.python.org"
|
||||
end_letter = last_mirror_hostname.split(".", 1)
|
||||
|
||||
# determine the list from the last one.
|
||||
return ["%s.%s" % (s, end_letter[1]) for s in string_range(end_letter[0])]
|
||||
|
|
|
@ -15,26 +15,26 @@ def running_under_virtualenv():
|
|||
"""
|
||||
return hasattr(sys, 'real_prefix')
|
||||
|
||||
|
||||
def virtualenv_no_global():
|
||||
"""
|
||||
Return True if in a venv and no system site packages.
|
||||
"""
|
||||
#this mirrors the logic in virtualenv.py for locating the no-global-site-packages.txt file
|
||||
site_mod_dir = os.path.dirname(os.path.abspath(site.__file__))
|
||||
no_global_file = os.path.join(site_mod_dir,'no-global-site-packages.txt')
|
||||
no_global_file = os.path.join(site_mod_dir, 'no-global-site-packages.txt')
|
||||
if running_under_virtualenv() and os.path.isfile(no_global_file):
|
||||
return True
|
||||
|
||||
|
||||
if running_under_virtualenv():
|
||||
## FIXME: is build/ a good name?
|
||||
build_prefix = os.path.join(sys.prefix, 'build')
|
||||
src_prefix = os.path.join(sys.prefix, 'src')
|
||||
else:
|
||||
# Use tempfile to create a temporary folder for build
|
||||
# Note: we are NOT using mkdtemp so we can have a consistent build dir
|
||||
build_prefix = os.path.join(tempfile.gettempdir(), 'pip-build')
|
||||
|
||||
|
||||
## FIXME: keep src in cwd for now (it is not a temporary folder)
|
||||
try:
|
||||
src_prefix = os.path.join(os.getcwd(), 'src')
|
||||
|
|
73
pip/req.py
73
pip/req.py
|
@ -1,5 +1,6 @@
|
|||
from email.parser import FeedParser
|
||||
import os
|
||||
import imp
|
||||
import pkg_resources
|
||||
import re
|
||||
import sys
|
||||
|
@ -16,10 +17,10 @@ from pip.log import logger
|
|||
from pip.util import display_path, rmtree
|
||||
from pip.util import ask, ask_path_exists, backup_dir
|
||||
from pip.util import is_installable_dir, is_local, dist_is_local, dist_in_usersite
|
||||
from pip.util import renames, normalize_path, egg_link_path
|
||||
from pip.util import renames, normalize_path, egg_link_path, dist_in_site_packages
|
||||
from pip.util import make_path_relative
|
||||
from pip.util import call_subprocess
|
||||
from pip.backwardcompat import (urlparse, urllib,
|
||||
from pip.backwardcompat import (urlparse, urllib, uses_pycache,
|
||||
ConfigParser, string_types, HTTPError,
|
||||
get_python_version, b)
|
||||
from pip.index import Link
|
||||
|
@ -94,7 +95,7 @@ class InstallRequirement(object):
|
|||
link = Link(name)
|
||||
elif os.path.isdir(path) and (os.path.sep in name or name.startswith('.')):
|
||||
if not is_installable_dir(path):
|
||||
raise InstallationError("Directory %r is not installable. File 'setup.py' not found.", name)
|
||||
raise InstallationError("Directory %r is not installable. File 'setup.py' not found." % name)
|
||||
link = Link(path_to_url(name))
|
||||
elif is_archive_file(path):
|
||||
if not os.path.isfile(path):
|
||||
|
@ -245,14 +246,16 @@ class InstallRequirement(object):
|
|||
_run_setup_py = """
|
||||
__file__ = __SETUP_PY__
|
||||
from setuptools.command import egg_info
|
||||
import pkg_resources
|
||||
import os
|
||||
def replacement_run(self):
|
||||
self.mkpath(self.egg_info)
|
||||
installer = self.distribution.fetch_build_egg
|
||||
for ep in egg_info.iter_entry_points('egg_info.writers'):
|
||||
for ep in pkg_resources.iter_entry_points('egg_info.writers'):
|
||||
# require=False is the change we're making:
|
||||
writer = ep.load(require=False)
|
||||
if writer:
|
||||
writer(self, ep.name, egg_info.os.path.join(self.egg_info,ep.name))
|
||||
writer(self, ep.name, os.path.join(self.egg_info,ep.name))
|
||||
self.find_sources()
|
||||
egg_info.egg_info.run = replacement_run
|
||||
exec(compile(open(__file__).read().replace('\\r\\n', '\\n'), __file__, 'exec'))
|
||||
|
@ -365,18 +368,9 @@ exec(compile(open(__file__).read().replace('\\r\\n', '\\n'), __file__, 'exec'))
|
|||
|
||||
def assert_source_matches_version(self):
|
||||
assert self.source_dir
|
||||
if self.comes_from is None:
|
||||
# We don't check the versions of things explicitly installed.
|
||||
# This makes, e.g., "pip Package==dev" possible
|
||||
return
|
||||
version = self.installed_version
|
||||
if version not in self.req:
|
||||
logger.fatal(
|
||||
'Source in %s has the version %s, which does not match the requirement %s'
|
||||
% (display_path(self.source_dir), version, self))
|
||||
raise InstallationError(
|
||||
'Source in %s has version %s that conflicts with %s'
|
||||
% (display_path(self.source_dir), version, self))
|
||||
logger.warn('Requested %s, but installing version %s' % (self, self.installed_version))
|
||||
else:
|
||||
logger.debug('Source in %s has version %s, which satisfies requirement %s'
|
||||
% (display_path(self.source_dir), version, self))
|
||||
|
@ -446,7 +440,9 @@ exec(compile(open(__file__).read().replace('\\r\\n', '\\n'), __file__, 'exec'))
|
|||
for installed_file in dist.get_metadata('installed-files.txt').splitlines():
|
||||
path = os.path.normpath(os.path.join(egg_info_path, installed_file))
|
||||
paths_to_remove.add(path)
|
||||
if dist.has_metadata('top_level.txt'):
|
||||
#FIXME: need a test for this elif block
|
||||
#occurs with --single-version-externally-managed/--record outside of pip
|
||||
elif dist.has_metadata('top_level.txt'):
|
||||
if dist.has_metadata('namespace_packages.txt'):
|
||||
namespaces = dist.get_metadata('namespace_packages.txt')
|
||||
else:
|
||||
|
@ -466,7 +462,7 @@ exec(compile(open(__file__).read().replace('\\r\\n', '\\n'), __file__, 'exec'))
|
|||
'easy-install.pth')
|
||||
paths_to_remove.add_pth(easy_install_pth, './' + easy_install_egg)
|
||||
|
||||
elif os.path.isfile(develop_egg_link):
|
||||
elif develop_egg_link:
|
||||
# develop egg
|
||||
fh = open(develop_egg_link, 'r')
|
||||
link_pointer = os.path.normcase(fh.readline().strip())
|
||||
|
@ -685,6 +681,9 @@ exec(compile(open(__file__).read().replace('\\r\\n', '\\n'), __file__, 'exec'))
|
|||
if self.use_user_site:
|
||||
if dist_in_usersite(existing_dist):
|
||||
self.conflicts_with = existing_dist
|
||||
elif running_under_virtualenv() and dist_in_site_packages(existing_dist):
|
||||
raise InstallationError("Will not install to the user site because it will lack sys.path precedence to %s in %s"
|
||||
%(existing_dist.project_name, existing_dist.location))
|
||||
else:
|
||||
self.conflicts_with = existing_dist
|
||||
return True
|
||||
|
@ -890,7 +889,7 @@ class RequirementSet(object):
|
|||
req.commit_uninstall()
|
||||
|
||||
def locate_files(self):
|
||||
## FIXME: duplicates code from install_files; relevant code should
|
||||
## FIXME: duplicates code from prepare_files; relevant code should
|
||||
## probably be factored out into a separate method
|
||||
unnamed = list(self.unnamed_requirements)
|
||||
reqs = list(self.requirements.values())
|
||||
|
@ -904,7 +903,9 @@ class RequirementSet(object):
|
|||
req_to_install.check_if_exists()
|
||||
if req_to_install.satisfied_by:
|
||||
if self.upgrade:
|
||||
req_to_install.conflicts_with = req_to_install.satisfied_by
|
||||
#don't uninstall conflict if user install and and conflict is not user install
|
||||
if not (self.use_user_site and not dist_in_usersite(req_to_install.satisfied_by)):
|
||||
req_to_install.conflicts_with = req_to_install.satisfied_by
|
||||
req_to_install.satisfied_by = None
|
||||
else:
|
||||
install_needed = False
|
||||
|
@ -956,7 +957,9 @@ class RequirementSet(object):
|
|||
req_to_install.url = url.url
|
||||
|
||||
if not best_installed:
|
||||
req_to_install.conflicts_with = req_to_install.satisfied_by
|
||||
#don't uninstall conflict if user install and conflict is not user install
|
||||
if not (self.use_user_site and not dist_in_usersite(req_to_install.satisfied_by)):
|
||||
req_to_install.conflicts_with = req_to_install.satisfied_by
|
||||
req_to_install.satisfied_by = None
|
||||
else:
|
||||
install = False
|
||||
|
@ -998,7 +1001,9 @@ class RequirementSet(object):
|
|||
##occurs when the script attempts to unpack the
|
||||
##build directory
|
||||
|
||||
# NB: This call can result in the creation of a temporary build directory
|
||||
location = req_to_install.build_location(self.build_dir, not self.is_download)
|
||||
|
||||
## FIXME: is the existance of the checkout good enough to use it? I don't think so.
|
||||
unpack = True
|
||||
url = None
|
||||
|
@ -1053,7 +1058,9 @@ class RequirementSet(object):
|
|||
req_to_install.check_if_exists()
|
||||
if req_to_install.satisfied_by:
|
||||
if self.upgrade or self.ignore_installed:
|
||||
req_to_install.conflicts_with = req_to_install.satisfied_by
|
||||
#don't uninstall conflict if user install and and conflict is not user install
|
||||
if not (self.use_user_site and not dist_in_usersite(req_to_install.satisfied_by)):
|
||||
req_to_install.conflicts_with = req_to_install.satisfied_by
|
||||
req_to_install.satisfied_by = None
|
||||
else:
|
||||
install = False
|
||||
|
@ -1079,7 +1086,7 @@ class RequirementSet(object):
|
|||
self.add_requirement(subreq)
|
||||
if req_to_install.name not in self.requirements:
|
||||
self.requirements[req_to_install.name] = req_to_install
|
||||
if self.is_download:
|
||||
if self.is_download or req_to_install._temp_build_dir is not None:
|
||||
self.reqs_to_cleanup.append(req_to_install)
|
||||
else:
|
||||
self.reqs_to_cleanup.append(req_to_install)
|
||||
|
@ -1133,7 +1140,8 @@ class RequirementSet(object):
|
|||
loc = location
|
||||
if is_vcs_url(link):
|
||||
return unpack_vcs_link(link, loc, only_download)
|
||||
elif is_file_url(link):
|
||||
# a local file:// index could have links with hashes
|
||||
elif not link.hash and is_file_url(link):
|
||||
return unpack_file_url(link, loc)
|
||||
else:
|
||||
if self.download_cache:
|
||||
|
@ -1269,9 +1277,10 @@ _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
|
||||
skip_regex = options.skip_requirements_regex if options else None
|
||||
if skip_regex:
|
||||
skip_match = re.compile(skip_regex)
|
||||
reqs_file_dir = os.path.dirname(os.path.abspath(filename))
|
||||
filename, content = get_file_content(filename, comes_from=comes_from)
|
||||
for line_number, line in enumerate(content.splitlines()):
|
||||
line_number += 1
|
||||
|
@ -1303,6 +1312,10 @@ 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:
|
||||
# support a find-links local path relative to a requirements file
|
||||
relative_to_reqs_file = os.path.join(reqs_file_dir, line)
|
||||
if os.path.exists(relative_to_reqs_file):
|
||||
line = relative_to_reqs_file
|
||||
if finder:
|
||||
finder.find_links.append(line)
|
||||
elif line.startswith('-i') or line.startswith('--index-url'):
|
||||
|
@ -1316,6 +1329,8 @@ def parse_requirements(filename, finder=None, comes_from=None, options=None):
|
|||
line = line[len('--extra-index-url'):].strip().lstrip('=')
|
||||
if finder:
|
||||
finder.index_urls.append(line)
|
||||
elif line.startswith('--no-index'):
|
||||
finder.index_urls = []
|
||||
else:
|
||||
comes_from = '-r %s (line %s)' % (filename, line_number)
|
||||
if line.startswith('-e') or line.startswith('--editable'):
|
||||
|
@ -1347,7 +1362,7 @@ def parse_editable(editable_req, default_vcs=None):
|
|||
|
||||
if os.path.isdir(url_no_extras):
|
||||
if not os.path.exists(os.path.join(url_no_extras, 'setup.py')):
|
||||
raise InstallationError("Directory %r is not installable. File 'setup.py' not found.", url_no_extras)
|
||||
raise InstallationError("Directory %r is not installable. File 'setup.py' not found." % url_no_extras)
|
||||
# Treating it as code that has already been checked out
|
||||
url_no_extras = path_to_url(url_no_extras)
|
||||
|
||||
|
@ -1428,6 +1443,11 @@ class UninstallPathSet(object):
|
|||
else:
|
||||
self._refuse.add(path)
|
||||
|
||||
# __pycache__ files can show up after 'installed-files.txt' is created, due to imports
|
||||
if os.path.splitext(path)[1] == '.py' and uses_pycache:
|
||||
self.add(imp.cache_from_source(path))
|
||||
|
||||
|
||||
def add_pth(self, pth_file, entry):
|
||||
pth_file = normalize_path(pth_file)
|
||||
if self._permitted(pth_file):
|
||||
|
@ -1459,6 +1479,9 @@ class UninstallPathSet(object):
|
|||
``auto_confirm`` is True)."""
|
||||
if not self._can_uninstall():
|
||||
return
|
||||
if not self.paths:
|
||||
logger.notify("Can't uninstall '%s'. No files were found to uninstall." % self.dist.project_name)
|
||||
return
|
||||
logger.notify('Uninstalling %s:' % self.dist.project_name)
|
||||
logger.indent += 2
|
||||
paths = sorted(self.compact(self.paths))
|
||||
|
|
82
pip/util.py
82
pip/util.py
|
@ -10,7 +10,7 @@ import tarfile
|
|||
import subprocess
|
||||
from pip.exceptions import InstallationError, BadCommand
|
||||
from pip.backwardcompat import WindowsError, string_types, raw_input, console_to_str, user_site
|
||||
from pip.locations import site_packages, running_under_virtualenv
|
||||
from pip.locations import site_packages, running_under_virtualenv, virtualenv_no_global
|
||||
from pip.log import logger
|
||||
|
||||
__all__ = ['rmtree', 'display_path', 'backup_dir',
|
||||
|
@ -20,11 +20,20 @@ __all__ = ['rmtree', 'display_path', 'backup_dir',
|
|||
'is_svn_page', 'file_contents',
|
||||
'split_leading_dir', 'has_leading_dir',
|
||||
'make_path_relative', 'normalize_path',
|
||||
'renames', 'get_terminal_size',
|
||||
'renames', 'get_terminal_size', 'get_prog',
|
||||
'unzip_file', 'untar_file', 'create_download_cache_folder',
|
||||
'cache_download', 'unpack_file', 'call_subprocess']
|
||||
|
||||
|
||||
def get_prog():
|
||||
try:
|
||||
if os.path.basename(sys.argv[0]) in ('__main__.py', '-c'):
|
||||
return "%s -m pip" % sys.executable
|
||||
except (AttributeError, TypeError, IndexError):
|
||||
pass
|
||||
return 'pip'
|
||||
|
||||
|
||||
def rmtree(dir, ignore_errors=False):
|
||||
shutil.rmtree(dir, ignore_errors=ignore_errors,
|
||||
onerror=rmtree_errorhandler)
|
||||
|
@ -78,7 +87,7 @@ def find_command(cmd, paths=None, pathext=None):
|
|||
# check if there are funny path extensions for executables, e.g. Windows
|
||||
if pathext is None:
|
||||
pathext = get_pathext()
|
||||
pathext = [ext for ext in pathext.lower().split(os.pathsep)]
|
||||
pathext = [ext for ext in pathext.lower().split(os.pathsep) if len(ext)]
|
||||
# don't use extensions if the command ends with one of them
|
||||
if os.path.splitext(cmd)[1].lower() in pathext:
|
||||
pathext = ['']
|
||||
|
@ -127,10 +136,27 @@ def ask(message, options):
|
|||
|
||||
class _Inf(object):
|
||||
"""I am bigger than everything!"""
|
||||
def __cmp__(self, a):
|
||||
if self is a:
|
||||
return 0
|
||||
return 1
|
||||
|
||||
def __eq__(self, other):
|
||||
if self is other:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self.__eq__(other)
|
||||
|
||||
def __lt__(self, other):
|
||||
return False
|
||||
|
||||
def __le__(self, other):
|
||||
return False
|
||||
|
||||
def __gt__(self, other):
|
||||
return True
|
||||
|
||||
def __ge__(self, other):
|
||||
return True
|
||||
|
||||
def __repr__(self):
|
||||
return 'Inf'
|
||||
|
@ -303,6 +329,12 @@ def dist_in_usersite(dist):
|
|||
else:
|
||||
return False
|
||||
|
||||
def dist_in_site_packages(dist):
|
||||
"""
|
||||
Return True if given Distribution is installed in distutils.sysconfig.get_python_lib().
|
||||
"""
|
||||
return normalize_path(dist_location(dist)).startswith(normalize_path(site_packages))
|
||||
|
||||
|
||||
def get_installed_distributions(local_only=True, skip=('setuptools', 'pip', 'python')):
|
||||
"""
|
||||
|
@ -325,16 +357,36 @@ def get_installed_distributions(local_only=True, skip=('setuptools', 'pip', 'pyt
|
|||
|
||||
def egg_link_path(dist):
|
||||
"""
|
||||
Return the path where we'd expect to find a .egg-link file for
|
||||
this distribution. (There doesn't seem to be any metadata in the
|
||||
Distribution object for a develop egg that points back to its
|
||||
.egg-link and easy-install.pth files).
|
||||
Return the path for the .egg-link file if it exists, otherwise, None.
|
||||
|
||||
This won't find a globally-installed develop egg if we're in a
|
||||
virtualenv.
|
||||
There's 3 scenarios:
|
||||
1) not in a virtualenv
|
||||
try to find in site.USER_SITE, then site_packages
|
||||
2) in a no-global virtualenv
|
||||
try to find in site_packages
|
||||
3) in a yes-global virtualenv
|
||||
try to find in site_packages, then site.USER_SITE (don't look in global location)
|
||||
|
||||
For #1 and #3, there could be odd cases, where there's an egg-link in 2 locations.
|
||||
This method will just return the first one found.
|
||||
"""
|
||||
return os.path.join(site_packages, dist.project_name) + '.egg-link'
|
||||
sites = []
|
||||
if running_under_virtualenv():
|
||||
if virtualenv_no_global():
|
||||
sites.append(site_packages)
|
||||
else:
|
||||
sites.append(site_packages)
|
||||
if user_site:
|
||||
sites.append(user_site)
|
||||
else:
|
||||
if user_site:
|
||||
sites.append(user_site)
|
||||
sites.append(site_packages)
|
||||
|
||||
for site in sites:
|
||||
egglink = os.path.join(site, dist.project_name) + '.egg-link'
|
||||
if os.path.isfile(egglink):
|
||||
return egglink
|
||||
|
||||
|
||||
def dist_location(dist):
|
||||
|
@ -346,7 +398,7 @@ def dist_location(dist):
|
|||
|
||||
"""
|
||||
egg_link = egg_link_path(dist)
|
||||
if os.path.exists(egg_link):
|
||||
if egg_link:
|
||||
return egg_link
|
||||
return dist.location
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ class VcsSupport(object):
|
|||
def __init__(self):
|
||||
# Register more schemes with urlparse for various version control systems
|
||||
urlparse.uses_netloc.extend(self.schemes)
|
||||
# Python 3.3 doesn't have uses_fragment
|
||||
# Python >= 2.7.4, 3.3 doesn't have uses_fragment
|
||||
if getattr(urlparse, 'uses_fragment', None):
|
||||
urlparse.uses_fragment.extend(self.schemes)
|
||||
super(VcsSupport, self).__init__()
|
||||
|
|
|
@ -19,8 +19,11 @@ class Bazaar(VersionControl):
|
|||
|
||||
def __init__(self, url=None, *args, **kwargs):
|
||||
super(Bazaar, self).__init__(url, *args, **kwargs)
|
||||
urlparse.non_hierarchical.extend(['lp'])
|
||||
urlparse.uses_fragment.extend(['lp'])
|
||||
# Python >= 2.7.4, 3.3 doesn't have uses_fragment or non_hierarchical
|
||||
# Register lp but do not expose as a scheme to support bzr+lp.
|
||||
if getattr(urlparse, 'uses_fragment', None):
|
||||
urlparse.uses_fragment.extend(['lp'])
|
||||
urlparse.non_hierarchical.extend(['lp'])
|
||||
|
||||
def parse_vcs_bundle_file(self, content):
|
||||
url = rev = None
|
||||
|
|
|
@ -214,8 +214,7 @@ class Git(VersionControl):
|
|||
def update_submodules(self, location):
|
||||
if not os.path.exists(os.path.join(location, '.gitmodules')):
|
||||
return
|
||||
call_subprocess([self.cmd, 'submodule', 'init', '-q'], cwd=location)
|
||||
call_subprocess([self.cmd, 'submodule', 'update', '--recursive', '-q'],
|
||||
call_subprocess([self.cmd, 'submodule', 'update', '--init', '--recursive', '-q'],
|
||||
cwd=location)
|
||||
|
||||
vcs.register(Git)
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
[nosetests]
|
||||
where=tests
|
||||
|
||||
[aliases]
|
||||
dev = develop easy_install pip[testing]
|
||||
|
|
46
setup.py
46
setup.py
|
@ -1,32 +1,39 @@
|
|||
import sys
|
||||
import codecs
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from setuptools import setup
|
||||
|
||||
# If you change this version, change it also in docs/conf.py
|
||||
version = "1.1.post2"
|
||||
|
||||
doc_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)), "docs")
|
||||
index_filename = os.path.join(doc_dir, "index.txt")
|
||||
news_filename = os.path.join(doc_dir, "news.txt")
|
||||
def read(*parts):
|
||||
return codecs.open(os.path.join(os.path.abspath(os.path.dirname(__file__)), *parts), 'r').read()
|
||||
|
||||
|
||||
def find_version(*file_paths):
|
||||
version_file = read(*file_paths)
|
||||
version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]",
|
||||
version_file, re.M)
|
||||
if version_match:
|
||||
return version_match.group(1)
|
||||
raise RuntimeError("Unable to find version string.")
|
||||
|
||||
long_description = """
|
||||
|
||||
The main website for pip is `www.pip-installer.org
|
||||
<http://www.pip-installer.org>`_. You can also install
|
||||
<http://www.pip-installer.org>`_. You can also install
|
||||
the `in-development version <https://github.com/pypa/pip/tarball/develop#egg=pip-dev>`_
|
||||
of pip with ``easy_install pip==dev``.
|
||||
|
||||
"""
|
||||
f = open(index_filename)
|
||||
# remove the toctree from sphinx index, as it breaks long_description
|
||||
parts = f.read().split("split here", 2)
|
||||
long_description = parts[0] + long_description + parts[2]
|
||||
f.close()
|
||||
f = open(news_filename)
|
||||
long_description += "\n\n" + f.read()
|
||||
f.close()
|
||||
parts = read("docs", "index.txt").split("split here", 2)
|
||||
long_description = (parts[0] + long_description + parts[2] +
|
||||
"\n\n" + read("docs", "news.txt"))
|
||||
|
||||
tests_require = ['nose', 'virtualenv>=1.7', 'scripttest>=1.1.1', 'mock']
|
||||
|
||||
setup(name="pip",
|
||||
version=version,
|
||||
version=find_version('pip', '__init__.py'),
|
||||
description="pip installs packages. Python packages. An easy_install replacement",
|
||||
long_description=long_description,
|
||||
classifiers=[
|
||||
|
@ -35,7 +42,6 @@ setup(name="pip",
|
|||
'License :: OSI Approved :: MIT License',
|
||||
'Topic :: Software Development :: Build Tools',
|
||||
'Programming Language :: Python :: 2',
|
||||
'Programming Language :: Python :: 2.4',
|
||||
'Programming Language :: Python :: 2.5',
|
||||
'Programming Language :: Python :: 2.6',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
|
@ -51,5 +57,9 @@ setup(name="pip",
|
|||
packages=['pip', 'pip.commands', 'pip.vcs'],
|
||||
entry_points=dict(console_scripts=['pip=pip:main', 'pip-%s=pip:main' % sys.version[:3]]),
|
||||
test_suite='nose.collector',
|
||||
tests_require=['nose', 'virtualenv>=1.7', 'scripttest>=1.1.1', 'mock'],
|
||||
zip_safe=False)
|
||||
tests_require=tests_require,
|
||||
zip_safe=False,
|
||||
extras_require = {
|
||||
'testing':tests_require,
|
||||
},
|
||||
)
|
||||
|
|
|
@ -44,19 +44,22 @@ def _create_test_package_with_submodule(env):
|
|||
packages=find_packages(),
|
||||
)
|
||||
'''), version_pkg_path)
|
||||
env.run('git', 'init', cwd=version_pkg_path)
|
||||
env.run('git', 'add', '.', cwd=version_pkg_path)
|
||||
env.run('git', 'init', cwd=version_pkg_path, expect_error=True)
|
||||
env.run('git', 'add', '.', cwd=version_pkg_path, expect_error=True)
|
||||
env.run('git', 'commit', '-q',
|
||||
'--author', 'Pip <python-virtualenv@googlegroups.com>',
|
||||
'-am', 'initial version', cwd=version_pkg_path)
|
||||
'-am', 'initial version', cwd=version_pkg_path,
|
||||
expect_error=True)
|
||||
|
||||
|
||||
submodule_path = _create_test_package_submodule(env)
|
||||
|
||||
env.run('git', 'submodule', 'add', submodule_path, 'testpkg/static', cwd=version_pkg_path)
|
||||
env.run('git', 'submodule', 'add', submodule_path, 'testpkg/static', cwd=version_pkg_path,
|
||||
expect_error=True)
|
||||
env.run('git', 'commit', '-q',
|
||||
'--author', 'Pip <python-virtualenv@googlegroups.com>',
|
||||
'-am', 'initial version w submodule', cwd=version_pkg_path)
|
||||
'-am', 'initial version w submodule', cwd=version_pkg_path,
|
||||
expect_error=True)
|
||||
|
||||
|
||||
return version_pkg_path, submodule_path
|
||||
|
|
Binary file not shown.
|
@ -1,3 +0,0 @@
|
|||
<html><head><title>Links for FSPkg</title></head><body><h1>Links for FSPkg</h1><a href="./FSPkg-0.1dev.tar.gz#md5=ba6e46bed32c5b6d20f974d7d889bdb2">FSPkg-0.1dev.tar.gz</a><br/>
|
||||
<a href="file://../../packages/FSPkg">Source</a><br/>
|
||||
</body></html>
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
Details on Test Indexes
|
||||
=======================
|
||||
|
||||
empty_with_pkg
|
||||
--------------
|
||||
empty index, but there's a package in the dir
|
||||
|
||||
in dex
|
||||
------
|
||||
for testing url quoting with indexes
|
||||
|
||||
simple
|
||||
------
|
||||
contains index page for "simple" pkg
|
Binary file not shown.
|
@ -0,0 +1,5 @@
|
|||
<html>
|
||||
<body>
|
||||
<a href="../../../packages/simple-1.0.tar.gz#md5=4bdf78ebb7911f215c1972cf71b378f0">simple-1.0.tar.gz</a>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,5 @@
|
|||
<html>
|
||||
<body>
|
||||
<a href="../../../packages/simple-1.0.tar.gz#md5=4bdf78ebb7911f215c1972cf71b378f0">simple-1.0.tar.gz</a>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,17 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from setuptools import setup
|
||||
from setuptools.command import egg_info as orig_egg_info
|
||||
|
||||
class egg_info (orig_egg_info.egg_info):
|
||||
def run(self):
|
||||
orig_egg_info.egg_info.run(self)
|
||||
|
||||
|
||||
setup(
|
||||
name = "hackedegginfo",
|
||||
version = '0.0.0',
|
||||
cmdclass = {'egg_info':egg_info },
|
||||
zip_safe = False,
|
||||
)
|
||||
|
|
@ -2,12 +2,12 @@ import os
|
|||
from setuptools import setup, find_packages
|
||||
|
||||
HERE = os.path.dirname(__file__)
|
||||
INDEX = os.path.join(HERE, '..', '..', 'in dex', 'FSPkg')
|
||||
INDEX = "file://" + os.path.join(HERE, '..', '..', 'indexes', 'simple', 'simple')
|
||||
|
||||
setup(
|
||||
name='LocalExtras',
|
||||
version='0.0.1',
|
||||
packages=find_packages(),
|
||||
extras_require={ 'bar': ['FSPkg'] },
|
||||
dependency_links=['file://' + INDEX]
|
||||
extras_require={ 'bar': ['simple'] },
|
||||
dependency_links=[INDEX]
|
||||
)
|
||||
|
|
|
@ -1,6 +1,70 @@
|
|||
This package exists for testing uninstall-rollback.
|
||||
|
||||
Details on Test Packages
|
||||
========================
|
||||
|
||||
broken-0.1.tar.gz
|
||||
-----------------
|
||||
This package exists for testing uninstall-rollback.
|
||||
|
||||
broken-0.2broken.tar.gz
|
||||
-----------------------
|
||||
Version 0.2broken has a setup.py crafted to fail on install (and only on
|
||||
install). If any earlier step would fail (i.e. egg-info-generation), the
|
||||
already-installed version would never be uninstalled, so uninstall-rollback
|
||||
would not come into play.
|
||||
|
||||
BrokenEmitsUTF8
|
||||
---------------
|
||||
for generating unicode error in py3.x
|
||||
|
||||
duplicate-1.0.tar.gz
|
||||
--------------------
|
||||
for testing finding dupes across multiple find-links
|
||||
|
||||
FSPkg
|
||||
-----
|
||||
for installing from the file system
|
||||
|
||||
gmpy-1.15.tar.gz
|
||||
----------------
|
||||
hash testing (altough this pkg isn't needed explicitly)
|
||||
|
||||
gmpy2-2.0.tar.gz
|
||||
----------------
|
||||
for testing finder logic when name *contains* the name of the package specified
|
||||
|
||||
HackedEggInfo
|
||||
-------------
|
||||
has it's own egg_info class
|
||||
|
||||
LineEndings
|
||||
-----------
|
||||
contains DOS line endings
|
||||
|
||||
LocalExtras
|
||||
-----------
|
||||
has an extra in a local file:// dependency link
|
||||
|
||||
parent/child-0.1.tar.gz
|
||||
-----------------------
|
||||
The parent-0.1.tar.gz and child-0.1.tar.gz packages are used by
|
||||
test_uninstall:test_uninstall_overlapping_package.
|
||||
|
||||
paxpkg.tar.bz2
|
||||
--------------
|
||||
tar with pax headers
|
||||
|
||||
pkgwithmpkg-1.0.tar.gz; pkgwithmpkg-1.0-py2.7-macosx10.7.mpkg.zip
|
||||
-----------------------------------------------------------------
|
||||
used for osx test case (tests.test_finder:test_no_mpkg)
|
||||
|
||||
simple-[123].0.tar.gz
|
||||
---------------------
|
||||
contains "simple" package; good for basic testing and version logic.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -5,7 +5,6 @@ import textwrap
|
|||
import sys
|
||||
from os.path import abspath, join, curdir, pardir
|
||||
|
||||
from nose import SkipTest
|
||||
from nose.tools import assert_raises
|
||||
from mock import patch
|
||||
|
||||
|
@ -376,6 +375,16 @@ def test_install_with_pax_header():
|
|||
run_pip('install', 'paxpkg.tar.bz2', cwd=run_from)
|
||||
|
||||
|
||||
def test_install_with_hacked_egg_info():
|
||||
"""
|
||||
test installing a package which defines its own egg_info class
|
||||
"""
|
||||
reset_env()
|
||||
run_from = abspath(join(here, 'packages', 'HackedEggInfo'))
|
||||
result = run_pip('install', '.', cwd=run_from)
|
||||
assert 'Successfully installed hackedegginfo\n' in result.stdout
|
||||
|
||||
|
||||
def test_install_using_install_option_and_editable():
|
||||
"""
|
||||
Test installing a tool using -e and --install-option
|
||||
|
|
|
@ -17,6 +17,7 @@ def test_cleanup_after_install_from_pypi():
|
|||
src = env.scratch_path/"src"
|
||||
assert not exists(build), "build/ dir still exists: %s" % build
|
||||
assert not exists(src), "unexpected src/ dir exists: %s" % src
|
||||
env.assert_no_temp()
|
||||
|
||||
|
||||
def test_cleanup_after_install_editable_from_hg():
|
||||
|
@ -34,6 +35,7 @@ def test_cleanup_after_install_editable_from_hg():
|
|||
src = env.venv_path/'src'
|
||||
assert not exists(build), "build/ dir still exists: %s" % build
|
||||
assert exists(src), "expected src/ dir doesn't exist: %s" % src
|
||||
env.assert_no_temp()
|
||||
|
||||
|
||||
def test_cleanup_after_install_from_local_directory():
|
||||
|
@ -48,6 +50,7 @@ def test_cleanup_after_install_from_local_directory():
|
|||
src = env.venv_path/'src'
|
||||
assert not exists(build), "unexpected build/ dir exists: %s" % build
|
||||
assert not exists(src), "unexpected src/ dir exist: %s" % src
|
||||
env.assert_no_temp()
|
||||
|
||||
|
||||
def test_cleanup_after_create_bundle():
|
||||
|
@ -79,6 +82,7 @@ def test_cleanup_after_create_bundle():
|
|||
src_bundle = env.scratch_path/"src-bundle"
|
||||
assert not exists(build_bundle), "build-bundle/ dir still exists: %s" % build_bundle
|
||||
assert not exists(src_bundle), "src-bundle/ dir still exists: %s" % src_bundle
|
||||
env.assert_no_temp()
|
||||
|
||||
# Make sure previously created src/ from editable still exists
|
||||
assert exists(src), "expected src dir doesn't exist: %s" % src
|
||||
|
@ -96,6 +100,25 @@ def test_no_install_and_download_should_not_leave_build_dir():
|
|||
assert not os.path.exists(env.venv_path/'/build'), "build/ dir should be deleted"
|
||||
|
||||
|
||||
def test_cleanup_req_satisifed_no_name():
|
||||
"""
|
||||
Test cleanup when req is already satisfied, and req has no 'name'
|
||||
"""
|
||||
#this test confirms Issue #420 is fixed
|
||||
#reqs with no 'name' that were already satisfied were leaving behind tmp build dirs
|
||||
#2 examples of reqs that would do this
|
||||
# 1) https://bitbucket.org/ianb/initools/get/tip.zip
|
||||
# 2) parent-0.1.tar.gz
|
||||
|
||||
dist = abspath(join(here, 'packages', 'parent-0.1.tar.gz'))
|
||||
env = reset_env()
|
||||
result = run_pip('install', dist)
|
||||
result = run_pip('install', dist)
|
||||
build = env.venv_path/'build'
|
||||
assert not exists(build), "unexpected build/ dir exists: %s" % build
|
||||
env.assert_no_temp()
|
||||
|
||||
|
||||
def test_download_should_not_delete_existing_build_dir():
|
||||
"""
|
||||
It should not delete build/ if existing before run the command
|
||||
|
|
|
@ -45,7 +45,7 @@ def test_completion_for_unknown_shell():
|
|||
Test getting completion for an unknown shell
|
||||
"""
|
||||
reset_env()
|
||||
error_msg = 'error: no such option: --myfooshell'
|
||||
error_msg = 'no such option: --myfooshell'
|
||||
result = run_pip('completion', '--myfooshell', expect_error=True)
|
||||
assert error_msg in result.stderr, 'tests for an unknown shell failed'
|
||||
|
||||
|
|
|
@ -39,3 +39,32 @@ def test_download_should_download_dependencies():
|
|||
openid_tarball_prefix = str(Path('scratch')/ 'python-openid-')
|
||||
assert any(path.startswith(openid_tarball_prefix) for path in result.files_created)
|
||||
assert env.site_packages/ 'openid' not in result.files_created
|
||||
|
||||
|
||||
def test_download_should_skip_existing_files():
|
||||
"""
|
||||
It should not download files already existing in the scratch dir
|
||||
"""
|
||||
env = reset_env()
|
||||
|
||||
write_file('test-req.txt', textwrap.dedent("""
|
||||
INITools==0.1
|
||||
"""))
|
||||
|
||||
result = run_pip('install', '-r', env.scratch_path/ 'test-req.txt', '-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
|
||||
|
||||
# adding second package to test-req.txt
|
||||
write_file('test-req.txt', textwrap.dedent("""
|
||||
INITools==0.1
|
||||
python-openid==2.2.5
|
||||
"""))
|
||||
|
||||
# only the second package should be downloaded
|
||||
result = run_pip('install', '-r', env.scratch_path/ 'test-req.txt', '-d', '.', expect_error=True)
|
||||
openid_tarball_prefix = str(Path('scratch')/ 'python-openid-')
|
||||
assert any(path.startswith(openid_tarball_prefix) for path in result.files_created)
|
||||
assert Path('scratch')/ 'INITools-0.1.tar.gz' not in result.files_created
|
||||
assert env.site_packages/ 'initools' not in result.files_created
|
||||
assert env.site_packages/ 'openid' not in result.files_created
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
from pip.backwardcompat import urllib
|
||||
from tests.test_pip import here, reset_env, run_pip, pyversion
|
||||
from tests.path import Path
|
||||
|
||||
index_url = 'file://' + urllib.quote(str(Path(here).abspath/'in dex').replace('\\', '/'))
|
||||
|
||||
|
||||
def test_install():
|
||||
"""
|
||||
Test installing from a local index.
|
||||
|
||||
"""
|
||||
env = reset_env()
|
||||
result = run_pip('install', '-vvv', '--index-url', index_url, 'FSPkg', expect_error=False)
|
||||
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)
|
|
@ -0,0 +1,38 @@
|
|||
import textwrap
|
||||
|
||||
from tests.test_pip import reset_env, run_pip, pyversion, here, write_file
|
||||
|
||||
|
||||
def test_find_links_relative_path():
|
||||
"""Test find-links as a relative path."""
|
||||
e = reset_env()
|
||||
result = run_pip(
|
||||
'install',
|
||||
'parent==0.1',
|
||||
'--no-index',
|
||||
'--find-links',
|
||||
'packages/',
|
||||
cwd=here)
|
||||
egg_info_folder = e.site_packages / 'parent-0.1-py%s.egg-info' % pyversion
|
||||
initools_folder = e.site_packages / 'parent'
|
||||
assert egg_info_folder in result.files_created, str(result)
|
||||
assert initools_folder in result.files_created, str(result)
|
||||
|
||||
|
||||
def test_find_links_requirements_file_relative_path():
|
||||
"""Test find-links as a relative path to a reqs file."""
|
||||
e = reset_env()
|
||||
write_file('test-req.txt', textwrap.dedent("""
|
||||
--no-index
|
||||
--find-links=../../../packages/
|
||||
parent==0.1
|
||||
"""))
|
||||
result = run_pip(
|
||||
'install',
|
||||
'-r',
|
||||
e.scratch_path / "test-req.txt",
|
||||
cwd=here)
|
||||
egg_info_folder = e.site_packages / 'parent-0.1-py%s.egg-info' % pyversion
|
||||
initools_folder = e.site_packages / 'parent'
|
||||
assert egg_info_folder in result.files_created, str(result)
|
||||
assert initools_folder in result.files_created, str(result)
|
|
@ -1,12 +1,15 @@
|
|||
from pkg_resources import parse_version
|
||||
from pip.backwardcompat import urllib
|
||||
|
||||
from pip.req import InstallRequirement
|
||||
from pip.index import PackageFinder
|
||||
|
||||
from pip.exceptions import BestVersionAlreadyInstalled
|
||||
from tests.path import Path
|
||||
from tests.test_pip import here
|
||||
from nose.tools import assert_raises
|
||||
from mock import Mock
|
||||
|
||||
find_links = 'file://' + urllib.quote(str(Path(here).abspath/'packages').replace('\\', '/'))
|
||||
find_links2 = 'file://' + urllib.quote(str(Path(here).abspath/'packages2').replace('\\', '/'))
|
||||
|
||||
|
||||
def test_no_mpkg():
|
||||
|
@ -25,3 +28,50 @@ def test_no_partial_name_match():
|
|||
found = finder.find_requirement(req, False)
|
||||
|
||||
assert found.url.endswith("gmpy-1.15.tar.gz"), found
|
||||
|
||||
def test_duplicates_sort_ok():
|
||||
"""Finder successfully finds one of a set of duplicates in different
|
||||
locations"""
|
||||
finder = PackageFinder([find_links, find_links2], [])
|
||||
req = InstallRequirement.from_line("duplicate")
|
||||
found = finder.find_requirement(req, False)
|
||||
|
||||
assert found.url.endswith("duplicate-1.0.tar.gz"), found
|
||||
|
||||
|
||||
def test_finder_detects_latest_find_links():
|
||||
"""Test PackageFinder detects latest using find-links"""
|
||||
req = InstallRequirement.from_line('simple', None)
|
||||
finder = PackageFinder([find_links], [])
|
||||
link = finder.find_requirement(req, False)
|
||||
assert link.url.endswith("simple-3.0.tar.gz")
|
||||
|
||||
|
||||
def test_finder_detects_latest_already_satisfied_find_links():
|
||||
"""Test PackageFinder detects latest already satisified using find-links"""
|
||||
req = InstallRequirement.from_line('simple', None)
|
||||
#the latest simple in local pkgs is 3.0
|
||||
latest_version = "3.0"
|
||||
satisfied_by = Mock(
|
||||
location = "/path",
|
||||
parsed_version = parse_version(latest_version),
|
||||
version = latest_version
|
||||
)
|
||||
req.satisfied_by = satisfied_by
|
||||
finder = PackageFinder([find_links], [])
|
||||
assert_raises(BestVersionAlreadyInstalled, finder.find_requirement, req, True)
|
||||
|
||||
|
||||
def test_finder_detects_latest_already_satisfied_pypi_links():
|
||||
"""Test PackageFinder detects latest already satisified using pypi links"""
|
||||
req = InstallRequirement.from_line('initools', None)
|
||||
#the latest initools on pypi is 0.3.1
|
||||
latest_version = "0.3.1"
|
||||
satisfied_by = Mock(
|
||||
location = "/path",
|
||||
parsed_version = parse_version(latest_version),
|
||||
version = latest_version
|
||||
)
|
||||
req.satisfied_by = satisfied_by
|
||||
finder = PackageFinder([], ["http://pypi.python.org/simple"])
|
||||
assert_raises(BestVersionAlreadyInstalled, finder.find_requirement, req, True)
|
||||
|
|
|
@ -91,7 +91,7 @@ def test_freeze_git_clone():
|
|||
expected = textwrap.dedent("""\
|
||||
Script result: ...pip freeze
|
||||
-- stdout: --------------------
|
||||
-e %s@...#egg=pip_test_package-...
|
||||
...-e %s@...#egg=pip_test_package-...
|
||||
...""" % local_checkout('git+http://github.com/pypa/pip-test-package.git'))
|
||||
_check_output(result, expected)
|
||||
|
||||
|
@ -101,7 +101,7 @@ def test_freeze_git_clone():
|
|||
expected = textwrap.dedent("""\
|
||||
Script result: pip freeze -f %(repo)s#egg=pip_test_package
|
||||
-- stdout: --------------------
|
||||
-f %(repo)s#egg=pip_test_package
|
||||
-f %(repo)s#egg=pip_test_package...
|
||||
-e %(repo)s@...#egg=pip_test_package-dev
|
||||
...""" % {'repo': local_checkout('git+http://github.com/pypa/pip-test-package.git')})
|
||||
_check_output(result, expected)
|
||||
|
@ -124,7 +124,7 @@ def test_freeze_mercurial_clone():
|
|||
expected = textwrap.dedent("""\
|
||||
Script result: ...pip freeze
|
||||
-- stdout: --------------------
|
||||
-e %s@...#egg=django_authority-...
|
||||
...-e %s@...#egg=django_authority-...
|
||||
...""" % local_checkout('hg+http://bitbucket.org/jezdez/django-authority'))
|
||||
_check_output(result, expected)
|
||||
|
||||
|
@ -135,7 +135,7 @@ def test_freeze_mercurial_clone():
|
|||
Script result: ...pip freeze -f %(repo)s#egg=django_authority
|
||||
-- stdout: --------------------
|
||||
-f %(repo)s#egg=django_authority
|
||||
-e %(repo)s@...#egg=django_authority-dev
|
||||
...-e %(repo)s@...#egg=django_authority-dev
|
||||
...""" % {'repo': local_checkout('hg+http://bitbucket.org/jezdez/django-authority')})
|
||||
_check_output(result, expected)
|
||||
|
||||
|
@ -156,7 +156,7 @@ def test_freeze_bazaar_clone():
|
|||
expected = textwrap.dedent("""\
|
||||
Script result: ...pip freeze
|
||||
-- stdout: --------------------
|
||||
-e %s@...#egg=django_wikiapp-...
|
||||
...-e %s@...#egg=django_wikiapp-...
|
||||
...""" % local_checkout('bzr+http://bazaar.launchpad.net/%7Edjango-wikiapp/django-wikiapp/release-0.1'))
|
||||
_check_output(result, expected)
|
||||
|
||||
|
@ -168,7 +168,7 @@ def test_freeze_bazaar_clone():
|
|||
Script result: ...pip freeze -f %(repo)s/#egg=django-wikiapp
|
||||
-- stdout: --------------------
|
||||
-f %(repo)s/#egg=django-wikiapp
|
||||
-e %(repo)s@...#egg=django_wikiapp-...
|
||||
...-e %(repo)s@...#egg=django_wikiapp-...
|
||||
...""" % {'repo':
|
||||
local_checkout('bzr+http://bazaar.launchpad.net/%7Edjango-wikiapp/django-wikiapp/release-0.1')})
|
||||
_check_output(result, expected)
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
import os
|
||||
|
||||
from nose.tools import assert_raises
|
||||
|
||||
from pip.download import _get_hash_from_file, _check_hash
|
||||
from pip.exceptions import InstallationError
|
||||
from pip.index import Link
|
||||
|
||||
|
||||
def test_get_hash_from_file_md5():
|
||||
file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz")
|
||||
file_link = Link("http://testserver/gmpy-1.15.tar.gz#md5=d41d8cd98f00b204e9800998ecf8427e")
|
||||
|
||||
download_hash = _get_hash_from_file(file_path, file_link)
|
||||
|
||||
assert download_hash.digest_size == 16
|
||||
assert download_hash.hexdigest() == "d41d8cd98f00b204e9800998ecf8427e"
|
||||
|
||||
|
||||
def test_get_hash_from_file_sha1():
|
||||
file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz")
|
||||
file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha1=da39a3ee5e6b4b0d3255bfef95601890afd80709")
|
||||
|
||||
download_hash = _get_hash_from_file(file_path, file_link)
|
||||
|
||||
assert download_hash.digest_size == 20
|
||||
assert download_hash.hexdigest() == "da39a3ee5e6b4b0d3255bfef95601890afd80709"
|
||||
|
||||
|
||||
def test_get_hash_from_file_sha224():
|
||||
file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz")
|
||||
file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha224=d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f")
|
||||
|
||||
download_hash = _get_hash_from_file(file_path, file_link)
|
||||
|
||||
assert download_hash.digest_size == 28
|
||||
assert download_hash.hexdigest() == "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f"
|
||||
|
||||
|
||||
def test_get_hash_from_file_sha384():
|
||||
file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz")
|
||||
file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha384=38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b")
|
||||
|
||||
download_hash = _get_hash_from_file(file_path, file_link)
|
||||
|
||||
assert download_hash.digest_size == 48
|
||||
assert download_hash.hexdigest() == "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"
|
||||
|
||||
|
||||
def test_get_hash_from_file_sha256():
|
||||
file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz")
|
||||
file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
|
||||
|
||||
download_hash = _get_hash_from_file(file_path, file_link)
|
||||
|
||||
assert download_hash.digest_size == 32
|
||||
assert download_hash.hexdigest() == "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
|
||||
|
||||
def test_get_hash_from_file_sha512():
|
||||
file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz")
|
||||
file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha512=cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e")
|
||||
|
||||
download_hash = _get_hash_from_file(file_path, file_link)
|
||||
|
||||
assert download_hash.digest_size == 64
|
||||
assert download_hash.hexdigest() == "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"
|
||||
|
||||
|
||||
def test_get_hash_from_file_unknown():
|
||||
file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz")
|
||||
file_link = Link("http://testserver/gmpy-1.15.tar.gz#unknown_hash=d41d8cd98f00b204e9800998ecf8427e")
|
||||
|
||||
download_hash = _get_hash_from_file(file_path, file_link)
|
||||
|
||||
assert download_hash is None
|
||||
|
||||
|
||||
def test_check_hash_md5_valid():
|
||||
file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz")
|
||||
file_link = Link("http://testserver/gmpy-1.15.tar.gz#md5=d41d8cd98f00b204e9800998ecf8427e")
|
||||
|
||||
download_hash = _get_hash_from_file(file_path, file_link)
|
||||
|
||||
_check_hash(download_hash, file_link)
|
||||
|
||||
|
||||
def test_check_hash_md5_invalid():
|
||||
file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz")
|
||||
file_link = Link("http://testserver/gmpy-1.15.tar.gz#md5=deadbeef")
|
||||
|
||||
download_hash = _get_hash_from_file(file_path, file_link)
|
||||
|
||||
assert_raises(InstallationError, _check_hash, download_hash, file_link)
|
||||
|
||||
|
||||
def test_check_hash_sha1_valid():
|
||||
file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz")
|
||||
file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha1=da39a3ee5e6b4b0d3255bfef95601890afd80709")
|
||||
|
||||
download_hash = _get_hash_from_file(file_path, file_link)
|
||||
|
||||
_check_hash(download_hash, file_link)
|
||||
|
||||
|
||||
def test_check_hash_sha1_invalid():
|
||||
file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz")
|
||||
file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha1=deadbeef")
|
||||
|
||||
download_hash = _get_hash_from_file(file_path, file_link)
|
||||
|
||||
assert_raises(InstallationError, _check_hash, download_hash, file_link)
|
||||
|
||||
|
||||
def test_check_hash_sha224_valid():
|
||||
file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz")
|
||||
file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha224=d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f'")
|
||||
|
||||
download_hash = _get_hash_from_file(file_path, file_link)
|
||||
|
||||
_check_hash(download_hash, file_link)
|
||||
|
||||
|
||||
def test_check_hash_sha224_invalid():
|
||||
file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz")
|
||||
file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha224=deadbeef")
|
||||
|
||||
download_hash = _get_hash_from_file(file_path, file_link)
|
||||
|
||||
assert_raises(InstallationError, _check_hash, download_hash, file_link)
|
||||
|
||||
|
||||
def test_check_hash_sha384_valid():
|
||||
file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz")
|
||||
file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha384=38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b")
|
||||
|
||||
download_hash = _get_hash_from_file(file_path, file_link)
|
||||
|
||||
_check_hash(download_hash, file_link)
|
||||
|
||||
|
||||
def test_check_hash_sha384_invalid():
|
||||
file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz")
|
||||
file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha384=deadbeef")
|
||||
|
||||
download_hash = _get_hash_from_file(file_path, file_link)
|
||||
|
||||
assert_raises(InstallationError, _check_hash, download_hash, file_link)
|
||||
|
||||
|
||||
def test_check_hash_sha256_valid():
|
||||
file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz")
|
||||
file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
|
||||
|
||||
download_hash = _get_hash_from_file(file_path, file_link)
|
||||
|
||||
_check_hash(download_hash, file_link)
|
||||
|
||||
|
||||
def test_check_hash_sha256_invalid():
|
||||
file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz")
|
||||
file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha256=deadbeef")
|
||||
|
||||
download_hash = _get_hash_from_file(file_path, file_link)
|
||||
|
||||
assert_raises(InstallationError, _check_hash, download_hash, file_link)
|
||||
|
||||
|
||||
def test_check_hash_sha512_valid():
|
||||
file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz")
|
||||
file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha512=cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e")
|
||||
|
||||
download_hash = _get_hash_from_file(file_path, file_link)
|
||||
|
||||
_check_hash(download_hash, file_link)
|
||||
|
||||
|
||||
def test_check_hash_sha512_invalid():
|
||||
file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz")
|
||||
file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha512=deadbeef")
|
||||
|
||||
download_hash = _get_hash_from_file(file_path, file_link)
|
||||
|
||||
assert_raises(InstallationError, _check_hash, download_hash, file_link)
|
||||
|
||||
|
||||
def test_check_hasher_mismsatch():
|
||||
file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz")
|
||||
file_link = Link("http://testserver/gmpy-1.15.tar.gz#md5=d41d8cd98f00b204e9800998ecf8427e")
|
||||
other_link = Link("http://testserver/gmpy-1.15.tar.gz#sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
|
||||
|
||||
download_hash = _get_hash_from_file(file_path, file_link)
|
||||
|
||||
assert_raises(InstallationError, _check_hash, download_hash, other_link)
|
|
@ -1,4 +1,11 @@
|
|||
from pip.index import package_to_requirement, HTMLPage
|
||||
import os
|
||||
from pip.backwardcompat import urllib
|
||||
from tests.path import Path
|
||||
from pip.index import package_to_requirement, HTMLPage, get_mirrors, DEFAULT_MIRROR_HOSTNAME
|
||||
from pip.index import PackageFinder, Link, InfLink
|
||||
from tests.test_pip import reset_env, run_pip, pyversion, here
|
||||
from string import ascii_lowercase
|
||||
from mock import patch
|
||||
|
||||
|
||||
def test_package_name_should_be_converted_to_requirement():
|
||||
|
@ -26,3 +33,75 @@ def test_html_page_should_be_able_to_scrap_rel_links():
|
|||
assert len(links) == 1
|
||||
assert links[0].url == 'http://supervisord.org/'
|
||||
|
||||
@patch('socket.gethostbyname_ex')
|
||||
def test_get_mirrors(mock_gethostbyname_ex):
|
||||
# Test when the expected result comes back
|
||||
# from socket.gethostbyname_ex
|
||||
mock_gethostbyname_ex.return_value = ('g.pypi.python.org', [DEFAULT_MIRROR_HOSTNAME], ['129.21.171.98'])
|
||||
mirrors = get_mirrors()
|
||||
# Expect [a-g].pypi.python.org, since last mirror
|
||||
# is returned as g.pypi.python.org
|
||||
assert len(mirrors) == 7
|
||||
for c in "abcdefg":
|
||||
assert c + ".pypi.python.org" in mirrors
|
||||
|
||||
@patch('socket.gethostbyname_ex')
|
||||
def test_get_mirrors_no_cname(mock_gethostbyname_ex):
|
||||
# Test when the UNexpected result comes back
|
||||
# from socket.gethostbyname_ex
|
||||
# (seeing this in Japan and was resulting in 216k
|
||||
# invalid mirrors and a hot CPU)
|
||||
mock_gethostbyname_ex.return_value = (DEFAULT_MIRROR_HOSTNAME, [DEFAULT_MIRROR_HOSTNAME], ['129.21.171.98'])
|
||||
mirrors = get_mirrors()
|
||||
# Falls back to [a-z].pypi.python.org
|
||||
assert len(mirrors) == 26
|
||||
for c in ascii_lowercase:
|
||||
assert c + ".pypi.python.org" in mirrors
|
||||
|
||||
|
||||
def test_sort_locations_file_find_link():
|
||||
"""
|
||||
Test that a file:// find-link dir gets listdir run
|
||||
"""
|
||||
find_links_url = 'file://' + os.path.join(here, 'packages')
|
||||
find_links = [find_links_url]
|
||||
finder = PackageFinder(find_links, [])
|
||||
files, urls = finder._sort_locations(find_links)
|
||||
assert files and not urls, "files and not urls should have been found at find-links url: %s" % find_links_url
|
||||
|
||||
|
||||
def test_sort_locations_file_not_find_link():
|
||||
"""
|
||||
Test that a file:// url dir that's not a find-link, doesn't get a listdir run
|
||||
"""
|
||||
index_url = 'file://' + os.path.join(here, 'indexes', 'empty_with_pkg')
|
||||
finder = PackageFinder([], [])
|
||||
files, urls = finder._sort_locations([index_url])
|
||||
assert urls and not files, "urls, but not files should have been found"
|
||||
|
||||
|
||||
def test_install_from_file_index_hash_link():
|
||||
"""
|
||||
Test that a pkg can be installed from a file:// index using a link with a hash
|
||||
"""
|
||||
env = reset_env()
|
||||
index_url = 'file://' + os.path.join(here, 'indexes', 'simple')
|
||||
result = run_pip('install', '-i', index_url, 'simple==1.0')
|
||||
egg_info_folder = env.site_packages / 'simple-1.0-py%s.egg-info' % pyversion
|
||||
assert egg_info_folder in result.files_created, str(result)
|
||||
|
||||
|
||||
def test_file_index_url_quoting():
|
||||
"""
|
||||
Test url quoting of file index url with a space
|
||||
"""
|
||||
index_url = 'file://' + urllib.quote(str(Path(here).abspath/'indexes'/'in dex').replace('\\', '/'))
|
||||
env = reset_env()
|
||||
result = run_pip('install', '-vvv', '--index-url', index_url, 'simple', expect_error=False)
|
||||
assert (env.site_packages/'simple') in result.files_created, str(result.stdout)
|
||||
assert (env.site_packages/'simple-1.0-py%s.egg-info' % pyversion) in result.files_created, str(result)
|
||||
|
||||
|
||||
def test_inflink_greater():
|
||||
"""Test InfLink compares greater."""
|
||||
assert InfLink > Link(object())
|
||||
|
|
|
@ -314,12 +314,18 @@ class TestPipEnvironment(TestFileEnvironment):
|
|||
assert self.venv_path == virtualenv_paths[0] # sanity check
|
||||
|
||||
for id, path in zip(('venv', 'lib', 'include', 'bin'), virtualenv_paths):
|
||||
#fix for virtualenv issue #306
|
||||
if hasattr(sys, "pypy_version_info") and id == 'lib':
|
||||
path = os.path.join(self.venv_path, 'lib-python', pyversion)
|
||||
setattr(self, id+'_path', Path(path))
|
||||
setattr(self, id, relpath(self.root_path, path))
|
||||
|
||||
assert self.venv == TestPipEnvironment.venv # sanity check
|
||||
|
||||
self.site_packages = self.lib/'site-packages'
|
||||
if hasattr(sys, "pypy_version_info"):
|
||||
self.site_packages = self.venv/'site-packages'
|
||||
else:
|
||||
self.site_packages = self.lib/'site-packages'
|
||||
self.user_base_path = self.venv_path/'user'
|
||||
self.user_site_path = self.venv_path/'user'/site_packages_suffix
|
||||
|
||||
|
@ -362,6 +368,10 @@ class TestPipEnvironment(TestFileEnvironment):
|
|||
if sitecustomize:
|
||||
self._add_to_sitecustomize(sitecustomize)
|
||||
|
||||
# Ensure that $TMPDIR exists (because we use start_clear=False, it's not created for us)
|
||||
if self.temp_path and not os.path.exists(self.temp_path):
|
||||
os.makedirs(self.temp_path)
|
||||
|
||||
def _ignore_file(self, fn):
|
||||
if fn.endswith('__pycache__') or fn.endswith(".pyc"):
|
||||
result = True
|
||||
|
@ -444,12 +454,18 @@ class FastTestPipEnvironment(TestPipEnvironment):
|
|||
virtualenv_paths = virtualenv.path_locations(self.venv_path)
|
||||
|
||||
for id, path in zip(('venv', 'lib', 'include', 'bin'), virtualenv_paths):
|
||||
#fix for virtualenv issue #306
|
||||
if hasattr(sys, "pypy_version_info") and id == 'lib':
|
||||
path = os.path.join(self.venv_path, 'lib-python', pyversion)
|
||||
setattr(self, id+'_path', Path(path))
|
||||
setattr(self, id, relpath(self.root_path, path))
|
||||
|
||||
assert self.venv == TestPipEnvironment.venv # sanity check
|
||||
|
||||
self.site_packages = self.lib/'site-packages'
|
||||
if hasattr(sys, "pypy_version_info"):
|
||||
self.site_packages = self.venv/'site-packages'
|
||||
else:
|
||||
self.site_packages = self.lib/'site-packages'
|
||||
self.user_base_path = self.venv_path/'user'
|
||||
self.user_site_path = self.venv_path/'user'/'lib'/self.lib.name/'site-packages'
|
||||
|
||||
|
@ -510,6 +526,10 @@ class FastTestPipEnvironment(TestPipEnvironment):
|
|||
|
||||
assert self.root_path.exists
|
||||
|
||||
# Ensure that $TMPDIR exists (because we use start_clear=False, it's not created for us)
|
||||
if self.temp_path and not os.path.exists(self.temp_path):
|
||||
os.makedirs(self.temp_path)
|
||||
|
||||
def __del__(self):
|
||||
pass # shutil.rmtree(str(self.root_path), ignore_errors=True)
|
||||
|
||||
|
@ -663,5 +683,5 @@ def _change_test_package_version(env, version_pkg_path):
|
|||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.stderr.write("Run pip's tests using nosetests. Requires virtualenv, ScriptTest, and nose.\n")
|
||||
sys.stderr.write("Run pip's tests using nosetests. Requires virtualenv, ScriptTest, mock, and nose.\n")
|
||||
sys.exit(1)
|
||||
|
|
|
@ -80,20 +80,23 @@ def test_multiple_requirements_files():
|
|||
def test_respect_order_in_requirements_file():
|
||||
env = reset_env()
|
||||
write_file('frameworks-req.txt', textwrap.dedent("""\
|
||||
bidict
|
||||
ordereddict
|
||||
initools
|
||||
parent
|
||||
child
|
||||
simple
|
||||
"""))
|
||||
result = run_pip('install', '-r', env.scratch_path / 'frameworks-req.txt')
|
||||
|
||||
find_links = 'file://' + os.path.join(here, 'packages')
|
||||
result = run_pip('install', '--no-index', '-f', find_links, '-r', env.scratch_path / 'frameworks-req.txt')
|
||||
|
||||
downloaded = [line for line in result.stdout.split('\n')
|
||||
if 'Downloading/unpacking' in line]
|
||||
|
||||
assert 'bidict' in downloaded[0], 'First download should ' \
|
||||
'be "bidict" but was "%s"' % downloaded[0]
|
||||
assert 'ordereddict' in downloaded[1], 'Second download should ' \
|
||||
'be "ordereddict" but was "%s"' % downloaded[1]
|
||||
assert 'initools' in downloaded[2], 'Third download should ' \
|
||||
'be "initools" but was "%s"' % downloaded[2]
|
||||
assert 'parent' in downloaded[0], 'First download should ' \
|
||||
'be "parent" but was "%s"' % downloaded[0]
|
||||
assert 'child' in downloaded[1], 'Second download should ' \
|
||||
'be "child" but was "%s"' % downloaded[1]
|
||||
assert 'simple' in downloaded[2], 'Third download should ' \
|
||||
'be "simple" but was "%s"' % downloaded[2]
|
||||
|
||||
|
||||
def test_requirements_data_structure_keeps_order():
|
||||
|
@ -121,19 +124,22 @@ def test_requirements_data_structure_implements__contains__():
|
|||
assert 'pip' in requirements
|
||||
assert 'nose' not in requirements
|
||||
|
||||
@patch('os.path.normcase')
|
||||
@patch('pip.req.os.getcwd')
|
||||
@patch('pip.req.os.path.exists')
|
||||
@patch('pip.req.os.path.isdir')
|
||||
def test_parse_editable_local(isdir_mock, exists_mock, getcwd_mock):
|
||||
def test_parse_editable_local(isdir_mock, exists_mock, getcwd_mock, normcase_mock):
|
||||
exists_mock.return_value = isdir_mock.return_value = True
|
||||
getcwd_mock.return_value = "/some/path"
|
||||
# mocks needed to support path operations on windows tests
|
||||
normcase_mock.return_value = getcwd_mock.return_value = "/some/path"
|
||||
assert_equal(
|
||||
parse_editable('.', 'git'),
|
||||
(None, 'file:///some/path', None)
|
||||
)
|
||||
normcase_mock.return_value = "/some/path/foo"
|
||||
assert_equal(
|
||||
parse_editable('foo', 'git'),
|
||||
(None, 'file://' + os.path.join("/some/path", 'foo'), None)
|
||||
(None, 'file:///some/path/foo', None)
|
||||
)
|
||||
|
||||
def test_parse_editable_default_vcs():
|
||||
|
@ -154,19 +160,21 @@ def test_parse_editable_vcs_extras():
|
|||
('foo[extras]', 'svn+https://foo#egg=foo[extras]', None)
|
||||
)
|
||||
|
||||
@patch('os.path.normcase')
|
||||
@patch('pip.req.os.getcwd')
|
||||
@patch('pip.req.os.path.exists')
|
||||
@patch('pip.req.os.path.isdir')
|
||||
def test_parse_editable_local_extras(isdir_mock, exists_mock, getcwd_mock):
|
||||
def test_parse_editable_local_extras(isdir_mock, exists_mock, getcwd_mock, normcase_mock):
|
||||
exists_mock.return_value = isdir_mock.return_value = True
|
||||
getcwd_mock.return_value = "/some/path"
|
||||
normcase_mock.return_value = getcwd_mock.return_value = "/some/path"
|
||||
assert_equal(
|
||||
parse_editable('.[extras]', 'git'),
|
||||
(None, 'file://' + "/some/path", ('extras',))
|
||||
)
|
||||
normcase_mock.return_value = "/some/path/foo"
|
||||
assert_equal(
|
||||
parse_editable('foo[bar,baz]', 'git'),
|
||||
(None, 'file://' + os.path.join("/some/path", 'foo'), ('bar', 'baz'))
|
||||
(None, 'file:///some/path/foo', ('bar', 'baz'))
|
||||
)
|
||||
|
||||
def test_install_local_editable_with_extras():
|
||||
|
@ -175,4 +183,4 @@ def test_install_local_editable_with_extras():
|
|||
res = run_pip('install', '-e', to_install + '[bar]', expect_error=False)
|
||||
assert env.site_packages/'easy-install.pth' in res.files_updated
|
||||
assert env.site_packages/'LocalExtras.egg-link' in res.files_created
|
||||
assert env.site_packages/'fspkg' in res.files_created
|
||||
assert env.site_packages/'simple' in res.files_created
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
import re
|
||||
from pip import __version__
|
||||
from pip.commands.show import search_packages_info
|
||||
from tests.test_pip import reset_env, run_pip
|
||||
|
||||
|
||||
def test_show():
|
||||
"""
|
||||
Test end to end test for show command.
|
||||
|
||||
"""
|
||||
reset_env()
|
||||
result = run_pip('show', 'pip')
|
||||
lines = result.stdout.split('\n')
|
||||
assert len(lines) == 6
|
||||
assert lines[0] == '---', lines[0]
|
||||
assert lines[1] == 'Name: pip', lines[1]
|
||||
assert lines[2] == 'Version: %s' % __version__, lines[2]
|
||||
assert lines[3].startswith('Location: '), lines[3]
|
||||
assert lines[4] == 'Requires: '
|
||||
|
||||
|
||||
def test_show_with_files_not_found():
|
||||
"""
|
||||
Test for show command with installed files listing enabled and
|
||||
installed-files.txt not found.
|
||||
|
||||
"""
|
||||
reset_env()
|
||||
result = run_pip('show', '-f', 'pip')
|
||||
lines = result.stdout.split('\n')
|
||||
assert len(lines) == 8
|
||||
assert lines[0] == '---', lines[0]
|
||||
assert lines[1] == 'Name: pip', lines[1]
|
||||
assert lines[2] == 'Version: %s' % __version__, lines[2]
|
||||
assert lines[3].startswith('Location: '), lines[3]
|
||||
assert lines[4] == 'Requires: '
|
||||
assert lines[5] == 'Files:', lines[4]
|
||||
assert lines[6] == 'Cannot locate installed-files.txt', lines[5]
|
||||
|
||||
|
||||
def test_show_with_all_files():
|
||||
"""
|
||||
Test listing all files in the show command.
|
||||
|
||||
"""
|
||||
reset_env()
|
||||
result = run_pip('install', 'initools==0.2')
|
||||
result = run_pip('show', '--files', 'initools')
|
||||
assert re.search(r"Files:\n( .+\n)+", result.stdout)
|
||||
|
||||
|
||||
def test_missing_argument():
|
||||
"""
|
||||
Test show command with no arguments.
|
||||
|
||||
"""
|
||||
reset_env()
|
||||
result = run_pip('show')
|
||||
assert 'ERROR: Please provide a project name or names.' in result.stdout
|
||||
|
||||
|
||||
def test_find_package_not_found():
|
||||
"""
|
||||
Test trying to get info about a nonexistent package.
|
||||
|
||||
"""
|
||||
result = search_packages_info(['abcd3'])
|
||||
assert len(list(result)) == 0
|
||||
|
||||
|
||||
def test_search_any_case():
|
||||
"""
|
||||
Search for a package in any case.
|
||||
|
||||
"""
|
||||
result = list(search_packages_info(['PIP']))
|
||||
assert len(result) == 1
|
||||
assert 'pip' == result[0]['name']
|
||||
|
||||
|
||||
def test_more_than_one_package():
|
||||
"""
|
||||
Search for more than one package.
|
||||
|
||||
"""
|
||||
result = list(search_packages_info(['Pip', 'Nose', 'Virtualenv']))
|
||||
assert len(result) == 3
|
|
@ -66,3 +66,24 @@ def test_sitecustomize_not_growing_in_fast_environment():
|
|||
size2 = os.stat(sc2).st_size
|
||||
assert size1==size2, "size before, %d != size after, %d" %(size1, size2)
|
||||
|
||||
|
||||
def test_tmp_dir_exists_in_env():
|
||||
"""
|
||||
Test that $TMPDIR == env.temp_path and path exists, and env.assert_no_temp() passes
|
||||
"""
|
||||
#need these tests to ensure the assert_no_temp feature of scripttest is working
|
||||
env = reset_env(use_distribute=True)
|
||||
env.assert_no_temp() #this fails if env.tmp_path doesn't exist
|
||||
assert env.environ['TMPDIR'] == env.temp_path
|
||||
assert isdir(env.temp_path)
|
||||
|
||||
|
||||
def test_tmp_dir_exists_in_fast_env():
|
||||
"""
|
||||
Test that $TMPDIR == env.temp_path and path exists and env.assert_no_temp() passes (in fast env)
|
||||
"""
|
||||
#need these tests to ensure the assert_no_temp feature of scripttest is working
|
||||
env = reset_env()
|
||||
env.assert_no_temp() #this fails if env.tmp_path doesn't exist
|
||||
assert env.environ['TMPDIR'] == env.temp_path
|
||||
assert isdir(env.temp_path)
|
||||
|
|
|
@ -20,6 +20,6 @@ def test_install_package_that_emits_unicode():
|
|||
|
||||
env = reset_env()
|
||||
to_install = os.path.abspath(os.path.join(here, 'packages', 'BrokenEmitsUTF8'))
|
||||
result = run_pip('install', to_install, expect_error=True)
|
||||
assert '__main__.FakeError: this package designed to fail on install' in result.stdout
|
||||
result = run_pip('install', to_install, expect_error=True, expect_temp=True, quiet=True)
|
||||
assert 'FakeError: this package designed to fail on install' in result.stdout
|
||||
assert 'UnicodeDecodeError' not in result.stdout
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
from __future__ import with_statement
|
||||
|
||||
import textwrap
|
||||
import sys
|
||||
from os.path import join, abspath
|
||||
from os.path import join, abspath, normpath
|
||||
from tempfile import mkdtemp
|
||||
from mock import patch
|
||||
from tests.test_pip import here, reset_env, run_pip, assert_all_changes, write_file, pyversion
|
||||
from tests.local_repos import local_repo, local_checkout
|
||||
|
||||
|
@ -16,6 +19,8 @@ def test_simple_uninstall():
|
|||
env = reset_env()
|
||||
result = run_pip('install', 'INITools==0.2')
|
||||
assert join(env.site_packages, 'initools') in result.files_created, sorted(result.files_created.keys())
|
||||
#the import forces the generation of __pycache__ if the version of python supports it
|
||||
env.run('python', '-c', "import initools")
|
||||
result2 = run_pip('uninstall', 'INITools', '-y')
|
||||
assert_all_changes(result, result2, [env.venv/'build', 'cache'])
|
||||
|
||||
|
@ -34,6 +39,19 @@ def test_uninstall_with_scripts():
|
|||
assert_all_changes(result, result2, [env.venv/'build', 'cache'])
|
||||
|
||||
|
||||
def test_uninstall_easy_install_after_import():
|
||||
"""
|
||||
Uninstall an easy_installed package after it's been imported
|
||||
|
||||
"""
|
||||
env = reset_env()
|
||||
result = env.run('easy_install', 'INITools==0.2', expect_stderr=True)
|
||||
#the import forces the generation of __pycache__ if the version of python supports it
|
||||
env.run('python', '-c', "import initools")
|
||||
result2 = run_pip('uninstall', 'INITools', '-y')
|
||||
assert_all_changes(result, result2, [env.venv/'build', 'cache'])
|
||||
|
||||
|
||||
def test_uninstall_namespace_package():
|
||||
"""
|
||||
Uninstall a distribution with a namespace package without clobbering
|
||||
|
@ -48,6 +66,33 @@ def test_uninstall_namespace_package():
|
|||
assert join(env.site_packages, 'pd', 'find') in result2.files_deleted, sorted(result2.files_deleted.keys())
|
||||
|
||||
|
||||
def test_uninstall_overlapping_package():
|
||||
"""
|
||||
Uninstalling a distribution that adds modules to a pre-existing package
|
||||
should only remove those added modules, not the rest of the existing
|
||||
package.
|
||||
|
||||
See: GitHub issue #355 (pip uninstall removes things it didn't install)
|
||||
"""
|
||||
parent_pkg = abspath(join(here, 'packages', 'parent-0.1.tar.gz'))
|
||||
child_pkg = abspath(join(here, 'packages', 'child-0.1.tar.gz'))
|
||||
env = reset_env()
|
||||
result1 = run_pip('install', parent_pkg, expect_error=False)
|
||||
assert join(env.site_packages, 'parent') in result1.files_created, sorted(result1.files_created.keys())
|
||||
result2 = run_pip('install', child_pkg, expect_error=False)
|
||||
assert join(env.site_packages, 'child') in result2.files_created, sorted(result2.files_created.keys())
|
||||
assert normpath(join(env.site_packages, 'parent/plugins/child_plugin.py')) in result2.files_created, sorted(result2.files_created.keys())
|
||||
#the import forces the generation of __pycache__ if the version of python supports it
|
||||
env.run('python', '-c', "import parent.plugins.child_plugin, child")
|
||||
result3 = run_pip('uninstall', '-y', 'child', expect_error=False)
|
||||
assert join(env.site_packages, 'child') in result3.files_deleted, sorted(result3.files_created.keys())
|
||||
assert normpath(join(env.site_packages, 'parent/plugins/child_plugin.py')) in result3.files_deleted, sorted(result3.files_deleted.keys())
|
||||
assert join(env.site_packages, 'parent') not in result3.files_deleted, sorted(result3.files_deleted.keys())
|
||||
# Additional check: uninstalling 'child' should return things to the
|
||||
# previous state, without unintended side effects.
|
||||
assert_all_changes(result2, result3, [])
|
||||
|
||||
|
||||
def test_uninstall_console_scripts():
|
||||
"""
|
||||
Test uninstalling a package with more files (console_script entry points, extra directories).
|
||||
|
@ -155,3 +200,42 @@ def test_uninstall_as_egg():
|
|||
result2 = run_pip('uninstall', 'FSPkg', '-y', expect_error=True)
|
||||
assert_all_changes(result, result2, [env.venv/'build', 'cache'])
|
||||
|
||||
|
||||
@patch('pip.req.logger')
|
||||
def test_uninstallpathset_no_paths(mock_logger):
|
||||
"""
|
||||
Test UninstallPathSet logs notification when there are no paths to uninstall
|
||||
|
||||
"""
|
||||
from pip.req import UninstallPathSet
|
||||
from pkg_resources import get_distribution
|
||||
test_dist = get_distribution('pip')
|
||||
# ensure that the distribution is "local"
|
||||
with patch("pip.req.dist_is_local") as mock_dist_is_local:
|
||||
mock_dist_is_local.return_value = True
|
||||
uninstall_set = UninstallPathSet(test_dist)
|
||||
uninstall_set.remove() #with no files added to set
|
||||
mock_logger.notify.assert_any_call("Can't uninstall 'pip'. No files were found to uninstall.")
|
||||
|
||||
|
||||
@patch('pip.req.logger')
|
||||
def test_uninstallpathset_non_local(mock_logger):
|
||||
"""
|
||||
Test UninstallPathSet logs notification and returns (with no exception) when dist is non-local
|
||||
|
||||
"""
|
||||
from pip.req import UninstallPathSet
|
||||
from pkg_resources import get_distribution
|
||||
test_dist = get_distribution('pip')
|
||||
test_dist.location = "/NON_LOCAL"
|
||||
# ensure that the distribution is "non-local"
|
||||
# setting location isn't enough, due to egg-link file checking for
|
||||
# develop-installs
|
||||
with patch("pip.req.dist_is_local") as mock_dist_is_local:
|
||||
mock_dist_is_local.return_value = False
|
||||
uninstall_set = UninstallPathSet(test_dist)
|
||||
uninstall_set.remove() #with no files added to set; which is the case when trying to remove non-local dists
|
||||
mock_logger.notify.assert_any_call("Not uninstalling pip at /NON_LOCAL, outside environment %s" % sys.prefix)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -49,11 +49,12 @@ def test_upgrade_with_newest_already_installed():
|
|||
not be reinstalled and the user should be informed.
|
||||
"""
|
||||
|
||||
find_links = 'file://' + join(here, 'packages')
|
||||
env = reset_env()
|
||||
run_pip('install', 'INITools')
|
||||
result = run_pip('install', '--upgrade', 'INITools')
|
||||
assert not result.files_created, 'pip install --upgrade INITools upgraded when it should not have'
|
||||
assert 'already up-to-date' in result.stdout
|
||||
run_pip('install', '-f', find_links, '--no-index', 'simple')
|
||||
result = run_pip('install', '--upgrade', '-f', find_links, '--no-index', 'simple')
|
||||
assert not result.files_created, 'simple upgraded when it should not have'
|
||||
assert 'already up-to-date' in result.stdout, result.stdout
|
||||
|
||||
|
||||
def test_upgrade_force_reinstall_newest():
|
||||
|
@ -207,8 +208,8 @@ def test_upgrade_vcs_req_with_no_dists_found():
|
|||
def test_upgrade_vcs_req_with_dist_found():
|
||||
"""It can upgrade a VCS requirement that has distributions on the index."""
|
||||
reset_env()
|
||||
req = "%s#egg=virtualenv" % local_checkout(
|
||||
"git+git://github.com/pypa/virtualenv@c21fef2c2d53cf19f49bcc37f9c058a33fb50499")
|
||||
# TODO(pnasrat) Using local_checkout fails on windows - oddness with the test path urls/git.
|
||||
req = "%s#egg=virtualenv" % "git+git://github.com/pypa/virtualenv@c21fef2c2d53cf19f49bcc37f9c058a33fb50499"
|
||||
run_pip("install", req)
|
||||
result = run_pip("install", "-U", req)
|
||||
assert not "pypi.python.org" in result.stdout, result.stdout
|
||||
|
|
|
@ -6,7 +6,15 @@ import sys
|
|||
from os.path import abspath, join, curdir, isdir, isfile
|
||||
from nose import SkipTest
|
||||
from tests.local_repos import local_checkout
|
||||
from tests.test_pip import here, reset_env, run_pip, pyversion
|
||||
from tests.test_pip import here, reset_env, run_pip, pyversion, assert_all_changes
|
||||
|
||||
|
||||
patch_dist_in_site_packages = """
|
||||
def dist_in_site_packages(dist):
|
||||
return False
|
||||
import pip
|
||||
pip.util.dist_in_site_packages=dist_in_site_packages
|
||||
"""
|
||||
|
||||
|
||||
def test_install_curdir_usersite_fails_in_old_python():
|
||||
|
@ -27,6 +35,10 @@ class Tests_UserSite:
|
|||
# --user only works on 2.6 or higher
|
||||
if sys.version_info < (2, 6):
|
||||
raise SkipTest()
|
||||
# --user option is broken in pypy
|
||||
if hasattr(sys, "pypy_version_info"):
|
||||
raise SkipTest()
|
||||
|
||||
|
||||
def test_reset_env_system_site_packages_usersite(self):
|
||||
"""
|
||||
|
@ -58,9 +70,6 @@ class Tests_UserSite:
|
|||
"""
|
||||
Test installing current directory ('.') into usersite after installing distribute
|
||||
"""
|
||||
# FIXME distutils --user option seems to be broken in pypy
|
||||
if hasattr(sys, "pypy_version_info"):
|
||||
raise SkipTest()
|
||||
env = reset_env(use_distribute=True, system_site_packages=True)
|
||||
result = run_pip('install', '--user', '-e',
|
||||
'%s#egg=initools-dev' %
|
||||
|
@ -72,9 +81,6 @@ class Tests_UserSite:
|
|||
"""
|
||||
Test installing current directory ('.') into usersite
|
||||
"""
|
||||
# FIXME distutils --user option seems to be broken in pypy
|
||||
if hasattr(sys, "pypy_version_info"):
|
||||
raise SkipTest()
|
||||
env = reset_env(use_distribute=True, system_site_packages=True)
|
||||
run_from = abspath(join(here, 'packages', 'FSPkg'))
|
||||
result = run_pip('install', '--user', curdir, cwd=run_from, expect_error=False)
|
||||
|
@ -111,15 +117,21 @@ class Tests_UserSite:
|
|||
assert not isfile(initools_v3_file), initools_v3_file
|
||||
|
||||
|
||||
def test_install_user_conflict_in_site(self):
|
||||
def test_install_user_conflict_in_globalsite(self):
|
||||
"""
|
||||
Test user install with conflict in site ignores site and installs to usersite
|
||||
Test user install with conflict in global site ignores site and installs to usersite
|
||||
"""
|
||||
|
||||
#the test framework only supports testing using virtualenvs
|
||||
#this test will use a --system_site_packages virtualenv to achieve the conflict scenario.
|
||||
# the test framework only supports testing using virtualenvs
|
||||
# the sys.path ordering for virtualenvs with --system-site-packages is this: virtualenv-site, user-site, global-site
|
||||
# this test will use 2 modifications to simulate the user-site/global-site relationship
|
||||
# 1) a monkey patch which will make it appear INITools==0.2 is not in in the virtualenv site
|
||||
# if we don't patch this, pip will return an installation error: "Will not install to the usersite because it will lack sys.path precedence..."
|
||||
# 2) adding usersite to PYTHONPATH, so usersite as sys.path precedence over the virtualenv site
|
||||
|
||||
env = reset_env(system_site_packages=True, sitecustomize=patch_dist_in_site_packages)
|
||||
env.environ["PYTHONPATH"] = env.root_path / env.user_site
|
||||
|
||||
env = reset_env(system_site_packages=True)
|
||||
result1 = run_pip('install', 'INITools==0.2')
|
||||
result2 = run_pip('install', '--user', 'INITools==0.1')
|
||||
|
||||
|
@ -136,19 +148,50 @@ class Tests_UserSite:
|
|||
assert isdir(initools_folder)
|
||||
|
||||
|
||||
def test_upgrade_user_conflict_in_globalsite(self):
|
||||
"""
|
||||
Test user install/upgrade with conflict in global site ignores site and installs to usersite
|
||||
"""
|
||||
|
||||
# the test framework only supports testing using virtualenvs
|
||||
# the sys.path ordering for virtualenvs with --system-site-packages is this: virtualenv-site, user-site, global-site
|
||||
# this test will use 2 modifications to simulate the user-site/global-site relationship
|
||||
# 1) a monkey patch which will make it appear INITools==0.2 is not in in the virtualenv site
|
||||
# if we don't patch this, pip will return an installation error: "Will not install to the usersite because it will lack sys.path precedence..."
|
||||
# 2) adding usersite to PYTHONPATH, so usersite as sys.path precedence over the virtualenv site
|
||||
|
||||
env = reset_env(system_site_packages=True, sitecustomize=patch_dist_in_site_packages)
|
||||
env.environ["PYTHONPATH"] = env.root_path / env.user_site
|
||||
|
||||
result1 = run_pip('install', 'INITools==0.2')
|
||||
result2 = run_pip('install', '--user', '--upgrade', 'INITools')
|
||||
|
||||
#usersite has 0.3.1
|
||||
egg_info_folder = env.user_site / 'INITools-0.3.1-py%s.egg-info' % pyversion
|
||||
initools_folder = env.user_site / 'initools'
|
||||
assert egg_info_folder in result2.files_created, str(result2)
|
||||
assert initools_folder in result2.files_created, str(result2)
|
||||
|
||||
#site still has 0.2 (can't look in result1; have to check)
|
||||
egg_info_folder = env.root_path / env.site_packages / 'INITools-0.2-py%s.egg-info' % pyversion
|
||||
initools_folder = env.root_path / env.site_packages / 'initools'
|
||||
assert isdir(egg_info_folder), result2.stdout
|
||||
assert isdir(initools_folder)
|
||||
|
||||
|
||||
def test_install_user_conflict_in_globalsite_and_usersite(self):
|
||||
"""
|
||||
Test user install with conflict in globalsite and usersite ignores global site and updates usersite.
|
||||
"""
|
||||
|
||||
#the test framework only supports testing using virtualenvs
|
||||
#this test will use a --system_site_packages virtualenv to achieve the conflict scenario.
|
||||
# the test framework only supports testing using virtualenvs.
|
||||
# the sys.path ordering for virtualenvs with --system-site-packages is this: virtualenv-site, user-site, global-site.
|
||||
# this test will use 2 modifications to simulate the user-site/global-site relationship
|
||||
# 1) a monkey patch which will make it appear INITools==0.2 is not in in the virtualenv site
|
||||
# if we don't patch this, pip will return an installation error: "Will not install to the usersite because it will lack sys.path precedence..."
|
||||
# 2) adding usersite to PYTHONPATH, so usersite as sys.path precedence over the virtualenv site
|
||||
|
||||
env = reset_env(system_site_packages=True)
|
||||
|
||||
# the sys.path ordering for virtualenvs with --system-site-packages is this: virtualenv site, usersite, global site
|
||||
# given this ordering you *can't* use it to simulate the scenario for this test.
|
||||
# this test will add the usersite to PYTHONPATH to simulate the desired ordering
|
||||
env = reset_env(system_site_packages=True, sitecustomize=patch_dist_in_site_packages)
|
||||
env.environ["PYTHONPATH"] = env.root_path / env.user_site
|
||||
|
||||
result1 = run_pip('install', 'INITools==0.2')
|
||||
|
@ -166,3 +209,48 @@ class Tests_UserSite:
|
|||
initools_folder = env.root_path / env.site_packages / 'initools'
|
||||
assert isdir(egg_info_folder)
|
||||
assert isdir(initools_folder)
|
||||
|
||||
|
||||
def test_install_user_in_global_virtualenv_with_conflict_fails(self):
|
||||
"""
|
||||
Test user install in --system-site-packages virtualenv with conflict in site fails.
|
||||
"""
|
||||
env = reset_env(system_site_packages=True)
|
||||
result1 = run_pip('install', 'INITools==0.2')
|
||||
result2 = run_pip('install', '--user', 'INITools==0.1', expect_error=True)
|
||||
resultp = env.run('python', '-c', "import pkg_resources; print(pkg_resources.get_distribution('initools').location)")
|
||||
dist_location = resultp.stdout.strip()
|
||||
assert result2.stdout.startswith("Will not install to the user site because it will lack sys.path precedence to %s in %s"
|
||||
%('INITools', dist_location)), result2.stdout
|
||||
|
||||
|
||||
def test_uninstall_from_usersite(self):
|
||||
"""
|
||||
Test uninstall from usersite
|
||||
"""
|
||||
env = reset_env(system_site_packages=True)
|
||||
result1 = run_pip('install', '--user', 'INITools==0.3')
|
||||
result2 = run_pip('uninstall', '-y', 'INITools')
|
||||
assert_all_changes(result1, result2, [env.venv/'build', 'cache'])
|
||||
|
||||
|
||||
def test_uninstall_editable_from_usersite(self):
|
||||
"""
|
||||
Test uninstall editable local user install
|
||||
"""
|
||||
env = reset_env(use_distribute=True, system_site_packages=True)
|
||||
|
||||
#install
|
||||
to_install = abspath(join(here, 'packages', 'FSPkg'))
|
||||
result1 = run_pip('install', '--user', '-e', to_install, expect_error=False)
|
||||
egg_link = env.user_site/'FSPkg.egg-link'
|
||||
assert egg_link in result1.files_created, str(result1.stdout)
|
||||
|
||||
#uninstall
|
||||
result2 = run_pip('uninstall', '-y', 'FSPkg')
|
||||
assert not isfile(env.root_path / egg_link)
|
||||
|
||||
assert_all_changes(result1, result2,
|
||||
[env.venv/'build', 'cache', env.user_site/'easy-install.pth'])
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,148 @@
|
|||
"""
|
||||
util tests
|
||||
|
||||
"""
|
||||
import os
|
||||
import pkg_resources
|
||||
from mock import Mock
|
||||
from nose.tools import eq_
|
||||
from tests.path import Path
|
||||
from pip.util import egg_link_path
|
||||
from pip.util import Inf
|
||||
|
||||
|
||||
class Tests_EgglinkPath:
|
||||
"util.egg_link_path() tests"
|
||||
|
||||
def setup(self):
|
||||
|
||||
project = 'foo'
|
||||
|
||||
self.mock_dist = Mock(project_name=project)
|
||||
self.site_packages = 'SITE_PACKAGES'
|
||||
self.user_site = 'USER_SITE'
|
||||
self.user_site_egglink = os.path.join(self.user_site,'%s.egg-link' % project)
|
||||
self.site_packages_egglink = os.path.join(self.site_packages,'%s.egg-link' % project)
|
||||
|
||||
#patches
|
||||
from pip import util
|
||||
self.old_site_packages = util.site_packages
|
||||
self.mock_site_packages = util.site_packages = 'SITE_PACKAGES'
|
||||
self.old_running_under_virtualenv = util.running_under_virtualenv
|
||||
self.mock_running_under_virtualenv = util.running_under_virtualenv = Mock()
|
||||
self.old_virtualenv_no_global = util.virtualenv_no_global
|
||||
self.mock_virtualenv_no_global = util.virtualenv_no_global = Mock()
|
||||
self.old_user_site = util.user_site
|
||||
self.mock_user_site = util.user_site = self.user_site
|
||||
from os import path
|
||||
self.old_isfile = path.isfile
|
||||
self.mock_isfile = path.isfile = Mock()
|
||||
|
||||
|
||||
def teardown(self):
|
||||
from pip import util
|
||||
util.site_packages = self.old_site_packages
|
||||
util.running_under_virtualenv = self.old_running_under_virtualenv
|
||||
util.virtualenv_no_global = self.old_virtualenv_no_global
|
||||
util.user_site = self.old_user_site
|
||||
from os import path
|
||||
path.isfile = self.old_isfile
|
||||
|
||||
|
||||
def eggLinkInUserSite(self,egglink):
|
||||
return egglink==self.user_site_egglink
|
||||
|
||||
def eggLinkInSitePackages(self,egglink):
|
||||
return egglink==self.site_packages_egglink
|
||||
|
||||
#########################
|
||||
## egglink in usersite ##
|
||||
#########################
|
||||
def test_egglink_in_usersite_notvenv(self):
|
||||
self.mock_virtualenv_no_global.return_value = False
|
||||
self.mock_running_under_virtualenv.return_value = False
|
||||
self.mock_isfile.side_effect = self.eggLinkInUserSite
|
||||
eq_(egg_link_path(self.mock_dist), self.user_site_egglink)
|
||||
|
||||
def test_egglink_in_usersite_venv_noglobal(self):
|
||||
self.mock_virtualenv_no_global.return_value = True
|
||||
self.mock_running_under_virtualenv.return_value = True
|
||||
self.mock_isfile.side_effect = self.eggLinkInUserSite
|
||||
eq_(egg_link_path(self.mock_dist), None)
|
||||
|
||||
def test_egglink_in_usersite_venv_global(self):
|
||||
self.mock_virtualenv_no_global.return_value = False
|
||||
self.mock_running_under_virtualenv.return_value = True
|
||||
self.mock_isfile.side_effect = self.eggLinkInUserSite
|
||||
eq_(egg_link_path(self.mock_dist), self.user_site_egglink)
|
||||
|
||||
#########################
|
||||
## egglink in sitepkgs ##
|
||||
#########################
|
||||
def test_egglink_in_sitepkgs_notvenv(self):
|
||||
self.mock_virtualenv_no_global.return_value = False
|
||||
self.mock_running_under_virtualenv.return_value = False
|
||||
self.mock_isfile.side_effect = self.eggLinkInSitePackages
|
||||
eq_(egg_link_path(self.mock_dist), self.site_packages_egglink)
|
||||
|
||||
def test_egglink_in_sitepkgs_venv_noglobal(self):
|
||||
self.mock_virtualenv_no_global.return_value = True
|
||||
self.mock_running_under_virtualenv.return_value = True
|
||||
self.mock_isfile.side_effect = self.eggLinkInSitePackages
|
||||
eq_(egg_link_path(self.mock_dist), self.site_packages_egglink)
|
||||
|
||||
def test_egglink_in_sitepkgs_venv_global(self):
|
||||
self.mock_virtualenv_no_global.return_value = False
|
||||
self.mock_running_under_virtualenv.return_value = True
|
||||
self.mock_isfile.side_effect = self.eggLinkInSitePackages
|
||||
eq_(egg_link_path(self.mock_dist), self.site_packages_egglink)
|
||||
|
||||
####################################
|
||||
## egglink in usersite & sitepkgs ##
|
||||
####################################
|
||||
def test_egglink_in_both_notvenv(self):
|
||||
self.mock_virtualenv_no_global.return_value = False
|
||||
self.mock_running_under_virtualenv.return_value = False
|
||||
self.mock_isfile.return_value = True
|
||||
eq_(egg_link_path(self.mock_dist), self.user_site_egglink)
|
||||
|
||||
def test_egglink_in_both_venv_noglobal(self):
|
||||
self.mock_virtualenv_no_global.return_value = True
|
||||
self.mock_running_under_virtualenv.return_value = True
|
||||
self.mock_isfile.return_value = True
|
||||
eq_(egg_link_path(self.mock_dist), self.site_packages_egglink)
|
||||
|
||||
def test_egglink_in_both_venv_global(self):
|
||||
self.mock_virtualenv_no_global.return_value = False
|
||||
self.mock_running_under_virtualenv.return_value = True
|
||||
self.mock_isfile.return_value = True
|
||||
eq_(egg_link_path(self.mock_dist), self.site_packages_egglink)
|
||||
|
||||
################
|
||||
## no egglink ##
|
||||
################
|
||||
def test_noegglink_in_sitepkgs_notvenv(self):
|
||||
self.mock_virtualenv_no_global.return_value = False
|
||||
self.mock_running_under_virtualenv.return_value = False
|
||||
self.mock_isfile.return_value = False
|
||||
eq_(egg_link_path(self.mock_dist), None)
|
||||
|
||||
def test_noegglink_in_sitepkgs_venv_noglobal(self):
|
||||
self.mock_virtualenv_no_global.return_value = True
|
||||
self.mock_running_under_virtualenv.return_value = True
|
||||
self.mock_isfile.return_value = False
|
||||
eq_(egg_link_path(self.mock_dist), None)
|
||||
|
||||
def test_noegglink_in_sitepkgs_venv_global(self):
|
||||
self.mock_virtualenv_no_global.return_value = False
|
||||
self.mock_running_under_virtualenv.return_value = True
|
||||
self.mock_isfile.return_value = False
|
||||
eq_(egg_link_path(self.mock_dist), None)
|
||||
|
||||
def test_Inf_greater():
|
||||
"""Test Inf compares greater."""
|
||||
assert Inf > object()
|
||||
|
||||
def test_Inf_equals_Inf():
|
||||
"""Test Inf compares greater."""
|
||||
assert Inf == Inf
|
|
@ -1,4 +1,6 @@
|
|||
import sys
|
||||
from mock import patch
|
||||
from nose import SkipTest
|
||||
from pip.vcs.git import Git
|
||||
from tests.test_pip import (reset_env, run_pip,
|
||||
_create_test_package,)
|
||||
|
@ -87,6 +89,9 @@ def test_check_submodule_addition():
|
|||
Submodules are pulled in on install and updated on upgrade.
|
||||
|
||||
"""
|
||||
# TODO(pnasrat) fix all helpers to do right things with paths on windows.
|
||||
if sys.platform == 'win32':
|
||||
raise SkipTest()
|
||||
env = reset_env()
|
||||
module_path, submodule_path = _create_test_package_with_submodule(env)
|
||||
|
||||
|
|
Loading…
Reference in New Issue