Skip to content

Commit

Permalink
(joe) requirement creation is very expensive, and at least in my test…
Browse files Browse the repository at this point in the history
… case there were only ~200 unique requirement objects created in ~5-10 minutes of resolution time
  • Loading branch information
jbylund committed Oct 6, 2021
1 parent 0981e07 commit dba95e8
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 4 deletions.
14 changes: 10 additions & 4 deletions src/pip/_internal/req/constructors.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
InstallRequirement.
"""

import functools
import logging
import os
import re
Expand Down Expand Up @@ -39,6 +40,11 @@
operators = Specifier._operators.keys()


@functools.lru_cache(maxsize=None)
def get_or_create_requirement(req_string: str) -> Requirement:
return Requirement(req_string)


def _strip_extras(path: str) -> Tuple[str, Optional[str]]:
m = re.match(r"^(.+)(\[[^\]]+\])$", path)
extras = None
Expand All @@ -54,7 +60,7 @@ def _strip_extras(path: str) -> Tuple[str, Optional[str]]:
def convert_extras(extras: Optional[str]) -> Set[str]:
if not extras:
return set()
return Requirement("placeholder" + extras.lower()).extras
return get_or_create_requirement("placeholder" + extras.lower()).extras


def parse_editable(editable_req: str) -> Tuple[Optional[str], str, Set[str]]:
Expand Down Expand Up @@ -83,7 +89,7 @@ def parse_editable(editable_req: str) -> Tuple[Optional[str], str, Set[str]]:
return (
package_name,
url_no_extras,
Requirement("placeholder" + extras.lower()).extras,
get_or_create_requirement("placeholder" + extras.lower()).extras,
)
else:
return package_name, url_no_extras, set()
Expand Down Expand Up @@ -309,7 +315,7 @@ def with_source(text: str) -> str:

def _parse_req_string(req_as_string: str) -> Requirement:
try:
req = Requirement(req_as_string)
req = get_or_create_requirement(req_as_string)
except InvalidRequirement:
if os.path.sep in req_as_string:
add_msg = "It looks like a path."
Expand Down Expand Up @@ -386,7 +392,7 @@ def install_req_from_req_string(
user_supplied: bool = False,
) -> InstallRequirement:
try:
req = Requirement(req_string)
req = get_or_create_requirement(req_string)
except InvalidRequirement:
raise InstallationError(f"Invalid requirement: '{req_string}'")

Expand Down
6 changes: 6 additions & 0 deletions tests/unit/test_req.py
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,12 @@ def test_parse_editable_local_extras(
{"bar", "baz"},
)

def test_get_or_create_caching() -> None:
"""test caching of get_or_create requirement"""
teststr = "affinegap==1.10"
assert get_or_create_requirement(teststr) == Requirement(teststr)
assert not(get_or_create_requirement(teststr) is Requirement(teststr))
assert get_or_create_requirement(teststr) is get_or_create_requirement(teststr)

def test_exclusive_environment_markers() -> None:
"""Make sure RequirementSet accepts several excluding env markers"""
Expand Down

0 comments on commit dba95e8

Please sign in to comment.