mirror of
https://github.com/pypa/pip
synced 2023-12-13 21:30:23 +01:00
Merge pull request #3085 from patricklaw/add-pip-download-command
Add `pip download` command and deprecate `pip install --download`.
This commit is contained in:
commit
0b1acf9726
|
@ -23,6 +23,9 @@
|
|||
* Allow repository URLs with secure transports to count as trusted. (E.g.,
|
||||
"git+ssh" is okay.) :issue:`2811`.
|
||||
|
||||
* Implement a top-level ``pip download`` command and deprecate
|
||||
``pip install --download``.
|
||||
|
||||
|
||||
**7.1.2 (2015-08-22)**
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ Reference Guide
|
|||
|
||||
pip
|
||||
pip_install
|
||||
pip_download
|
||||
pip_uninstall
|
||||
pip_freeze
|
||||
pip_list
|
||||
|
|
53
docs/reference/pip_download.rst
Normal file
53
docs/reference/pip_download.rst
Normal file
|
@ -0,0 +1,53 @@
|
|||
|
||||
.. _`pip download`:
|
||||
|
||||
pip download
|
||||
------------
|
||||
|
||||
.. contents::
|
||||
|
||||
Usage
|
||||
*****
|
||||
|
||||
.. pip-command-usage:: download
|
||||
|
||||
|
||||
Description
|
||||
***********
|
||||
|
||||
.. pip-command-description:: download
|
||||
|
||||
|
||||
Overview
|
||||
++++++++
|
||||
``pip download`` replaces the ``--download`` option to ``pip install``,
|
||||
which is now deprecated and will be removed in pip 10.
|
||||
|
||||
``pip download`` does the same resolution and downloading as ``pip install``,
|
||||
but instead of installing the dependencies, it collects the downloaded
|
||||
distributions into the directory provided (defaulting to ``./pip_downloads``).
|
||||
This directory can later be passed as the value to
|
||||
``pip install --find-links`` to facilitate offline or locked down package
|
||||
installation.
|
||||
|
||||
|
||||
Options
|
||||
*******
|
||||
|
||||
.. pip-command-options:: download
|
||||
|
||||
.. pip-index-options::
|
||||
|
||||
|
||||
Examples
|
||||
********
|
||||
|
||||
1. Download a package and all of its dependencies
|
||||
|
||||
::
|
||||
|
||||
$ pip download -d ./pip_downloads SomePackage
|
||||
$ pip download SomePackage # equivalent to above
|
||||
$ pip download --no-index --find-links=/tmp/wheelhouse -d /tmp/otherwheelhouse SomePackage
|
||||
|
||||
|
|
@ -7,10 +7,12 @@ import sys
|
|||
import optparse
|
||||
|
||||
from pip import cmdoptions
|
||||
from pip.index import PackageFinder
|
||||
from pip.locations import running_under_virtualenv
|
||||
from pip.download import PipSession
|
||||
from pip.exceptions import (BadCommand, InstallationError, UninstallationError,
|
||||
CommandError, PreviousBuildDirError)
|
||||
|
||||
from pip.compat import logging_dictConfig
|
||||
from pip.baseparser import ConfigOptionParser, UpdatingDefaultsHelpFormatter
|
||||
from pip.req import InstallRequirement, parse_requirements
|
||||
|
@ -290,3 +292,22 @@ class RequirementCommand(Command):
|
|||
msg = ('You must give at least one requirement '
|
||||
'to %(name)s (see "pip help %(name)s")' % opts)
|
||||
logger.warning(msg)
|
||||
|
||||
def _build_package_finder(self, options, session):
|
||||
"""
|
||||
Create a package finder appropriate to this requirement command.
|
||||
"""
|
||||
index_urls = [options.index_url] + options.extra_index_urls
|
||||
if options.no_index:
|
||||
logger.info('Ignoring indexes: %s', ','.join(index_urls))
|
||||
index_urls = []
|
||||
|
||||
return PackageFinder(
|
||||
find_links=options.find_links,
|
||||
format_control=options.format_control,
|
||||
index_urls=index_urls,
|
||||
trusted_hosts=options.trusted_hosts,
|
||||
allow_all_prereleases=options.pre,
|
||||
process_dependency_links=options.process_dependency_links,
|
||||
session=session,
|
||||
)
|
||||
|
|
|
@ -553,18 +553,24 @@ general_group = {
|
|||
]
|
||||
}
|
||||
|
||||
index_group = {
|
||||
non_deprecated_index_group = {
|
||||
'name': 'Package Index Options',
|
||||
'options': [
|
||||
index_url,
|
||||
extra_index_url,
|
||||
no_index,
|
||||
find_links,
|
||||
process_dependency_links,
|
||||
]
|
||||
}
|
||||
|
||||
index_group = {
|
||||
'name': 'Package Index Options (including deprecated options)',
|
||||
'options': non_deprecated_index_group['options'] + [
|
||||
allow_external,
|
||||
allow_all_external,
|
||||
no_allow_external,
|
||||
allow_unsafe,
|
||||
no_allow_unsafe,
|
||||
process_dependency_links,
|
||||
]
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ Package containing all pip commands
|
|||
from __future__ import absolute_import
|
||||
|
||||
from pip.commands.completion import CompletionCommand
|
||||
from pip.commands.download import DownloadCommand
|
||||
from pip.commands.freeze import FreezeCommand
|
||||
from pip.commands.help import HelpCommand
|
||||
from pip.commands.list import ListCommand
|
||||
|
@ -22,6 +23,7 @@ commands_dict = {
|
|||
ShowCommand.name: ShowCommand,
|
||||
InstallCommand.name: InstallCommand,
|
||||
UninstallCommand.name: UninstallCommand,
|
||||
DownloadCommand.name: DownloadCommand,
|
||||
ListCommand.name: ListCommand,
|
||||
WheelCommand.name: WheelCommand,
|
||||
}
|
||||
|
@ -29,6 +31,7 @@ commands_dict = {
|
|||
|
||||
commands_order = [
|
||||
InstallCommand,
|
||||
DownloadCommand,
|
||||
UninstallCommand,
|
||||
FreezeCommand,
|
||||
ListCommand,
|
||||
|
|
135
pip/commands/download.py
Normal file
135
pip/commands/download.py
Normal file
|
@ -0,0 +1,135 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
from pip.req import RequirementSet
|
||||
from pip.basecommand import RequirementCommand
|
||||
from pip import cmdoptions
|
||||
from pip.utils import ensure_dir, normalize_path
|
||||
from pip.utils.build import BuildDirectory
|
||||
from pip.utils.filesystem import check_path_owner
|
||||
|
||||
|
||||
DEFAULT_DOWNLOAD_DIR = os.path.join(normalize_path(os.curdir), 'pip_downloads')
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DownloadCommand(RequirementCommand):
|
||||
"""
|
||||
Download packages from:
|
||||
|
||||
- PyPI (and other indexes) using requirement specifiers.
|
||||
- VCS project urls.
|
||||
- Local project directories.
|
||||
- Local or remote source archives.
|
||||
|
||||
pip also supports downloading from "requirements files", which provide
|
||||
an easy way to specify a whole environment to be downloaded.
|
||||
"""
|
||||
name = 'download'
|
||||
|
||||
usage = """
|
||||
%prog [options] <requirement specifier> [package-index-options] ...
|
||||
%prog [options] -r <requirements file> [package-index-options] ...
|
||||
%prog [options] [-e] <vcs project url> ...
|
||||
%prog [options] [-e] <local project path> ...
|
||||
%prog [options] <archive url/path> ..."""
|
||||
|
||||
summary = 'Download packages.'
|
||||
|
||||
def __init__(self, *args, **kw):
|
||||
super(DownloadCommand, self).__init__(*args, **kw)
|
||||
|
||||
cmd_opts = self.cmd_opts
|
||||
|
||||
cmd_opts.add_option(cmdoptions.constraints())
|
||||
cmd_opts.add_option(cmdoptions.editable())
|
||||
cmd_opts.add_option(cmdoptions.requirements())
|
||||
cmd_opts.add_option(cmdoptions.build_dir())
|
||||
cmd_opts.add_option(cmdoptions.no_deps())
|
||||
cmd_opts.add_option(cmdoptions.global_options())
|
||||
cmd_opts.add_option(cmdoptions.no_binary())
|
||||
cmd_opts.add_option(cmdoptions.only_binary())
|
||||
cmd_opts.add_option(cmdoptions.src())
|
||||
cmd_opts.add_option(cmdoptions.no_clean())
|
||||
cmd_opts.add_option(cmdoptions.pre())
|
||||
|
||||
cmd_opts.add_option(
|
||||
'-d', '--dest', '--destination-dir', '--destination-directory',
|
||||
dest='download_dir',
|
||||
metavar='dir',
|
||||
default=DEFAULT_DOWNLOAD_DIR,
|
||||
help=("Download packages into <dir>."),
|
||||
)
|
||||
|
||||
index_opts = cmdoptions.make_option_group(
|
||||
cmdoptions.non_deprecated_index_group,
|
||||
self.parser,
|
||||
)
|
||||
|
||||
self.parser.insert_option_group(0, index_opts)
|
||||
self.parser.insert_option_group(0, cmd_opts)
|
||||
|
||||
def run(self, options, args):
|
||||
options.ignore_installed = True
|
||||
options.src_dir = os.path.abspath(options.src_dir)
|
||||
ensure_dir(options.download_dir)
|
||||
|
||||
with self._build_session(options) as session:
|
||||
|
||||
finder = self._build_package_finder(options, session)
|
||||
build_delete = (not (options.no_clean or options.build_dir))
|
||||
if options.cache_dir and not check_path_owner(options.cache_dir):
|
||||
logger.warning(
|
||||
"The directory '%s' or its parent directory is not owned "
|
||||
"by the current user and caching wheels has been "
|
||||
"disabled. check the permissions and owner of that "
|
||||
"directory. If executing pip with sudo, you may want "
|
||||
"sudo's -H flag.",
|
||||
options.cache_dir,
|
||||
)
|
||||
options.cache_dir = None
|
||||
|
||||
with BuildDirectory(options.build_dir,
|
||||
delete=build_delete) as build_dir:
|
||||
|
||||
requirement_set = RequirementSet(
|
||||
build_dir=build_dir,
|
||||
src_dir=options.src_dir,
|
||||
download_dir=options.download_dir,
|
||||
ignore_installed=True,
|
||||
ignore_dependencies=options.ignore_dependencies,
|
||||
session=session,
|
||||
isolated=options.isolated_mode,
|
||||
)
|
||||
self.populate_requirement_set(
|
||||
requirement_set,
|
||||
args,
|
||||
options,
|
||||
finder,
|
||||
session,
|
||||
self.name,
|
||||
None
|
||||
)
|
||||
|
||||
if not requirement_set.has_requirements:
|
||||
return
|
||||
|
||||
requirement_set.prepare_files(finder)
|
||||
|
||||
downloaded = ' '.join([
|
||||
req.name for req in requirement_set.successfully_downloaded
|
||||
])
|
||||
if downloaded:
|
||||
logger.info(
|
||||
'Successfully downloaded %s', downloaded
|
||||
)
|
||||
|
||||
# Clean up
|
||||
if not options.no_clean:
|
||||
requirement_set.cleanup_files()
|
||||
|
||||
return requirement_set
|
|
@ -14,7 +14,6 @@ except ImportError:
|
|||
from pip.req import RequirementSet
|
||||
from pip.basecommand import RequirementCommand
|
||||
from pip.locations import virtualenv_no_global, distutils_scheme
|
||||
from pip.index import PackageFinder
|
||||
from pip.exceptions import (
|
||||
InstallationError, CommandError, PreviousBuildDirError,
|
||||
)
|
||||
|
@ -168,22 +167,6 @@ class InstallCommand(RequirementCommand):
|
|||
self.parser.insert_option_group(0, index_opts)
|
||||
self.parser.insert_option_group(0, cmd_opts)
|
||||
|
||||
def _build_package_finder(self, options, index_urls, session):
|
||||
"""
|
||||
Create a package finder appropriate to this install command.
|
||||
This method is meant to be overridden by subclasses, not
|
||||
called directly.
|
||||
"""
|
||||
return PackageFinder(
|
||||
find_links=options.find_links,
|
||||
format_control=options.format_control,
|
||||
index_urls=index_urls,
|
||||
trusted_hosts=options.trusted_hosts,
|
||||
allow_all_prereleases=options.pre,
|
||||
process_dependency_links=options.process_dependency_links,
|
||||
session=session,
|
||||
)
|
||||
|
||||
def run(self, options, args):
|
||||
cmdoptions.resolve_wheel_no_use_binary(options)
|
||||
cmdoptions.check_install_build_global(options)
|
||||
|
@ -213,6 +196,12 @@ class InstallCommand(RequirementCommand):
|
|||
)
|
||||
|
||||
if options.download_dir:
|
||||
warnings.warn(
|
||||
"pip install --download has been deprecated and will be "
|
||||
"removed in the future. Pip now has a download command that "
|
||||
"should be used instead.",
|
||||
RemovedInPip10Warning,
|
||||
)
|
||||
options.ignore_installed = True
|
||||
|
||||
if options.build_dir:
|
||||
|
@ -243,14 +232,10 @@ class InstallCommand(RequirementCommand):
|
|||
install_options.append('--home=' + temp_target_dir)
|
||||
|
||||
global_options = options.global_options or []
|
||||
index_urls = [options.index_url] + options.extra_index_urls
|
||||
if options.no_index:
|
||||
logger.info('Ignoring indexes: %s', ','.join(index_urls))
|
||||
index_urls = []
|
||||
|
||||
with self._build_session(options) as session:
|
||||
|
||||
finder = self._build_package_finder(options, index_urls, session)
|
||||
finder = self._build_package_finder(options, session)
|
||||
build_delete = (not (options.no_clean or options.build_dir))
|
||||
wheel_cache = WheelCache(options.cache_dir, options.format_control)
|
||||
if options.cache_dir and not check_path_owner(options.cache_dir):
|
||||
|
|
|
@ -6,7 +6,6 @@ import os
|
|||
import warnings
|
||||
|
||||
from pip.basecommand import RequirementCommand
|
||||
from pip.index import PackageFinder
|
||||
from pip.exceptions import CommandError, PreviousBuildDirError
|
||||
from pip.req import RequirementSet
|
||||
from pip.utils import import_or_raise, normalize_path
|
||||
|
@ -161,16 +160,7 @@ class WheelCommand(RequirementCommand):
|
|||
|
||||
with self._build_session(options) as session:
|
||||
|
||||
finder = PackageFinder(
|
||||
find_links=options.find_links,
|
||||
format_control=options.format_control,
|
||||
index_urls=index_urls,
|
||||
allow_all_prereleases=options.pre,
|
||||
trusted_hosts=options.trusted_hosts,
|
||||
process_dependency_links=options.process_dependency_links,
|
||||
session=session,
|
||||
)
|
||||
|
||||
finder = self._build_package_finder(options, session)
|
||||
build_delete = (not (options.no_clean or options.build_dir))
|
||||
wheel_cache = WheelCache(options.cache_dir, options.format_control)
|
||||
with BuildDirectory(options.build_dir,
|
||||
|
|
162
tests/functional/test_download.py
Normal file
162
tests/functional/test_download.py
Normal file
|
@ -0,0 +1,162 @@
|
|||
import os
|
||||
import textwrap
|
||||
import pytest
|
||||
|
||||
from tests.lib.path import Path
|
||||
|
||||
|
||||
@pytest.mark.network
|
||||
def test_download_if_requested(script):
|
||||
"""
|
||||
It should download (in the scratch path) and not install if requested.
|
||||
"""
|
||||
result = script.pip(
|
||||
'download', '-d', '.', 'INITools==0.1', expect_error=True
|
||||
)
|
||||
assert Path('scratch') / 'INITools-0.1.tar.gz' in result.files_created
|
||||
assert script.site_packages / 'initools' not in result.files_created
|
||||
|
||||
|
||||
@pytest.mark.network
|
||||
def test_download_setuptools(script):
|
||||
"""
|
||||
It should download (in the scratch path) and not install if requested.
|
||||
"""
|
||||
result = script.pip('download', 'setuptools')
|
||||
setuptools_prefix = str(
|
||||
Path('scratch') / 'pip_downloads' / 'setuptools'
|
||||
)
|
||||
assert any(
|
||||
path.startswith(setuptools_prefix) for path in result.files_created
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.network
|
||||
def test_download_wheel(script):
|
||||
"""
|
||||
Test using "pip download" to download a *.whl archive.
|
||||
FIXME: this test could use a local --find-links dir, but -d with local
|
||||
--find-links has a bug https://github.com/pypa/pip/issues/1111
|
||||
"""
|
||||
result = script.pip(
|
||||
'download',
|
||||
'-f', 'https://bitbucket.org/pypa/pip-test-package/downloads',
|
||||
'-d', '.', 'pip-test-package'
|
||||
)
|
||||
assert (
|
||||
Path('scratch') / 'pip_test_package-0.1.1-py2.py3-none-any.whl'
|
||||
in result.files_created
|
||||
)
|
||||
assert script.site_packages / 'piptestpackage' not in result.files_created
|
||||
|
||||
|
||||
@pytest.mark.network
|
||||
def test_single_download_from_requirements_file(script):
|
||||
"""
|
||||
It should support download (in the scratch path) from PyPi from a
|
||||
requirements file
|
||||
"""
|
||||
script.scratch_path.join("test-req.txt").write(textwrap.dedent("""
|
||||
INITools==0.1
|
||||
"""))
|
||||
result = script.pip(
|
||||
'download', '-r', script.scratch_path / 'test-req.txt', '-d', '.',
|
||||
expect_error=True,
|
||||
)
|
||||
assert Path('scratch') / 'INITools-0.1.tar.gz' in result.files_created
|
||||
assert script.site_packages / 'initools' not in result.files_created
|
||||
|
||||
|
||||
@pytest.mark.network
|
||||
def test_download_should_download_dependencies(script):
|
||||
"""
|
||||
It should download dependencies (in the scratch path)
|
||||
"""
|
||||
result = script.pip(
|
||||
'download', 'Paste[openid]==1.7.5.1', '-d', '.', expect_error=True,
|
||||
)
|
||||
assert Path('scratch') / 'Paste-1.7.5.1.tar.gz' in result.files_created
|
||||
openid_tarball_prefix = str(Path('scratch') / 'python-openid-')
|
||||
assert any(
|
||||
path.startswith(openid_tarball_prefix) for path in result.files_created
|
||||
)
|
||||
assert script.site_packages / 'openid' not in result.files_created
|
||||
|
||||
|
||||
def test_download_wheel_archive(script, data):
|
||||
"""
|
||||
It should download a wheel archive path
|
||||
"""
|
||||
wheel_filename = 'colander-0.9.9-py2.py3-none-any.whl'
|
||||
wheel_path = os.path.join(data.find_links, wheel_filename)
|
||||
result = script.pip(
|
||||
'download', wheel_path,
|
||||
'-d', '.', '--no-deps'
|
||||
)
|
||||
assert Path('scratch') / wheel_filename in result.files_created
|
||||
|
||||
|
||||
def test_download_should_download_wheel_deps(script, data):
|
||||
"""
|
||||
It should download dependencies for wheels(in the scratch path)
|
||||
"""
|
||||
wheel_filename = 'colander-0.9.9-py2.py3-none-any.whl'
|
||||
dep_filename = 'translationstring-1.1.tar.gz'
|
||||
wheel_path = os.path.join(data.find_links, wheel_filename)
|
||||
result = script.pip(
|
||||
'download', wheel_path,
|
||||
'-d', '.', '--find-links', data.find_links, '--no-index'
|
||||
)
|
||||
assert Path('scratch') / wheel_filename in result.files_created
|
||||
assert Path('scratch') / dep_filename in result.files_created
|
||||
|
||||
|
||||
@pytest.mark.network
|
||||
def test_download_should_skip_existing_files(script):
|
||||
"""
|
||||
It should not download files already existing in the scratch dir
|
||||
"""
|
||||
script.scratch_path.join("test-req.txt").write(textwrap.dedent("""
|
||||
INITools==0.1
|
||||
"""))
|
||||
|
||||
result = script.pip(
|
||||
'download', '-r', script.scratch_path / 'test-req.txt', '-d', '.',
|
||||
expect_error=True,
|
||||
)
|
||||
assert Path('scratch') / 'INITools-0.1.tar.gz' in result.files_created
|
||||
assert script.site_packages / 'initools' not in result.files_created
|
||||
|
||||
# adding second package to test-req.txt
|
||||
script.scratch_path.join("test-req.txt").write(textwrap.dedent("""
|
||||
INITools==0.1
|
||||
python-openid==2.2.5
|
||||
"""))
|
||||
|
||||
# only the second package should be downloaded
|
||||
result = script.pip(
|
||||
'download', '-r', script.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 script.site_packages / 'initools' not in result.files_created
|
||||
assert script.site_packages / 'openid' not in result.files_created
|
||||
|
||||
|
||||
@pytest.mark.network
|
||||
def test_download_vcs_link(script):
|
||||
"""
|
||||
It should allow -d flag for vcs links, regression test for issue #798.
|
||||
"""
|
||||
result = script.pip(
|
||||
'download', '-d', '.', 'git+git://github.com/pypa/pip-test-package.git'
|
||||
)
|
||||
assert (
|
||||
Path('scratch') / 'pip-test-package-0.1.1.zip'
|
||||
in result.files_created
|
||||
)
|
||||
assert script.site_packages / 'piptestpackage' not in result.files_created
|
|
@ -111,6 +111,7 @@ def test_download_editable_to_custom_path(script, tmpdir):
|
|||
'customsrc',
|
||||
'--download',
|
||||
'customdl',
|
||||
expect_stderr=True
|
||||
)
|
||||
customsrc = Path('scratch') / 'customsrc' / 'initools'
|
||||
assert customsrc in result.files_created, (
|
||||
|
@ -126,6 +127,9 @@ def test_download_editable_to_custom_path(script, tmpdir):
|
|||
if filename.startswith(customdl)
|
||||
]
|
||||
assert customdl_files_created
|
||||
assert ('DEPRECATION: pip install --download has been deprecated and will '
|
||||
'be removed in the future. Pip now has a download command that '
|
||||
'should be used instead.') in result.stderr
|
||||
|
||||
|
||||
@pytest.mark.network
|
||||
|
|
|
@ -27,7 +27,8 @@ def test_download_wheel(script):
|
|||
result = script.pip(
|
||||
'install',
|
||||
'-f', 'https://bitbucket.org/pypa/pip-test-package/downloads',
|
||||
'-d', '.', 'pip-test-package'
|
||||
'-d', '.', 'pip-test-package',
|
||||
expect_stderr=True,
|
||||
)
|
||||
assert (
|
||||
Path('scratch') / 'pip_test_package-0.1.1-py2.py3-none-any.whl'
|
||||
|
@ -77,7 +78,8 @@ def test_download_wheel_archive(script, data):
|
|||
wheel_path = os.path.join(data.find_links, wheel_filename)
|
||||
result = script.pip(
|
||||
'install', wheel_path,
|
||||
'-d', '.', '--no-deps'
|
||||
'-d', '.', '--no-deps',
|
||||
expect_stderr=True,
|
||||
)
|
||||
assert Path('scratch') / wheel_filename in result.files_created
|
||||
|
||||
|
@ -91,7 +93,8 @@ def test_download_should_download_wheel_deps(script, data):
|
|||
wheel_path = os.path.join(data.find_links, wheel_filename)
|
||||
result = script.pip(
|
||||
'install', wheel_path,
|
||||
'-d', '.', '--find-links', data.find_links, '--no-index'
|
||||
'-d', '.', '--find-links', data.find_links, '--no-index',
|
||||
expect_stderr=True,
|
||||
)
|
||||
assert Path('scratch') / wheel_filename in result.files_created
|
||||
assert Path('scratch') / dep_filename in result.files_created
|
||||
|
@ -139,7 +142,8 @@ def test_download_vcs_link(script):
|
|||
It should allow -d flag for vcs links, regression test for issue #798.
|
||||
"""
|
||||
result = script.pip(
|
||||
'install', '-d', '.', 'git+git://github.com/pypa/pip-test-package.git'
|
||||
'install', '-d', '.', 'git+git://github.com/pypa/pip-test-package.git',
|
||||
expect_stderr=True,
|
||||
)
|
||||
assert (
|
||||
Path('scratch') / 'pip-test-package-0.1.1.zip'
|
||||
|
|
|
@ -329,7 +329,7 @@ class PipTestEnvironment(scripttest.TestFileEnvironment):
|
|||
# about the lack of an SSLContext. Expect it when running commands
|
||||
# that will touch the outside world.
|
||||
if (pyversion_tuple < (2, 7, 9) and
|
||||
args and args[0] in ('search', 'install')):
|
||||
args and args[0] in ('search', 'install', 'download')):
|
||||
kwargs['expect_stderr'] = True
|
||||
|
||||
return self.run("pip", *args, **kwargs)
|
||||
|
|
Loading…
Reference in a new issue