Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

performance: cache parsed markers, constraints and versions #556

Merged
merged 3 commits into from
Feb 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ repos:
args: [--all]

- repo: https://github.com/pycqa/isort
rev: 5.10.1
rev: 5.12.0
hooks:
- id: isort
args: [--add-import, from __future__ import annotations]
Expand Down
2 changes: 2 additions & 0 deletions src/poetry/core/constraints/generic/parser.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import functools
import re

from typing import TYPE_CHECKING
Expand All @@ -17,6 +18,7 @@
BASIC_CONSTRAINT = re.compile(r"^(!?==?)?\s*([^\s]+?)\s*$")


@functools.lru_cache(maxsize=None)
def parse_constraint(constraints: str) -> BaseConstraint:
if constraints == "*":
return AnyConstraint()
Expand Down
2 changes: 2 additions & 0 deletions src/poetry/core/constraints/version/parser.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import functools
import re

from typing import TYPE_CHECKING
Expand All @@ -12,6 +13,7 @@
from poetry.core.constraints.version.version_constraint import VersionConstraint


@functools.lru_cache(maxsize=None)
def parse_constraint(constraints: str) -> VersionConstraint:
if constraints == "*":
from poetry.core.constraints.version.version_range import VersionRange
Expand Down
21 changes: 20 additions & 1 deletion src/poetry/core/version/markers.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from __future__ import annotations

import functools
import itertools
import re

from abc import ABC
from abc import abstractmethod
from typing import TYPE_CHECKING
from typing import Any
from typing import Callable
Expand Down Expand Up @@ -53,10 +56,12 @@ class UndefinedEnvironmentName(ValueError):
_parser = Parser(GRAMMAR_PEP_508_MARKERS, "lalr")


class BaseMarker:
class BaseMarker(ABC):
@abstractmethod
def intersect(self, other: BaseMarker) -> BaseMarker:
raise NotImplementedError()

@abstractmethod
def union(self, other: BaseMarker) -> BaseMarker:
raise NotImplementedError()

Expand All @@ -66,24 +71,37 @@ def is_any(self) -> bool:
def is_empty(self) -> bool:
return False

@abstractmethod
def validate(self, environment: dict[str, Any] | None) -> bool:
raise NotImplementedError()

@abstractmethod
def without_extras(self) -> BaseMarker:
raise NotImplementedError()

@abstractmethod
def exclude(self, marker_name: str) -> BaseMarker:
raise NotImplementedError()

@abstractmethod
def only(self, *marker_names: str) -> BaseMarker:
raise NotImplementedError()

@abstractmethod
def invert(self) -> BaseMarker:
raise NotImplementedError()

def __repr__(self) -> str:
return f"<{self.__class__.__name__} {str(self)}>"

@abstractmethod
def __hash__(self) -> int:
raise NotImplementedError()

@abstractmethod
def __eq__(self, other: object) -> bool:
raise NotImplementedError()


class AnyMarker(BaseMarker):
def intersect(self, other: BaseMarker) -> BaseMarker:
Expand Down Expand Up @@ -725,6 +743,7 @@ def is_empty(self) -> bool:
return all(m.is_empty() for m in self._markers)


@functools.lru_cache(maxsize=None)
radoering marked this conversation as resolved.
Show resolved Hide resolved
def parse_marker(marker: str) -> BaseMarker:
if marker == "<empty>":
return EmptyMarker()
Expand Down
4 changes: 3 additions & 1 deletion src/poetry/core/version/pep440/parser.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import functools
import re

from typing import TYPE_CHECKING
Expand Down Expand Up @@ -63,6 +64,7 @@ def _get_local(cls, match: Match[str] | None) -> LocalSegmentType | None:
)

@classmethod
@functools.lru_cache(maxsize=None)
def parse(cls, value: str, version_class: type[T]) -> T:
match = cls._regex.search(value) if value else None
if not match:
Expand All @@ -80,4 +82,4 @@ def parse(cls, value: str, version_class: type[T]) -> T:


def parse_pep440(value: str, version_class: type[T]) -> T:
return PEP440Parser.parse(value, version_class)
return PEP440Parser.parse(value, version_class) # type: ignore[arg-type]