diff --git a/src/pip/_internal/index.py b/src/pip/_internal/index.py index 5dafd1c7e..aac93cdb6 100644 --- a/src/pip/_internal/index.py +++ b/src/pip/_internal/index.py @@ -413,7 +413,9 @@ class CandidateEvaluator(object): return (False, 'No sources permitted for %s' % search.supplied) if not version: - version = _egg_info_matches(egg_info, search.canonical) + version = _extract_version_from_fragment( + egg_info, search.canonical, + ) if not version: return (False, 'Missing project version for %s' % search.supplied) @@ -1117,45 +1119,47 @@ class PackageFinder(object): return result -def _find_name_version_sep(egg_info, canonical_name): +def _find_name_version_sep(fragment, canonical_name): # type: (str, str) -> int """Find the separator's index based on the package's canonical name. - `egg_info` must be an egg info string for the given package, and - `canonical_name` must be the package's canonical name. + :param fragment: A + filename "fragment" (stem) or + egg fragment. + :param canonical_name: The package's canonical name. This function is needed since the canonicalized name does not necessarily have the same length as the egg info's name part. An example:: - >>> egg_info = 'foo__bar-1.0' + >>> fragment = 'foo__bar-1.0' >>> canonical_name = 'foo-bar' - >>> _find_name_version_sep(egg_info, canonical_name) + >>> _find_name_version_sep(fragment, canonical_name) 8 """ # Project name and version must be separated by one single dash. Find all # occurrences of dashes; if the string in front of it matches the canonical # name, this is the one separating the name and version parts. - for i, c in enumerate(egg_info): + for i, c in enumerate(fragment): if c != "-": continue - if canonicalize_name(egg_info[:i]) == canonical_name: + if canonicalize_name(fragment[:i]) == canonical_name: return i - raise ValueError("{} does not match {}".format(egg_info, canonical_name)) + raise ValueError("{} does not match {}".format(fragment, canonical_name)) -def _egg_info_matches(egg_info, canonical_name): +def _extract_version_from_fragment(fragment, canonical_name): # type: (str, str) -> Optional[str] - """Pull the version part out of a string. + """Parse the version string from a + filename + "fragment" (stem) or egg fragment. - :param egg_info: The string to parse. E.g. foo-2.1 + :param fragment: The string to parse. E.g. foo-2.1 :param canonical_name: The canonicalized name of the package this belongs to. """ try: - version_start = _find_name_version_sep(egg_info, canonical_name) + 1 + version_start = _find_name_version_sep(fragment, canonical_name) + 1 except ValueError: return None - version = egg_info[version_start:] + version = fragment[version_start:] if not version: return None return version diff --git a/tests/unit/test_index.py b/tests/unit/test_index.py index 83531d4d2..4c07d052f 100644 --- a/tests/unit/test_index.py +++ b/tests/unit/test_index.py @@ -9,7 +9,7 @@ from pip._internal.download import PipSession from pip._internal.index import ( CandidateEvaluator, HTMLPage, Link, PackageFinder, Search, _check_link_requires_python, _clean_link, _determine_base_url, - _egg_info_matches, _find_name_version_sep, _get_html_page, + _extract_version_from_fragment, _find_name_version_sep, _get_html_page, ) from pip._internal.models.candidate import InstallationCandidate from pip._internal.models.search_scope import SearchScope @@ -510,7 +510,7 @@ def test_secure_origin(location, trusted, expected): @pytest.mark.parametrize( - ("egg_info", "canonical_name", "expected"), + ("fragment", "canonical_name", "expected"), [ # Trivial. ("pip-18.0", "pip", 3), @@ -539,13 +539,13 @@ def test_secure_origin(location, trusted, expected): ("zope.interface-", "zope-interface", 14), ], ) -def test_find_name_version_sep(egg_info, canonical_name, expected): - index = _find_name_version_sep(egg_info, canonical_name) +def test_find_name_version_sep(fragment, canonical_name, expected): + index = _find_name_version_sep(fragment, canonical_name) assert index == expected @pytest.mark.parametrize( - ("egg_info", "canonical_name"), + ("fragment", "canonical_name"), [ # A dash must follow the package name. ("zope.interface4.5.0", "zope-interface"), @@ -554,15 +554,15 @@ def test_find_name_version_sep(egg_info, canonical_name, expected): ("zope.interface", "zope-interface"), ], ) -def test_find_name_version_sep_failure(egg_info, canonical_name): +def test_find_name_version_sep_failure(fragment, canonical_name): with pytest.raises(ValueError) as ctx: - _find_name_version_sep(egg_info, canonical_name) - message = "{} does not match {}".format(egg_info, canonical_name) + _find_name_version_sep(fragment, canonical_name) + message = "{} does not match {}".format(fragment, canonical_name) assert str(ctx.value) == message @pytest.mark.parametrize( - ("egg_info", "canonical_name", "expected"), + ("fragment", "canonical_name", "expected"), [ # Trivial. ("pip-18.0", "pip", "18.0"), @@ -594,8 +594,8 @@ def test_find_name_version_sep_failure(egg_info, canonical_name): ("zope.interface", "zope-interface", None), ], ) -def test_egg_info_matches(egg_info, canonical_name, expected): - version = _egg_info_matches(egg_info, canonical_name) +def test_extract_version_from_fragment(fragment, canonical_name, expected): + version = _extract_version_from_fragment(fragment, canonical_name) assert version == expected