Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-dep-logic for
openSUSE:Factory checked in at 2025-07-14 10:51:42
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-dep-logic (Old)
and /work/SRC/openSUSE:Factory/.python-dep-logic.new.7373 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-dep-logic"
Mon Jul 14 10:51:42 2025 rev:6 rq:1292441 version:0.5.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-dep-logic/python-dep-logic.changes
2025-01-23 18:06:54.363835133 +0100
+++
/work/SRC/openSUSE:Factory/.python-dep-logic.new.7373/python-dep-logic.changes
2025-07-14 10:57:01.481870034 +0200
@@ -1,0 +2,13 @@
+Sat Jul 12 17:31:35 UTC 2025 - Dirk Müller <[email protected]>
+
+- update to 0.5.1:
+ * Improve docstrings and format
+- update to 0.5.0:
+ * Support 'extras' and 'dependency_groups' markers
+ * Improve logic for detecting msys2-based Python (works for
+ 3.11 and 3.
+- update to 0.4.11:
+ * Handle irregular python tags
+ * Basic loongarch64 support
+
+-------------------------------------------------------------------
Old:
----
dep_logic-0.4.10.tar.gz
New:
----
dep_logic-0.5.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-dep-logic.spec ++++++
--- /var/tmp/diff_new_pack.2HD6dI/_old 2025-07-14 10:57:02.085895074 +0200
+++ /var/tmp/diff_new_pack.2HD6dI/_new 2025-07-14 10:57:02.089895240 +0200
@@ -18,7 +18,7 @@
%{?sle15_python_module_pythons}
Name: python-dep-logic
-Version: 0.4.10
+Version: 0.5.1
Release: 0
Summary: Python dependency specifications supporting logical operations
License: Apache-2.0
++++++ dep_logic-0.4.10.tar.gz -> dep_logic-0.5.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/dep_logic-0.4.10/PKG-INFO
new/dep_logic-0.5.1/PKG-INFO
--- old/dep_logic-0.4.10/PKG-INFO 1970-01-01 01:00:00.000000000 +0100
+++ new/dep_logic-0.5.1/PKG-INFO 1970-01-01 01:00:00.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: dep-logic
-Version: 0.4.10
+Version: 0.5.1
Summary: Python dependency specifications supporting logical operations
Keywords: dependency,specification,logic,packaging
Author-Email: Frost Ming <[email protected]>
@@ -12,6 +12,7 @@
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
+Classifier: Programming Language :: Python :: 3.13
Classifier: License :: OSI Approved :: Apache Software License
Requires-Python: >=3.8
Requires-Dist: packaging>=22
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/dep_logic-0.4.10/pyproject.toml
new/dep_logic-0.5.1/pyproject.toml
--- old/dep_logic-0.4.10/pyproject.toml 2024-12-13 12:04:19.215864000 +0100
+++ new/dep_logic-0.5.1/pyproject.toml 2025-05-19 11:34:51.963228700 +0200
@@ -24,9 +24,10 @@
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
+ "Programming Language :: Python :: 3.13",
"License :: OSI Approved :: Apache Software License",
]
-version = "0.4.10"
+version = "0.5.1"
[project.license]
text = "Apache-2.0"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/dep_logic-0.4.10/src/dep_logic/markers/__init__.py
new/dep_logic-0.5.1/src/dep_logic/markers/__init__.py
--- old/dep_logic-0.4.10/src/dep_logic/markers/__init__.py 2024-12-13
12:04:09.695863000 +0100
+++ new/dep_logic-0.5.1/src/dep_logic/markers/__init__.py 2025-05-19
11:34:42.943260200 +0200
@@ -31,15 +31,15 @@
__all__ = [
- "parse_marker",
- "from_pkg_marker",
- "InvalidMarker",
- "BaseMarker",
"AnyMarker",
+ "BaseMarker",
"EmptyMarker",
+ "InvalidMarker",
"MarkerExpression",
"MarkerUnion",
"MultiMarker",
+ "from_pkg_marker",
+ "parse_marker",
]
@@ -99,3 +99,34 @@
else:
or_groups[-1] &= _build_markers(item)
return MarkerUnion.of(*or_groups)
+
+
+def _patch_marker_parser() -> None:
+ import re
+
+ try:
+ from packaging._tokenizer import DEFAULT_RULES
+ except (ModuleNotFoundError, AttributeError):
+ return
+
+ DEFAULT_RULES["VARIABLE"] = re.compile(
+ r"""
+ \b(
+ python_version
+ |python_full_version
+ |os[._]name
+ |sys[._]platform
+ |platform_(release|system)
+ |platform[._](version|machine|python_implementation)
+ |python_implementation
+ |implementation_(name|version)
+ |extras?
+ |dependency_groups
+ )\b
+ """,
+ re.VERBOSE,
+ )
+
+
+_patch_marker_parser()
+del _patch_marker_parser
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/dep_logic-0.4.10/src/dep_logic/markers/any.py
new/dep_logic-0.5.1/src/dep_logic/markers/any.py
--- old/dep_logic-0.4.10/src/dep_logic/markers/any.py 2024-12-13
12:04:09.695863000 +0100
+++ new/dep_logic-0.5.1/src/dep_logic/markers/any.py 2025-05-19
11:34:42.943260200 +0200
@@ -1,6 +1,6 @@
from __future__ import annotations
-from dep_logic.markers.base import BaseMarker
+from dep_logic.markers.base import BaseMarker, EvaluationContext
class AnyMarker(BaseMarker):
@@ -17,7 +17,11 @@
def is_any(self) -> bool:
return True
- def evaluate(self, environment: dict[str, str] | None = None) -> bool:
+ def evaluate(
+ self,
+ environment: dict[str, str | set[str]] | None = None,
+ context: EvaluationContext = "metadata",
+ ):
return True
def without_extras(self) -> BaseMarker:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/dep_logic-0.4.10/src/dep_logic/markers/base.py
new/dep_logic-0.5.1/src/dep_logic/markers/base.py
--- old/dep_logic-0.4.10/src/dep_logic/markers/base.py 2024-12-13
12:04:09.695863000 +0100
+++ new/dep_logic-0.5.1/src/dep_logic/markers/base.py 2025-05-19
11:34:42.943260200 +0200
@@ -1,7 +1,9 @@
from __future__ import annotations
from abc import ABCMeta, abstractmethod
-from typing import Any
+from typing import Any, Literal
+
+EvaluationContext = Literal["lock_file", "metadata", "requirement"]
class BaseMarker(metaclass=ABCMeta):
@@ -22,25 +24,41 @@
raise NotImplementedError
def is_any(self) -> bool:
+ """Returns True if the marker allows any environment."""
return False
def is_empty(self) -> bool:
+ """Returns True if the marker disallows any environment."""
return False
@abstractmethod
- def evaluate(self, environment: dict[str, str] | None = None) -> bool:
+ def evaluate(
+ self,
+ environment: dict[str, str | set[str]] | None = None,
+ context: EvaluationContext = "metadata",
+ ) -> bool:
+ """Evaluates the marker against the given environment.
+
+ Args:
+ environment: The environment to evaluate against.
+ context: The context in which the evaluation is performed,
+ can be "lock_file", "metadata", or "requirement".
+ """
raise NotImplementedError
@abstractmethod
def without_extras(self) -> BaseMarker:
+ """Generate a new marker from the current marker but without "extra"
markers."""
raise NotImplementedError
@abstractmethod
def exclude(self, marker_name: str) -> BaseMarker:
+ """Generate a new marker from the current marker but without the given
marker."""
raise NotImplementedError
@abstractmethod
def only(self, *marker_names: str) -> BaseMarker:
+ """Generate a new marker from the current marker but only with the
given markers."""
raise NotImplementedError
def __repr__(self) -> str:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/dep_logic-0.4.10/src/dep_logic/markers/empty.py
new/dep_logic-0.5.1/src/dep_logic/markers/empty.py
--- old/dep_logic-0.4.10/src/dep_logic/markers/empty.py 2024-12-13
12:04:09.695863000 +0100
+++ new/dep_logic-0.5.1/src/dep_logic/markers/empty.py 2025-05-19
11:34:42.943260200 +0200
@@ -1,6 +1,6 @@
from __future__ import annotations
-from dep_logic.markers.base import BaseMarker
+from dep_logic.markers.base import BaseMarker, EvaluationContext
class EmptyMarker(BaseMarker):
@@ -17,7 +17,11 @@
def is_empty(self) -> bool:
return True
- def evaluate(self, environment: dict[str, str] | None = None) -> bool:
+ def evaluate(
+ self,
+ environment: dict[str, str | set[str]] | None = None,
+ context: EvaluationContext = "metadata",
+ ) -> bool:
return False
def without_extras(self) -> BaseMarker:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/dep_logic-0.4.10/src/dep_logic/markers/multi.py
new/dep_logic-0.5.1/src/dep_logic/markers/multi.py
--- old/dep_logic-0.4.10/src/dep_logic/markers/multi.py 2024-12-13
12:04:09.695863000 +0100
+++ new/dep_logic-0.5.1/src/dep_logic/markers/multi.py 2025-05-19
11:34:42.943260200 +0200
@@ -4,7 +4,7 @@
from typing import Iterator
from dep_logic.markers.any import AnyMarker
-from dep_logic.markers.base import BaseMarker
+from dep_logic.markers.base import BaseMarker, EvaluationContext
from dep_logic.markers.empty import EmptyMarker
from dep_logic.markers.single import MarkerExpression, SingleMarker
from dep_logic.utils import DATACLASS_ARGS, flatten_items, intersection, union
@@ -135,8 +135,12 @@
return None
- def evaluate(self, environment: dict[str, str] | None = None) -> bool:
- return all(m.evaluate(environment) for m in self.markers)
+ def evaluate(
+ self,
+ environment: dict[str, str | set[str]] | None = None,
+ context: EvaluationContext = "metadata",
+ ) -> bool:
+ return all(m.evaluate(environment, context) for m in self.markers)
def without_extras(self) -> BaseMarker:
return self.exclude("extra")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/dep_logic-0.4.10/src/dep_logic/markers/single.py
new/dep_logic-0.5.1/src/dep_logic/markers/single.py
--- old/dep_logic-0.4.10/src/dep_logic/markers/single.py 2024-12-13
12:04:09.695863000 +0100
+++ new/dep_logic-0.5.1/src/dep_logic/markers/single.py 2025-05-19
11:34:42.943260200 +0200
@@ -1,24 +1,44 @@
from __future__ import annotations
import functools
+import operator
import typing as t
+from abc import abstractmethod
from dataclasses import dataclass, field, replace
-from packaging.markers import Marker as _Marker
+from packaging.markers import default_environment
+from packaging.specifiers import InvalidSpecifier, Specifier
+from packaging.version import InvalidVersion
from dep_logic.markers.any import AnyMarker
-from dep_logic.markers.base import BaseMarker
+from dep_logic.markers.base import BaseMarker, EvaluationContext
from dep_logic.markers.empty import EmptyMarker
from dep_logic.specifiers import BaseSpecifier
from dep_logic.specifiers.base import VersionSpecifier
from dep_logic.specifiers.generic import GenericSpecifier
-from dep_logic.utils import DATACLASS_ARGS, OrderedSet, get_reflect_op
+from dep_logic.utils import DATACLASS_ARGS, OrderedSet, get_reflect_op,
normalize_name
if t.TYPE_CHECKING:
from dep_logic.markers.multi import MultiMarker
from dep_logic.markers.union import MarkerUnion
PYTHON_VERSION_MARKERS = {"python_version", "python_full_version"}
+MARKERS_ALLOWING_SET = {"extras", "dependency_groups"}
+Operator = t.Callable[[str, t.Union[str, t.Set[str]]], bool]
+_operators: dict[str, Operator] = {
+ "in": lambda lhs, rhs: lhs in rhs,
+ "not in": lambda lhs, rhs: lhs not in rhs,
+ "<": operator.lt,
+ "<=": operator.le,
+ "==": operator.eq,
+ "!=": operator.ne,
+ ">=": operator.ge,
+ ">": operator.gt,
+}
+
+
+class UndefinedComparison(ValueError):
+ pass
class SingleMarker(BaseMarker):
@@ -44,16 +64,25 @@
return self
- def evaluate(self, environment: dict[str, str] | None = None) -> bool:
- pkg_marker = _Marker(str(self))
- if self.name != "extra" or not environment or "extra" not in
environment:
- return pkg_marker.evaluate(environment)
- extras = [extra] if isinstance(extra := environment["extra"], str)
else extra
- assert isinstance(self, MarkerExpression)
- is_negated = self.op in ("not in", "!=")
- if is_negated:
- return all(pkg_marker.evaluate({"extra": extra}) for extra in
extras)
- return any(pkg_marker.evaluate({"extra": extra}) for extra in extras)
+ def evaluate(
+ self,
+ environment: dict[str, str | set[str]] | None = None,
+ context: EvaluationContext = "metadata",
+ ) -> bool:
+ current_environment = t.cast("dict[str, str|set[str]]",
default_environment())
+ if context == "metadata":
+ current_environment["extra"] = ""
+ elif context == "lock_file":
+ current_environment.update(extras=set(), dependency_groups=set())
+ if environment:
+ current_environment.update(environment)
+ if "extra" in current_environment and current_environment["extra"] is
None:
+ current_environment["extra"] = ""
+ return self._evaluate(current_environment)
+
+ @abstractmethod
+ def _evaluate(self, environment: dict[str, str | set[str]]) -> bool:
+ raise NotImplementedError
@dataclass(unsafe_hash=True, **DATACLASS_ARGS)
@@ -141,6 +170,46 @@
return MarkerUnion(self, other)
+ def _evaluate(self, environment: dict[str, str | set[str]]) -> bool:
+ if self.name == "extra":
+ # Support batch comparison for "extra" markers
+ extra = environment["extra"]
+ if isinstance(extra, str):
+ extra = {extra}
+ assert self.op in ("==", "!=")
+ value = normalize_name(self.value)
+ extra = {normalize_name(v) for v in extra}
+ return value in extra if self.op == "==" else value not in extra
+
+ target = environment[self.name]
+ if self.reversed:
+ lhs, rhs = self.value, target
+ oper = _operators.get(get_reflect_op(self.op))
+ else:
+ lhs, rhs = target, self.value
+ assert isinstance(lhs, str)
+ oper = _operators.get(self.op)
+ if self.name in MARKERS_ALLOWING_SET:
+ lhs = normalize_name(lhs)
+ if isinstance(rhs, set):
+ rhs = {normalize_name(v) for v in rhs}
+ else:
+ rhs = normalize_name(rhs)
+ if isinstance(rhs, str):
+ try:
+ spec = Specifier(f"{self.op}{rhs}")
+ except InvalidSpecifier:
+ pass
+ else:
+ try:
+ return spec.contains(lhs)
+ except InvalidVersion:
+ pass
+
+ if oper is None:
+ raise UndefinedComparison(f"Undefined comparison {self}")
+ return oper(lhs, rhs)
+
@dataclass(frozen=True, unsafe_hash=True, **DATACLASS_ARGS)
class EqualityMarkerUnion(SingleMarker):
@@ -210,6 +279,9 @@
__rand__ = __and__
__ror__ = __or__
+ def _evaluate(self, environment: dict[str, str | set[str]]) -> bool:
+ return environment[self.name] in self.values
+
@dataclass(frozen=True, unsafe_hash=True, **DATACLASS_ARGS)
class InequalityMultiMarker(SingleMarker):
@@ -283,6 +355,9 @@
__rand__ = __and__
__ror__ = __or__
+ def _evaluate(self, environment: dict[str, str | set[str]]) -> bool:
+ return environment[self.name] not in self.values
+
@functools.lru_cache(maxsize=None)
def _merge_single_markers(
@@ -375,5 +450,5 @@
splitted[-1] = str(int(splitted[-1]) + 1)
op = "<"
- spec = parse_version_specifier(f'{op}{".".join(splitted)}')
+ spec = parse_version_specifier(f"{op}{'.'.join(splitted)}")
return spec
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/dep_logic-0.4.10/src/dep_logic/markers/union.py
new/dep_logic-0.5.1/src/dep_logic/markers/union.py
--- old/dep_logic-0.4.10/src/dep_logic/markers/union.py 2024-12-13
12:04:09.695863000 +0100
+++ new/dep_logic-0.5.1/src/dep_logic/markers/union.py 2025-05-19
11:34:42.943260200 +0200
@@ -4,7 +4,7 @@
from typing import Iterator
from dep_logic.markers.any import AnyMarker
-from dep_logic.markers.base import BaseMarker
+from dep_logic.markers.base import BaseMarker, EvaluationContext
from dep_logic.markers.empty import EmptyMarker
from dep_logic.markers.multi import MultiMarker
from dep_logic.markers.single import SingleMarker
@@ -135,8 +135,12 @@
return None
- def evaluate(self, environment: dict[str, str] | None = None) -> bool:
- return any(m.evaluate(environment) for m in self.markers)
+ def evaluate(
+ self,
+ environment: dict[str, str | set[str]] | None = None,
+ context: EvaluationContext = "metadata",
+ ) -> bool:
+ return any(m.evaluate(environment, context) for m in self.markers)
def without_extras(self) -> BaseMarker:
return self.exclude("extra")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/dep_logic-0.4.10/src/dep_logic/specifiers/range.py
new/dep_logic-0.5.1/src/dep_logic/specifiers/range.py
--- old/dep_logic-0.4.10/src/dep_logic/specifiers/range.py 2024-12-13
12:04:09.695863000 +0100
+++ new/dep_logic-0.5.1/src/dep_logic/specifiers/range.py 2025-05-19
11:34:42.944260100 +0200
@@ -81,7 +81,7 @@
simplified = self._simplified_form
if simplified is not None:
return simplified
- return f'{">=" if self.include_min else ">"}{self.min},{"<=" if
self.include_max else "<"}{self.max}'
+ return f"{'>=' if self.include_min else '>'}{self.min},{'<=' if
self.include_max else '<'}{self.max}"
def contains(
self, version: UnparsedVersion, prereleases: bool | None = None
@@ -115,11 +115,8 @@
if self.min is None:
return True
- return (
- self.min < other.min
- or self.min == other.min
- and self.include_min
- and not other.include_min
+ return self.min < other.min or (
+ self.min == other.min and self.include_min and not
other.include_min
)
def allows_higher(self, other: RangeSpecifier) -> bool:
@@ -128,11 +125,8 @@
if self.max is None:
return True
- return (
- self.max > other.max
- or self.max == other.max
- and self.include_max
- and not other.include_max
+ return self.max > other.max or (
+ self.max == other.max and self.include_max and not
other.include_max
)
def is_strictly_lower(self, other: RangeSpecifier) -> bool:
@@ -142,10 +136,8 @@
if self.max is None or other.min is None:
return False
- return (
- self.max < other.min
- or self.max == other.min
- and False in (self.include_max, other.include_min)
+ return self.max < other.min or (
+ self.max == other.min and False in (self.include_max,
other.include_min)
)
def is_adjacent_to(self, other: RangeSpecifier) -> bool:
@@ -162,22 +154,24 @@
return self.allows_lower(other)
def is_superset(self, other: RangeSpecifier) -> bool:
- min_lower = (
- self.min is None
- or other.min is not None
+ min_lower = self.min is None or (
+ other.min is not None
and (
self.min < other.min
- or self.min == other.min
- and not (not self.include_min and other.include_min)
+ or (
+ self.min == other.min
+ and not (not self.include_min and other.include_min)
+ )
)
)
- max_higher = (
- self.max is None
- or other.max is not None
+ max_higher = self.max is None or (
+ other.max is not None
and (
self.max > other.max
- or self.max == other.max
- and not (not self.include_max and other.include_max)
+ or (
+ self.max == other.max
+ and not (not self.include_max and other.include_max)
+ )
)
)
return min_lower and max_higher
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/dep_logic-0.4.10/src/dep_logic/specifiers/special.py
new/dep_logic-0.5.1/src/dep_logic/specifiers/special.py
--- old/dep_logic-0.4.10/src/dep_logic/specifiers/special.py 2024-12-13
12:04:09.695863000 +0100
+++ new/dep_logic-0.5.1/src/dep_logic/specifiers/special.py 2025-05-19
11:34:42.944260100 +0200
@@ -36,7 +36,7 @@
return True
def __contains__(self, value: str) -> bool:
- return True
+ return False
class AnySpecifier(BaseSpecifier):
@@ -72,4 +72,4 @@
return True
def __contains__(self, value: str) -> bool:
- return False
+ return True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/dep_logic-0.4.10/src/dep_logic/tags/platform.py
new/dep_logic-0.5.1/src/dep_logic/tags/platform.py
--- old/dep_logic-0.4.10/src/dep_logic/tags/platform.py 2024-12-13
12:04:09.696863000 +0100
+++ new/dep_logic-0.5.1/src/dep_logic/tags/platform.py 2025-05-19
11:34:42.944260100 +0200
@@ -118,9 +118,11 @@
# Ex: macosx-11.2-arm64
version, architecture = version_arch.rsplit("-", 1)
else:
- # Ex: linux-x86_64
+ # Ex: linux-x86_64 or x86_64_msvcrt_gnu
version = None
architecture = version_arch
+ if version_arch.startswith("x86_64"):
+ architecture = "x86_64"
if operating_system == "linux":
from packaging._manylinux import _get_glibc_version
@@ -337,6 +339,7 @@
X86_64 = "x86_64"
S390X = "s390x"
RISCV64 = "riscv64"
+ LoongArch64 = "loongarch64"
def __str__(self) -> str:
return self.value
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/dep_logic-0.4.10/src/dep_logic/tags/tags.py
new/dep_logic-0.5.1/src/dep_logic/tags/tags.py
--- old/dep_logic-0.4.10/src/dep_logic/tags/tags.py 2024-12-13
12:04:09.696863000 +0100
+++ new/dep_logic-0.5.1/src/dep_logic/tags/tags.py 2025-05-19
11:34:42.944260100 +0200
@@ -155,7 +155,7 @@
self, python_tag: str, abi_tag: str
) -> tuple[int, int, int] | None:
"""Return a tuple of (major, minor, abi) if the wheel is compatible
with the environment, or None otherwise."""
- impl, major, minor = python_tag[:2], python_tag[2], python_tag[3:]
+ impl, major, minor = python_tag[:2], python_tag[2:3], python_tag[3:]
if self.implementation is not None and impl not in [
self.implementation.short,
"py",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/dep_logic-0.4.10/src/dep_logic/utils.py
new/dep_logic-0.5.1/src/dep_logic/utils.py
--- old/dep_logic-0.4.10/src/dep_logic/utils.py 2024-12-13 12:04:09.696863000
+0100
+++ new/dep_logic-0.5.1/src/dep_logic/utils.py 2025-05-19 11:34:42.944260100
+0200
@@ -191,3 +191,7 @@
def peek(self) -> T:
return self._data[0]
+
+
+def normalize_name(name: str) -> str:
+ return re.sub(r"[-_.]+", "-", name).lower()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/dep_logic-0.4.10/tests/marker/test_evaluation.py
new/dep_logic-0.5.1/tests/marker/test_evaluation.py
--- old/dep_logic-0.4.10/tests/marker/test_evaluation.py 2024-12-13
12:04:09.696863000 +0100
+++ new/dep_logic-0.5.1/tests/marker/test_evaluation.py 2025-05-19
11:34:42.945260000 +0200
@@ -21,17 +21,17 @@
True,
),
(
- "python_version ~= '2.7.0' and (os_name == 'foo' or " "os_name ==
'bar')",
+ "python_version ~= '2.7.0' and (os_name == 'foo' or os_name ==
'bar')",
{"os_name": "foo", "python_version": "2.7.4"},
True,
),
(
- "python_version ~= '2.7.0' and (os_name == 'foo' or " "os_name ==
'bar')",
+ "python_version ~= '2.7.0' and (os_name == 'foo' or os_name ==
'bar')",
{"os_name": "bar", "python_version": "2.7.4"},
True,
),
(
- "python_version ~= '2.7.0' and (os_name == 'foo' or " "os_name ==
'bar')",
+ "python_version ~= '2.7.0' and (os_name == 'foo' or os_name ==
'bar')",
{"os_name": "other", "python_version": "2.7.4"},
False,
),
@@ -48,10 +48,9 @@
],
)
def test_evaluates(
- marker_string: str, environment: dict[str, str], expected: bool
+ marker_string: str, environment: dict[str, str | set[str]], expected: bool
) -> None:
- args = [] if environment is None else [environment]
- assert parse_marker(marker_string).evaluate(*args) == expected
+ assert parse_marker(marker_string).evaluate(environment) == expected
@pytest.mark.parametrize(
@@ -103,6 +102,7 @@
{"platform_machine": "x86_64"},
False,
),
+ ("platform_release >= '6'", {"platform_release": "6.1-foobar"}, True),
# extras
# single extra
("extra != 'security'", {"extra": "quux"}, True),
@@ -144,7 +144,7 @@
],
)
def test_evaluate_extra(
- marker_string: str, environment: dict[str, str] | None, expected: bool
+ marker_string: str, environment: dict[str, str | set[str]] | None,
expected: bool
) -> None:
m = parse_marker(marker_string)
@@ -160,7 +160,43 @@
)
],
)
-def test_parse_version_like_markers(marker: str, env: dict[str, str]) -> None:
+def test_parse_version_like_markers(
+ marker: str, env: dict[str, str | set[str]]
+) -> None:
m = parse_marker(marker)
assert m.evaluate(env)
+
+
[email protected]("variable", ["extras", "dependency_groups"])
[email protected](
+ "expression,result",
+ [
+ pytest.param('"foo" in {0}', True, id="value-in-foo"),
+ pytest.param('"bar" in {0}', True, id="value-in-bar"),
+ pytest.param('"baz" in {0}', False, id="value-not-in"),
+ pytest.param('"baz" not in {0}', True, id="value-not-in-negated"),
+ pytest.param('"foo" in {0} and "bar" in {0}', True, id="and-in"),
+ pytest.param('"foo" in {0} or "bar" in {0}', True, id="or-in"),
+ pytest.param('"baz" in {0} and "foo" in {0}', False,
id="short-circuit-and"),
+ pytest.param('"foo" in {0} or "baz" in {0}', True,
id="short-circuit-or"),
+ pytest.param('"Foo" in {0}', True, id="case-sensitive"),
+ ],
+)
+def test_extras_and_dependency_groups(
+ variable: str, expression: str, result: bool
+) -> None:
+ environment: dict[str, str | set[str]] = {variable: {"foo", "bar"}}
+ assert parse_marker(expression.format(variable)).evaluate(environment) ==
result
+
+
[email protected]("variable", ["extras", "dependency_groups"])
+def test_extras_and_dependency_groups_disallowed(variable: str) -> None:
+ marker = parse_marker(f'"foo" in {variable}')
+ assert not marker.evaluate(context="lock_file")
+
+ with pytest.raises(KeyError):
+ marker.evaluate()
+
+ with pytest.raises(KeyError):
+ marker.evaluate(context="requirement")