Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-packaging for
openSUSE:Factory checked in at 2025-08-01 22:40:12
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-packaging (Old)
and /work/SRC/openSUSE:Factory/.python-packaging.new.1944 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-packaging"
Fri Aug 1 22:40:12 2025 rev:37 rq:1296839 version:25.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-packaging/python-packaging.changes
2025-05-20 09:31:40.081136057 +0200
+++
/work/SRC/openSUSE:Factory/.python-packaging.new.1944/python-packaging.changes
2025-08-01 22:40:25.785055033 +0200
@@ -1,0 +2,7 @@
+Thu Jul 31 11:44:29 UTC 2025 - marec <[email protected]>
+
+- update to 25.0:
+ * PEP 751: Add support for extras and dependency_groups markers. (#885)
+ * PEP 738: Add support for Android platform tags. (#880)
+
+-------------------------------------------------------------------
Old:
----
packaging-24.2.tar.gz
New:
----
packaging-25.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-packaging.spec ++++++
--- /var/tmp/diff_new_pack.qzqhD1/_old 2025-08-01 22:40:26.285075862 +0200
+++ /var/tmp/diff_new_pack.qzqhD1/_new 2025-08-01 22:40:26.285075862 +0200
@@ -53,7 +53,7 @@
%endif
Name: %{pprefix}-packaging%{?psuffix}
-Version: 24.2
+Version: 25.0
Release: 0
Summary: Core utilities for Python packages
License: Apache-2.0 AND BSD-2-Clause
++++++ packaging-24.2.tar.gz -> packaging-25.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/packaging-24.2/CHANGELOG.rst
new/packaging-25.0/CHANGELOG.rst
--- old/packaging-24.2/CHANGELOG.rst 2024-11-08 10:47:13.100733500 +0100
+++ new/packaging-25.0/CHANGELOG.rst 2025-04-19 13:48:37.249769700 +0200
@@ -1,6 +1,12 @@
Changelog
---------
+25.0 - 2025-04-19
+~~~~~~~~~~~~~~~~~
+
+* PEP 751: Add support for ``extras`` and ``dependency_groups`` markers.
(:issue:`885`)
+* PEP 738: Add support for Android platform tags. (:issue:`880`)
+
24.2 - 2024-11-08
~~~~~~~~~~~~~~~~~
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/packaging-24.2/PKG-INFO new/packaging-25.0/PKG-INFO
--- old/packaging-24.2/PKG-INFO 1970-01-01 01:00:00.000000000 +0100
+++ new/packaging-25.0/PKG-INFO 1970-01-01 01:00:00.000000000 +0100
@@ -1,6 +1,6 @@
-Metadata-Version: 2.3
+Metadata-Version: 2.4
Name: packaging
-Version: 24.2
+Version: 25.0
Summary: Core utilities for Python packages
Author-email: Donald Stufft <[email protected]>
Requires-Python: >=3.8
@@ -21,6 +21,9 @@
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Typing :: Typed
+License-File: LICENSE
+License-File: LICENSE.APACHE
+License-File: LICENSE.BSD
Project-URL: Documentation, https://packaging.pypa.io/
Project-URL: Source, https://github.com/pypa/packaging
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/packaging-24.2/docs/markers.rst
new/packaging-25.0/docs/markers.rst
--- old/packaging-24.2/docs/markers.rst 2024-09-15 20:27:03.642005700 +0200
+++ new/packaging-25.0/docs/markers.rst 2025-04-19 13:45:16.853398600 +0200
@@ -64,6 +64,9 @@
:param dict environment: A dictionary containing keys and values to
override the detected environment.
+ :param str context: A string representing the context in which the marker
is evaluated.
+ Acceptable values are "metadata" (for core metadata;
default),
+ "lock_file", and "requirement" (i.e. all other
situations).
:raises: UndefinedComparison: If the marker uses a comparison on strings
which are not valid versions per the
:ref:`specification of version specifiers
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/packaging-24.2/docs/tags.rst
new/packaging-25.0/docs/tags.rst
--- old/packaging-24.2/docs/tags.rst 2024-10-03 22:21:49.599062700 +0200
+++ new/packaging-25.0/docs/tags.rst 2025-04-19 13:45:16.853845000 +0200
@@ -168,6 +168,21 @@
Behavior of this method is undefined if invoked on non-iOS platforms
without providing explicit version and multiarch arguments.
+
+.. function:: android_platforms(api_level=None, abi=None)
+
+ Yields the :attr:`~Tag.platform` tags for Android. If this function is
invoked on
+ non-Android platforms, the ``api_level`` and ``abi`` arguments are
required.
+
+ :param int api_level: The maximum `API level
+ <https://developer.android.com/tools/releases/platforms>`__ to return.
Defaults
+ to the current system's version, as returned by
``platform.android_ver``.
+ :param str abi: The `Android ABI
<https://developer.android.com/ndk/guides/abis>`__,
+ e.g. ``arm64_v8a``. Defaults to the current system's ABI , as returned
by
+ ``sysconfig.get_platform``. Hyphens and periods will be replaced with
+ underscores.
+
+
.. function:: platform_tags(version=None, arch=None)
Yields the :attr:`~Tag.platform` tags for the running interpreter.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/packaging-24.2/pyproject.toml
new/packaging-25.0/pyproject.toml
--- old/packaging-24.2/pyproject.toml 2024-11-08 10:41:39.082868600 +0100
+++ new/packaging-25.0/pyproject.toml 2025-04-19 13:45:16.854215000 +0200
@@ -78,6 +78,7 @@
]
ignore = [
"B027",
+ "F821",
"N818",
"RUF003",
"RUF012",
@@ -95,6 +96,4 @@
"Q003",
"COM812",
"COM819",
- "ISC001",
- "ISC002",
]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/packaging-24.2/src/packaging/__init__.py
new/packaging-25.0/src/packaging/__init__.py
--- old/packaging-24.2/src/packaging/__init__.py 2024-11-08
10:47:13.101016300 +0100
+++ new/packaging-25.0/src/packaging/__init__.py 2025-04-19
13:48:37.250069400 +0200
@@ -6,7 +6,7 @@
__summary__ = "Core utilities for Python packages"
__uri__ = "https://github.com/pypa/packaging"
-__version__ = "24.2"
+__version__ = "25.0"
__author__ = "Donald Stufft and individual contributors"
__email__ = "[email protected]"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/packaging-24.2/src/packaging/_elffile.py
new/packaging-25.0/src/packaging/_elffile.py
--- old/packaging-24.2/src/packaging/_elffile.py 2024-09-15
20:27:08.853526600 +0200
+++ new/packaging-25.0/src/packaging/_elffile.py 2025-04-19
13:45:16.854780400 +0200
@@ -69,8 +69,7 @@
}[(self.capacity, self.encoding)]
except KeyError as e:
raise ELFInvalid(
- f"unrecognized capacity ({self.capacity}) or "
- f"encoding ({self.encoding})"
+ f"unrecognized capacity ({self.capacity}) or encoding
({self.encoding})"
) from e
try:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/packaging-24.2/src/packaging/_manylinux.py
new/packaging-25.0/src/packaging/_manylinux.py
--- old/packaging-24.2/src/packaging/_manylinux.py 2024-09-15
20:27:08.853865100 +0200
+++ new/packaging-25.0/src/packaging/_manylinux.py 2025-04-19
13:45:16.855287800 +0200
@@ -161,8 +161,7 @@
m = re.match(r"(?P<major>[0-9]+)\.(?P<minor>[0-9]+)", version_str)
if not m:
warnings.warn(
- f"Expected glibc version with 2 components major.minor,"
- f" got: {version_str}",
+ f"Expected glibc version with 2 components major.minor, got:
{version_str}",
RuntimeWarning,
stacklevel=2,
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/packaging-24.2/src/packaging/_parser.py
new/packaging-25.0/src/packaging/_parser.py
--- old/packaging-24.2/src/packaging/_parser.py 2024-10-03 22:21:49.599353000
+0200
+++ new/packaging-25.0/src/packaging/_parser.py 2025-04-19 13:45:16.855672400
+0200
@@ -349,6 +349,5 @@
return Op(tokenizer.read().text)
else:
return tokenizer.raise_syntax_error(
- "Expected marker operator, one of "
- "<=, <, !=, ==, >=, >, ~=, ===, in, not in"
+ "Expected marker operator, one of <=, <, !=, ==, >=, >, ~=, ===,
in, not in"
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/packaging-24.2/src/packaging/_tokenizer.py
new/packaging-25.0/src/packaging/_tokenizer.py
--- old/packaging-24.2/src/packaging/_tokenizer.py 2024-06-10
01:16:42.855516200 +0200
+++ new/packaging-25.0/src/packaging/_tokenizer.py 2025-04-19
13:45:16.856002000 +0200
@@ -68,7 +68,8 @@
|platform[._](version|machine|python_implementation)
|python_implementation
|implementation_(name|version)
- |extra
+ |extras?
+ |dependency_groups
)\b
""",
re.VERBOSE,
@@ -119,9 +120,9 @@
another check. If `peek` is set to `True`, the token is not loaded and
would need to be checked again.
"""
- assert (
- self.next_token is None
- ), f"Cannot check for {name!r}, already have {self.next_token!r}"
+ assert self.next_token is None, (
+ f"Cannot check for {name!r}, already have {self.next_token!r}"
+ )
assert name in self.rules, f"Unknown token name: {name!r}"
expression = self.rules[name]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/packaging-24.2/src/packaging/licenses/__init__.py
new/packaging-25.0/src/packaging/licenses/__init__.py
--- old/packaging-24.2/src/packaging/licenses/__init__.py 2024-11-08
10:41:39.083118200 +0100
+++ new/packaging-25.0/src/packaging/licenses/__init__.py 2025-04-19
13:45:16.856330400 +0200
@@ -37,8 +37,8 @@
from packaging.licenses._spdx import EXCEPTIONS, LICENSES
__all__ = [
- "NormalizedLicenseExpression",
"InvalidLicenseExpression",
+ "NormalizedLicenseExpression",
"canonicalize_license_expression",
]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/packaging-24.2/src/packaging/markers.py
new/packaging-25.0/src/packaging/markers.py
--- old/packaging-24.2/src/packaging/markers.py 2024-09-15 20:27:08.854714400
+0200
+++ new/packaging-25.0/src/packaging/markers.py 2025-04-19 13:45:16.856696100
+0200
@@ -8,7 +8,7 @@
import os
import platform
import sys
-from typing import Any, Callable, TypedDict, cast
+from typing import AbstractSet, Any, Callable, Literal, TypedDict, Union, cast
from ._parser import MarkerAtom, MarkerList, Op, Value, Variable
from ._parser import parse_marker as _parse_marker
@@ -17,6 +17,7 @@
from .utils import canonicalize_name
__all__ = [
+ "EvaluateContext",
"InvalidMarker",
"Marker",
"UndefinedComparison",
@@ -24,7 +25,9 @@
"default_environment",
]
-Operator = Callable[[str, str], bool]
+Operator = Callable[[str, Union[str, AbstractSet[str]]], bool]
+EvaluateContext = Literal["metadata", "lock_file", "requirement"]
+MARKERS_ALLOWING_SET = {"extras", "dependency_groups"}
class InvalidMarker(ValueError):
@@ -174,13 +177,14 @@
}
-def _eval_op(lhs: str, op: Op, rhs: str) -> bool:
- try:
- spec = Specifier("".join([op.serialize(), rhs]))
- except InvalidSpecifier:
- pass
- else:
- return spec.contains(lhs, prereleases=True)
+def _eval_op(lhs: str, op: Op, rhs: str | AbstractSet[str]) -> bool:
+ if isinstance(rhs, str):
+ try:
+ spec = Specifier("".join([op.serialize(), rhs]))
+ except InvalidSpecifier:
+ pass
+ else:
+ return spec.contains(lhs, prereleases=True)
oper: Operator | None = _operators.get(op.serialize())
if oper is None:
@@ -189,19 +193,29 @@
return oper(lhs, rhs)
-def _normalize(*values: str, key: str) -> tuple[str, ...]:
+def _normalize(
+ lhs: str, rhs: str | AbstractSet[str], key: str
+) -> tuple[str, str | AbstractSet[str]]:
# PEP 685 – Comparison of extra names for optional distribution
dependencies
# https://peps.python.org/pep-0685/
# > When comparing extra names, tools MUST normalize the names being
# > compared using the semantics outlined in PEP 503 for names
if key == "extra":
- return tuple(canonicalize_name(v) for v in values)
+ assert isinstance(rhs, str), "extra value must be a string"
+ return (canonicalize_name(lhs), canonicalize_name(rhs))
+ if key in MARKERS_ALLOWING_SET:
+ if isinstance(rhs, str): # pragma: no cover
+ return (canonicalize_name(lhs), canonicalize_name(rhs))
+ else:
+ return (canonicalize_name(lhs), {canonicalize_name(v) for v in
rhs})
# other environment markers don't have such standards
- return values
+ return lhs, rhs
-def _evaluate_markers(markers: MarkerList, environment: dict[str, str]) ->
bool:
+def _evaluate_markers(
+ markers: MarkerList, environment: dict[str, str | AbstractSet[str]]
+) -> bool:
groups: list[list[bool]] = [[]]
for marker in markers:
@@ -220,7 +234,7 @@
lhs_value = lhs.value
environment_key = rhs.value
rhs_value = environment[environment_key]
-
+ assert isinstance(lhs_value, str), "lhs must be a string"
lhs_value, rhs_value = _normalize(lhs_value, rhs_value,
key=environment_key)
groups[-1].append(_eval_op(lhs_value, op, rhs_value))
else:
@@ -298,22 +312,36 @@
return str(self) == str(other)
- def evaluate(self, environment: dict[str, str] | None = None) -> bool:
+ def evaluate(
+ self,
+ environment: dict[str, str] | None = None,
+ context: EvaluateContext = "metadata",
+ ) -> bool:
"""Evaluate a marker.
Return the boolean from evaluating the given marker against the
environment. environment is an optional argument to override all or
- part of the determined environment.
+ part of the determined environment. The *context* parameter specifies
what
+ context the markers are being evaluated for, which influences what
markers
+ are considered valid. Acceptable values are "metadata" (for core
metadata;
+ default), "lock_file", and "requirement" (i.e. all other situations).
The environment is determined from the current Python process.
"""
- current_environment = cast("dict[str, str]", default_environment())
- current_environment["extra"] = ""
+ current_environment = cast(
+ "dict[str, str | AbstractSet[str]]", default_environment()
+ )
+ if context == "lock_file":
+ current_environment.update(
+ extras=frozenset(), dependency_groups=frozenset()
+ )
+ elif context == "metadata":
+ current_environment["extra"] = ""
if environment is not None:
current_environment.update(environment)
# The API used to allow setting extra to None. We need to handle
this
# case for backwards compatibility.
- if current_environment["extra"] is None:
+ if "extra" in current_environment and current_environment["extra"]
is None:
current_environment["extra"] = ""
return _evaluate_markers(
@@ -321,11 +349,14 @@
)
-def _repair_python_full_version(env: dict[str, str]) -> dict[str, str]:
+def _repair_python_full_version(
+ env: dict[str, str | AbstractSet[str]],
+) -> dict[str, str | AbstractSet[str]]:
"""
Work around platform.python_version() returning something that is not PEP
440
compliant for non-tagged Python builds.
"""
- if env["python_full_version"].endswith("+"):
- env["python_full_version"] += "local"
+ python_full_version = cast(str, env["python_full_version"])
+ if python_full_version.endswith("+"):
+ env["python_full_version"] = f"{python_full_version}local"
return env
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/packaging-24.2/src/packaging/metadata.py
new/packaging-25.0/src/packaging/metadata.py
--- old/packaging-24.2/src/packaging/metadata.py 2024-11-08
10:41:39.083711000 +0100
+++ new/packaging-25.0/src/packaging/metadata.py 2025-04-19
13:45:16.857118800 +0200
@@ -678,8 +678,7 @@
)
if pathlib.PureWindowsPath(path).as_posix() != path:
raise self._invalid_metadata(
- f"{path!r} is invalid for {{field}}, "
- "paths must use '/' delimiter"
+ f"{path!r} is invalid for {{field}}, paths must use '/'
delimiter"
)
paths.append(path)
return paths
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/packaging-24.2/src/packaging/specifiers.py
new/packaging-25.0/src/packaging/specifiers.py
--- old/packaging-24.2/src/packaging/specifiers.py 2024-11-08
10:41:39.084588800 +0100
+++ new/packaging-25.0/src/packaging/specifiers.py 2025-04-19
13:45:16.857555200 +0200
@@ -816,8 +816,7 @@
specifier._prereleases = self._prereleases
else:
raise ValueError(
- "Cannot combine SpecifierSets with True and False prerelease "
- "overrides."
+ "Cannot combine SpecifierSets with True and False prerelease
overrides."
)
return specifier
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/packaging-24.2/src/packaging/tags.py
new/packaging-25.0/src/packaging/tags.py
--- old/packaging-24.2/src/packaging/tags.py 2024-11-08 10:41:39.084987400
+0100
+++ new/packaging-25.0/src/packaging/tags.py 2025-04-19 13:45:16.857928000
+0200
@@ -530,6 +530,43 @@
)
+def android_platforms(
+ api_level: int | None = None, abi: str | None = None
+) -> Iterator[str]:
+ """
+ Yields the :attr:`~Tag.platform` tags for Android. If this function is
invoked on
+ non-Android platforms, the ``api_level`` and ``abi`` arguments are
required.
+
+ :param int api_level: The maximum `API level
+ <https://developer.android.com/tools/releases/platforms>`__ to return.
Defaults
+ to the current system's version, as returned by
``platform.android_ver``.
+ :param str abi: The `Android ABI
<https://developer.android.com/ndk/guides/abis>`__,
+ e.g. ``arm64_v8a``. Defaults to the current system's ABI , as returned
by
+ ``sysconfig.get_platform``. Hyphens and periods will be replaced with
+ underscores.
+ """
+ if platform.system() != "Android" and (api_level is None or abi is None):
+ raise TypeError(
+ "on non-Android platforms, the api_level and abi arguments are
required"
+ )
+
+ if api_level is None:
+ # Python 3.13 was the first version to return platform.system() ==
"Android",
+ # and also the first version to define platform.android_ver().
+ api_level = platform.android_ver().api_level # type:
ignore[attr-defined]
+
+ if abi is None:
+ abi = sysconfig.get_platform().split("-")[-1]
+ abi = _normalize_string(abi)
+
+ # 16 is the minimum API level known to have enough features to support
CPython
+ # without major patching. Yield every API level from the maximum down to
the
+ # minimum, inclusive.
+ min_api_level = 16
+ for ver in range(api_level, min_api_level - 1, -1):
+ yield f"android_{ver}_{abi}"
+
+
def _linux_platforms(is_32bit: bool = _32_BIT_INTERPRETER) -> Iterator[str]:
linux = _normalize_string(sysconfig.get_platform())
if not linux.startswith("linux_"):
@@ -561,6 +598,8 @@
return mac_platforms()
elif platform.system() == "iOS":
return ios_platforms()
+ elif platform.system() == "Android":
+ return android_platforms()
elif platform.system() == "Linux":
return _linux_platforms()
else:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/packaging-24.2/tests/test_markers.py
new/packaging-25.0/tests/test_markers.py
--- old/packaging-24.2/tests/test_markers.py 2024-09-15 20:27:08.856824000
+0200
+++ new/packaging-25.0/tests/test_markers.py 2025-04-19 13:45:16.858205300
+0200
@@ -290,20 +290,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,
),
@@ -350,8 +347,7 @@
False,
),
(
- "python_version == '2.5' and platform.python_implementation"
- "!= 'Jython'",
+ "python_version == '2.5' and platform.python_implementation!=
'Jython'",
{"python_version": "2.7"},
False,
),
@@ -398,3 +394,35 @@
def test_python_full_version_untagged(self):
with mock.patch("platform.python_version", return_value="3.11.1+"):
assert Marker("python_full_version < '3.12'").evaluate()
+
+ @pytest.mark.parametrize("variable", ["extras", "dependency_groups"])
+ @pytest.mark.parametrize(
+ "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(self, variable, expression, result):
+ environment = {variable: {"foo", "bar"}}
+ assert Marker(expression.format(variable)).evaluate(environment) ==
result
+
+ @pytest.mark.parametrize("variable", ["extras", "dependency_groups"])
+ def test_extras_and_dependency_groups_disallowed(self, variable):
+ marker = 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")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/packaging-24.2/tests/test_tags.py
new/packaging-25.0/tests/test_tags.py
--- old/packaging-24.2/tests/test_tags.py 2024-10-03 22:21:49.600872800
+0200
+++ new/packaging-25.0/tests/test_tags.py 2025-04-19 13:45:16.858640700
+0200
@@ -77,6 +77,23 @@
monkeypatch.setattr(platform, "ios_ver", mock_ios_ver)
[email protected]
+def mock_android(monkeypatch):
+ monkeypatch.setattr(sys, "platform", "android")
+ monkeypatch.setattr(platform, "system", lambda: "Android")
+ monkeypatch.setattr(sysconfig, "get_platform", lambda:
"android-21-arm64_v8a")
+
+ AndroidVer = collections.namedtuple(
+ "AndroidVer", "release api_level manufacturer model device is_emulator"
+ )
+ monkeypatch.setattr(
+ platform,
+ "android_ver",
+ lambda: AndroidVer("5.0", 21, "Google", "sdk_gphone64_arm64",
"emu64a", True),
+ raising=False, # This function was added in Python 3.13.
+ )
+
+
class TestTag:
def test_lowercasing(self):
tag = tags.Tag("PY3", "None", "ANY")
@@ -437,6 +454,69 @@
]
+class TestAndroidPlatforms:
+ def test_non_android(self):
+ non_android_error = pytest.raises(TypeError)
+ with non_android_error:
+ list(tags.android_platforms())
+ with non_android_error:
+ list(tags.android_platforms(api_level=18))
+ with non_android_error:
+ list(tags.android_platforms(abi="x86_64"))
+
+ # The function can only be called on non-Android platforms if both
arguments are
+ # provided.
+ assert list(tags.android_platforms(api_level=18, abi="x86_64")) == [
+ "android_18_x86_64",
+ "android_17_x86_64",
+ "android_16_x86_64",
+ ]
+
+ def test_detection(self, mock_android):
+ assert list(tags.android_platforms()) == [
+ "android_21_arm64_v8a",
+ "android_20_arm64_v8a",
+ "android_19_arm64_v8a",
+ "android_18_arm64_v8a",
+ "android_17_arm64_v8a",
+ "android_16_arm64_v8a",
+ ]
+
+ def test_api_level(self):
+ # API levels below the minimum should return nothing.
+ assert list(tags.android_platforms(api_level=14, abi="x86")) == []
+ assert list(tags.android_platforms(api_level=15, abi="x86")) == []
+
+ assert list(tags.android_platforms(api_level=16, abi="x86")) == [
+ "android_16_x86",
+ ]
+ assert list(tags.android_platforms(api_level=17, abi="x86")) == [
+ "android_17_x86",
+ "android_16_x86",
+ ]
+ assert list(tags.android_platforms(api_level=18, abi="x86")) == [
+ "android_18_x86",
+ "android_17_x86",
+ "android_16_x86",
+ ]
+
+ def test_abi(self):
+ # Real ABI, normalized.
+ assert list(tags.android_platforms(api_level=16, abi="armeabi_v7a"))
== [
+ "android_16_armeabi_v7a",
+ ]
+
+ # Real ABI, not normalized.
+ assert list(tags.android_platforms(api_level=16, abi="armeabi-v7a"))
== [
+ "android_16_armeabi_v7a",
+ ]
+
+ # Nonexistent ABIs should still be accepted and normalized.
+ assert list(tags.android_platforms(api_level=16, abi="myarch-4.2")) ==
[
+ "android_16_myarch_4_2",
+ ]
+
+
class TestManylinuxPlatform:
def teardown_method(self):
# Clear the version cache
@@ -722,6 +802,7 @@
[
("Darwin", "mac_platforms"),
("iOS", "ios_platforms"),
+ ("Android", "android_platforms"),
("Linux", "_linux_platforms"),
("Generic", "_generic_platforms"),
],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/packaging-24.2/tests/test_utils.py
new/packaging-25.0/tests/test_utils.py
--- old/packaging-24.2/tests/test_utils.py 2023-10-01 14:58:59.375378600
+0200
+++ new/packaging-25.0/tests/test_utils.py 2025-04-19 13:45:16.858939600
+0200
@@ -123,6 +123,20 @@
(1000, "abc"),
{Tag("py3", "none", "any")},
),
+ (
+ "foo_bár-1.0-py3-none-any.whl",
+ "foo-bár",
+ Version("1.0"),
+ (),
+ {Tag("py3", "none", "any")},
+ ),
+ (
+ "foo_bár-1.0-1000-py3-none-any.whl",
+ "foo-bár",
+ Version("1.0"),
+ (1000, ""),
+ {Tag("py3", "none", "any")},
+ ),
],
)
def test_parse_wheel_filename(filename, name, version, build, tags):