From 6e7f17cc81cfd0ffcb90c3fff08f31fb2f3f2e56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Randy=20D=C3=B6ring?= <30527984+radoering@users.noreply.github.com> Date: Sun, 19 Feb 2023 06:32:02 +0100 Subject: [PATCH 1/3] performance: cache parsed markers --- src/poetry/core/version/markers.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/poetry/core/version/markers.py b/src/poetry/core/version/markers.py index 7c12a34db..9d36a9703 100644 --- a/src/poetry/core/version/markers.py +++ b/src/poetry/core/version/markers.py @@ -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 @@ -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() @@ -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: @@ -725,6 +743,7 @@ def is_empty(self) -> bool: return all(m.is_empty() for m in self._markers) +@functools.lru_cache(maxsize=None) def parse_marker(marker: str) -> BaseMarker: if marker == "": return EmptyMarker() From c218ddedd895f0f454ff1a4b84816b5eab0a9cd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Randy=20D=C3=B6ring?= <30527984+radoering@users.noreply.github.com> Date: Sun, 19 Feb 2023 07:28:24 +0100 Subject: [PATCH 2/3] chore: bump isort version --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 371073dab..d9d7fdbf4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -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] From 46392366b3813b74b3485759a0dcd01a74e8a3a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Randy=20D=C3=B6ring?= <30527984+radoering@users.noreply.github.com> Date: Sun, 19 Feb 2023 14:46:47 +0100 Subject: [PATCH 3/3] performance: cache parsed constraints and versions --- src/poetry/core/constraints/generic/parser.py | 2 ++ src/poetry/core/constraints/version/parser.py | 2 ++ src/poetry/core/version/pep440/parser.py | 4 +++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/poetry/core/constraints/generic/parser.py b/src/poetry/core/constraints/generic/parser.py index abfba8eb5..9b5185385 100644 --- a/src/poetry/core/constraints/generic/parser.py +++ b/src/poetry/core/constraints/generic/parser.py @@ -1,5 +1,6 @@ from __future__ import annotations +import functools import re from typing import TYPE_CHECKING @@ -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() diff --git a/src/poetry/core/constraints/version/parser.py b/src/poetry/core/constraints/version/parser.py index 118a78cc3..86d59f649 100644 --- a/src/poetry/core/constraints/version/parser.py +++ b/src/poetry/core/constraints/version/parser.py @@ -1,5 +1,6 @@ from __future__ import annotations +import functools import re from typing import TYPE_CHECKING @@ -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 diff --git a/src/poetry/core/version/pep440/parser.py b/src/poetry/core/version/pep440/parser.py index 11fae074d..6aa99cf24 100644 --- a/src/poetry/core/version/pep440/parser.py +++ b/src/poetry/core/version/pep440/parser.py @@ -1,5 +1,6 @@ from __future__ import annotations +import functools import re from typing import TYPE_CHECKING @@ -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: @@ -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]