mirror of https://github.com/pypa/pip
Split, simplify, and fix egg_info_matches
This commit is contained in:
parent
83b879b1ec
commit
3368819156
|
@ -0,0 +1 @@
|
|||
Canonicalize sdist file names so they can be matched to a canonicalized package name passed to ``pip install``.
|
|
@ -815,7 +815,7 @@ class PackageFinder(object):
|
|||
return
|
||||
|
||||
if not version:
|
||||
version = egg_info_matches(egg_info, search.supplied, link)
|
||||
version = _egg_info_matches(egg_info, search.canonical, link)
|
||||
if version is None:
|
||||
self._log_skipped_link(
|
||||
link, 'Missing project version for %s' % search.supplied)
|
||||
|
@ -846,33 +846,20 @@ class PackageFinder(object):
|
|||
return InstallationCandidate(search.supplied, version, link)
|
||||
|
||||
|
||||
def egg_info_matches(
|
||||
egg_info, search_name, link,
|
||||
_egg_info_re=re.compile(r'([a-z0-9_.]+)-([a-z0-9_.!+-]+)', re.I)):
|
||||
def _egg_info_matches(egg_info, canonical_name, link):
|
||||
"""Pull the version part out of a string.
|
||||
|
||||
:param egg_info: The string to parse. E.g. foo-2.1
|
||||
:param search_name: The name of the package this belongs to. None to
|
||||
infer the name. Note that this cannot unambiguously parse strings
|
||||
like foo-2-2 which might be foo, 2-2 or foo-2, 2.
|
||||
:param canonical_name: The canonicalized name of the package this
|
||||
belongs to.
|
||||
:param link: The link the string came from, for logging on failure.
|
||||
"""
|
||||
match = _egg_info_re.search(egg_info)
|
||||
if not match:
|
||||
logger.debug('Could not parse version from link: %s', link)
|
||||
if not canonicalize_name(egg_info).startswith(canonical_name):
|
||||
return None
|
||||
if search_name is None:
|
||||
full_match = match.group(0)
|
||||
return full_match.split('-', 1)[-1]
|
||||
name = match.group(0).lower()
|
||||
# To match the "safe" name that pkg_resources creates:
|
||||
name = name.replace('_', '-')
|
||||
# project name and version must be separated by a dash
|
||||
look_for = search_name.lower() + "-"
|
||||
if name.startswith(look_for):
|
||||
return match.group(0)[len(look_for):]
|
||||
else:
|
||||
# Project name and version must be separated by a dash.
|
||||
if egg_info[len(canonical_name)] != "-":
|
||||
return None
|
||||
return egg_info[(len(canonical_name) + 1):]
|
||||
|
||||
|
||||
def _determine_base_url(document, page_url):
|
||||
|
|
|
@ -620,6 +620,15 @@ class Wheel(object):
|
|||
return bool(set(tags).intersection(self.file_tags))
|
||||
|
||||
|
||||
def _contains_egg_info(
|
||||
s, _egg_info_re=re.compile(r'([a-z0-9_.]+)-([a-z0-9_.!+-]+)', re.I)):
|
||||
"""Determine whether the string looks like an egg_info.
|
||||
|
||||
:param s: The string to parse. E.g. foo-2.1
|
||||
"""
|
||||
return bool(_egg_info_re.search(s))
|
||||
|
||||
|
||||
class WheelBuilder(object):
|
||||
"""Build wheels from a RequirementSet."""
|
||||
|
||||
|
@ -712,7 +721,6 @@ class WheelBuilder(object):
|
|||
newly built wheel, in preparation for installation.
|
||||
:return: True if all the wheels built correctly.
|
||||
"""
|
||||
from pip._internal import index
|
||||
from pip._internal.models.link import Link
|
||||
|
||||
building_is_possible = self._wheel_dir or (
|
||||
|
@ -742,7 +750,7 @@ class WheelBuilder(object):
|
|||
if autobuilding:
|
||||
link = req.link
|
||||
base, ext = link.splitext()
|
||||
if index.egg_info_matches(base, None, link) is None:
|
||||
if not _contains_egg_info(base):
|
||||
# E.g. local directory. Build wheel just for this run.
|
||||
ephem_cache = True
|
||||
if "binary" not in format_control.get_allowed_formats(
|
||||
|
|
|
@ -7,7 +7,8 @@ from pip._vendor import html5lib, requests
|
|||
|
||||
from pip._internal.download import PipSession
|
||||
from pip._internal.index import (
|
||||
Link, PackageFinder, _determine_base_url, _get_html_page, egg_info_matches,
|
||||
Link, PackageFinder, _determine_base_url, _egg_info_matches,
|
||||
_get_html_page,
|
||||
)
|
||||
|
||||
|
||||
|
@ -165,32 +166,29 @@ def test_get_formatted_locations_basic_auth():
|
|||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("egg_info", "search_name", "expected"),
|
||||
("egg_info", "canonical_name", "expected"),
|
||||
[
|
||||
# Trivial.
|
||||
("pip-18.0", "pip", "18.0"),
|
||||
("pip-18.0", None, "18.0"),
|
||||
("zope-interface-4.5.0", "zope-interface", "4.5.0"),
|
||||
|
||||
# Non-canonical names.
|
||||
# Canonicalized name match non-canonicalized egg info. (pypa/pip#5870)
|
||||
("Jinja2-2.10", "jinja2", "2.10"),
|
||||
("jinja2-2.10", "Jinja2", "2.10"),
|
||||
("zope.interface-4.5.0", "zope-interface", "4.5.0"),
|
||||
("zope_interface-4.5.0", "zope-interface", "4.5.0"),
|
||||
|
||||
# Ambiguous names. Should be smart enough if the package name is
|
||||
# provided, otherwise make a guess.
|
||||
# Should be smart enough to parse ambiguous names from the provided
|
||||
# package name.
|
||||
("foo-2-2", "foo", "2-2"),
|
||||
("foo-2-2", "foo-2", "2"),
|
||||
("foo-2-2", None, "2-2"),
|
||||
("im-valid", None, "valid"),
|
||||
|
||||
# Invalid names.
|
||||
("invalid", None, None),
|
||||
("im_invalid", None, None),
|
||||
# Invalid.
|
||||
("the-package-name-8.19", "does-not-match", None),
|
||||
],
|
||||
)
|
||||
def test_egg_info_matches(egg_info, search_name, expected):
|
||||
def test_egg_info_matches(egg_info, canonical_name, expected):
|
||||
link = None # Only used for reporting.
|
||||
version = egg_info_matches(egg_info, search_name, link)
|
||||
version = _egg_info_matches(egg_info, canonical_name, link)
|
||||
assert version == expected
|
||||
|
||||
|
||||
|
|
|
@ -13,6 +13,26 @@ from pip._internal.utils.misc import unpack_file
|
|||
from tests.lib import DATA_DIR
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"s, expected",
|
||||
[
|
||||
# Trivial.
|
||||
("pip-18.0", True),
|
||||
|
||||
# Ambiguous.
|
||||
("foo-2-2", True),
|
||||
("im-valid", True),
|
||||
|
||||
# Invalid.
|
||||
("invalid", False),
|
||||
("im_invalid", False),
|
||||
],
|
||||
)
|
||||
def test_contains_egg_info(s, expected):
|
||||
result = wheel._contains_egg_info(s)
|
||||
assert result == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize("console_scripts",
|
||||
["pip = pip._internal.main:pip",
|
||||
"pip:pip = pip._internal.main:pip"])
|
||||
|
|
Loading…
Reference in New Issue