summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Jerdonek <chris.jerdonek@gmail.com>2019-05-25 11:48:51 -0700
committerChris Jerdonek <chris.jerdonek@gmail.com>2019-05-28 03:05:14 -0700
commit798d814629440d73256d12d0e5dc2544310af342 (patch)
tree82adf63cfdd1f7738f9989e0c937efa19ed47568
parentfada348b0085d71da5d3161a868a6fcc41da4bd9 (diff)
downloadpip-798d814629440d73256d12d0e5dc2544310af342.tar.gz
Change PackageFinder to use Tuple[int, ...] instead of List[str] for --python-version.
-rw-r--r--src/pip/_internal/cli/base_command.py4
-rw-r--r--src/pip/_internal/cli/cmdoptions.py27
-rw-r--r--src/pip/_internal/commands/download.py7
-rw-r--r--src/pip/_internal/commands/install.py7
-rw-r--r--src/pip/_internal/index.py15
-rw-r--r--src/pip/_internal/pep425tags.py6
-rw-r--r--tests/unit/test_cmdoptions.py15
-rw-r--r--tests/unit/test_index.py30
-rw-r--r--tests/unit/test_pep425tags.py15
9 files changed, 106 insertions, 20 deletions
diff --git a/src/pip/_internal/cli/base_command.py b/src/pip/_internal/cli/base_command.py
index 8d71edc6f..959b82a1c 100644
--- a/src/pip/_internal/cli/base_command.py
+++ b/src/pip/_internal/cli/base_command.py
@@ -324,7 +324,7 @@ class RequirementCommand(Command):
options, # type: Values
session, # type: PipSession
platform=None, # type: Optional[str]
- python_versions=None, # type: Optional[List[str]]
+ py_version_info=None, # type: Optional[Tuple[int, ...]]
abi=None, # type: Optional[str]
implementation=None, # type: Optional[str]
ignore_requires_python=None, # type: Optional[bool]
@@ -352,7 +352,7 @@ class RequirementCommand(Command):
allow_all_prereleases=options.pre,
session=session,
platform=platform,
- versions=python_versions,
+ py_version_info=py_version_info,
abi=abi,
implementation=implementation,
prefer_binary=options.prefer_binary,
diff --git a/src/pip/_internal/cli/cmdoptions.py b/src/pip/_internal/cli/cmdoptions.py
index 96c1bbdbf..f5d20dd4f 100644
--- a/src/pip/_internal/cli/cmdoptions.py
+++ b/src/pip/_internal/cli/cmdoptions.py
@@ -24,7 +24,7 @@ from pip._internal.utils.typing import MYPY_CHECK_RUNNING
from pip._internal.utils.ui import BAR_TYPES
if MYPY_CHECK_RUNNING:
- from typing import Any, Callable, Dict, Optional
+ from typing import Any, Callable, Dict, Optional, Tuple
from optparse import OptionParser, Values
from pip._internal.cli.parser import ConfigOptionParser
@@ -478,11 +478,36 @@ platform = partial(
) # type: Callable[..., Option]
+# This was made a separate function for unit-testing purposes.
+def _convert_python_version(value):
+ # type: (str) -> Tuple[int, ...]
+ """
+ Convert a string like "3" or "34" into a tuple of ints.
+ """
+ if len(value) == 1:
+ parts = [value]
+ else:
+ parts = [value[0], value[1:]]
+
+ return tuple(int(part) for part in parts)
+
+
+def _handle_python_version(option, opt_str, value, parser):
+ # type: (Option, str, str, OptionParser) -> None
+ """
+ Convert a string like "3" or "34" into a tuple of ints.
+ """
+ version_info = _convert_python_version(value)
+ parser.values.python_version = version_info
+
+
python_version = partial(
Option,
'--python-version',
dest='python_version',
metavar='python_version',
+ action='callback',
+ callback=_handle_python_version, type='str',
default=None,
help=("Only use wheels compatible with Python "
"interpreter version <version>. If not specified, then the "
diff --git a/src/pip/_internal/commands/download.py b/src/pip/_internal/commands/download.py
index a5e9b840f..b2c9ce49e 100644
--- a/src/pip/_internal/commands/download.py
+++ b/src/pip/_internal/commands/download.py
@@ -88,11 +88,6 @@ class DownloadCommand(RequirementCommand):
# of the RequirementSet code require that property.
options.editables = []
- if options.python_version:
- python_versions = [options.python_version]
- else:
- python_versions = None
-
cmdoptions.check_dist_restriction(options)
options.src_dir = os.path.abspath(options.src_dir)
@@ -105,7 +100,7 @@ class DownloadCommand(RequirementCommand):
options=options,
session=session,
platform=options.platform,
- python_versions=python_versions,
+ py_version_info=options.python_version,
abi=options.abi,
implementation=options.implementation,
)
diff --git a/src/pip/_internal/commands/install.py b/src/pip/_internal/commands/install.py
index a646991bb..6898cb276 100644
--- a/src/pip/_internal/commands/install.py
+++ b/src/pip/_internal/commands/install.py
@@ -251,11 +251,6 @@ class InstallCommand(RequirementCommand):
cmdoptions.check_dist_restriction(options, check_target=True)
- if options.python_version:
- python_versions = [options.python_version]
- else:
- python_versions = None
-
options.src_dir = os.path.abspath(options.src_dir)
install_options = options.install_options or []
if options.use_user_site:
@@ -294,7 +289,7 @@ class InstallCommand(RequirementCommand):
options=options,
session=session,
platform=options.platform,
- python_versions=python_versions,
+ py_version_info=options.python_version,
abi=options.abi,
implementation=options.implementation,
ignore_requires_python=options.ignore_requires_python,
diff --git a/src/pip/_internal/index.py b/src/pip/_internal/index.py
index 5b42a7c72..88c409e19 100644
--- a/src/pip/_internal/index.py
+++ b/src/pip/_internal/index.py
@@ -29,7 +29,7 @@ from pip._internal.models.candidate import InstallationCandidate
from pip._internal.models.format_control import FormatControl
from pip._internal.models.index import PyPI
from pip._internal.models.link import Link
-from pip._internal.pep425tags import get_supported
+from pip._internal.pep425tags import get_supported, version_info_to_nodot
from pip._internal.utils.compat import ipaddress
from pip._internal.utils.logging import indent_log
from pip._internal.utils.misc import (
@@ -604,7 +604,7 @@ class PackageFinder(object):
session=None, # type: Optional[PipSession]
format_control=None, # type: Optional[FormatControl]
platform=None, # type: Optional[str]
- versions=None, # type: Optional[List[str]]
+ py_version_info=None, # type: Optional[Tuple[int, ...]]
abi=None, # type: Optional[str]
implementation=None, # type: Optional[str]
prefer_binary=False, # type: bool
@@ -624,8 +624,10 @@ class PackageFinder(object):
packages that can be built on the platform passed in. These
packages will only be downloaded for distribution: they will
not be built locally.
- :param versions: A list of strings or None. This is passed directly
- to pep425tags.py in the get_supported() method.
+ :param py_version_info: An optional tuple of ints representing the
+ Python version information to use (e.g. `sys.version_info[:3]`).
+ This can have length 1, 2, or 3. This is used to construct the
+ value passed to pep425tags.py's get_supported() function.
:param abi: A string or None. This is passed directly
to pep425tags.py in the get_supported() method.
:param implementation: A string or None. This is passed directly
@@ -659,6 +661,11 @@ class PackageFinder(object):
for host in (trusted_hosts if trusted_hosts else [])
] # type: List[SecureOrigin]
+ if py_version_info:
+ versions = [version_info_to_nodot(py_version_info)]
+ else:
+ versions = None
+
# The valid tags to check potential found wheel candidates against
valid_tags = get_supported(
versions=versions,
diff --git a/src/pip/_internal/pep425tags.py b/src/pip/_internal/pep425tags.py
index 3b68f28d2..07dc148ee 100644
--- a/src/pip/_internal/pep425tags.py
+++ b/src/pip/_internal/pep425tags.py
@@ -49,6 +49,12 @@ def get_abbr_impl():
return pyimpl
+def version_info_to_nodot(version_info):
+ # type: (Tuple[int, ...]) -> str
+ # Only use up to the first two numbers.
+ return ''.join(map(str, version_info[:2]))
+
+
def get_impl_ver():
# type: () -> str
"""Return implementation version."""
diff --git a/tests/unit/test_cmdoptions.py b/tests/unit/test_cmdoptions.py
new file mode 100644
index 000000000..8f0a2f075
--- /dev/null
+++ b/tests/unit/test_cmdoptions.py
@@ -0,0 +1,15 @@
+import pytest
+
+from pip._internal.cli.cmdoptions import _convert_python_version
+
+
+@pytest.mark.parametrize('value, expected', [
+ ('2', (2,)),
+ ('3', (3,)),
+ ('34', (3, 4)),
+ # Test a 2-digit minor version.
+ ('310', (3, 10)),
+])
+def test_convert_python_version(value, expected):
+ actual = _convert_python_version(value)
+ assert actual == expected
diff --git a/tests/unit/test_index.py b/tests/unit/test_index.py
index 094c23af4..513826d61 100644
--- a/tests/unit/test_index.py
+++ b/tests/unit/test_index.py
@@ -3,7 +3,7 @@ import os.path
import sys
import pytest
-from mock import Mock
+from mock import Mock, patch
from pip._vendor import html5lib, requests
from pip._internal.download import PipSession
@@ -149,6 +149,34 @@ class TestCandidateEvaluator:
assert actual == expected
+class TestPackageFinder:
+
+ @pytest.mark.parametrize('version_info, expected', [
+ ((2,), ['2']),
+ ((3,), ['3']),
+ ((3, 6,), ['36']),
+ # Test a tuple of length 3.
+ ((3, 6, 5), ['36']),
+ # Test a 2-digit minor version.
+ ((3, 10), ['310']),
+ # Test falsey values.
+ (None, None),
+ ((), None),
+ ])
+ @patch('pip._internal.index.get_supported')
+ def test_create__py_version_info(
+ self, mock_get_supported, version_info, expected,
+ ):
+ """
+ Test that the py_version_info argument is handled correctly.
+ """
+ PackageFinder.create(
+ [], [], py_version_info=version_info, session=object(),
+ )
+ actual = mock_get_supported.call_args[1]['versions']
+ assert actual == expected
+
+
def test_sort_locations_file_expand_dir(data):
"""
Test that a file:// dir gets listdir run with expand_dir
diff --git a/tests/unit/test_pep425tags.py b/tests/unit/test_pep425tags.py
index 03dbac87f..f570de621 100644
--- a/tests/unit/test_pep425tags.py
+++ b/tests/unit/test_pep425tags.py
@@ -6,6 +6,21 @@ from mock import patch
from pip._internal import pep425tags
+@pytest.mark.parametrize('version_info, expected', [
+ ((2,), '2'),
+ ((2, 8), '28'),
+ ((3,), '3'),
+ ((3, 6), '36'),
+ # Test a tuple of length 3.
+ ((3, 6, 5), '36'),
+ # Test a 2-digit minor version.
+ ((3, 10), '310'),
+])
+def test_version_info_to_nodot(version_info, expected):
+ actual = pep425tags.version_info_to_nodot(version_info)
+ assert actual == expected
+
+
class TestPEP425Tags(object):
def mock_get_config_var(self, **kwd):