commit: b6d98b9ed55e3cc9aeda8d4959d5c957a6432e53
Author: Brian Harring <ferringb <AT> gmail <DOT> com>
AuthorDate: Sat Dec 13 21:48:20 2025 +0000
Commit: Brian Harring <ferringb <AT> gmail <DOT> com>
CommitDate: Mon Dec 15 12:42:09 2025 +0000
URL:
https://gitweb.gentoo.org/proj/pkgcore/snakeoil.git/commit/?id=b6d98b9e
chore: push current versions into the registry directly.
This simplifies expired_deprecations, simplifying the tool
being added that will be used for changelog additions.
Signed-off-by: Brian Harring <ferringb <AT> gmail.com>
src/snakeoil/_internals.py | 9 +++++--
src/snakeoil/deprecation/__init__.py | 48 ++++++++++++++++++++++++------------
src/snakeoil/test/code_quality.py | 6 +----
tests/test_code_quality.py | 2 --
tests/test_deprecation.py | 45 +++++++++++++++++++--------------
5 files changed, 66 insertions(+), 44 deletions(-)
diff --git a/src/snakeoil/_internals.py b/src/snakeoil/_internals.py
index 1641120..d7ed23f 100644
--- a/src/snakeoil/_internals.py
+++ b/src/snakeoil/_internals.py
@@ -1,9 +1,14 @@
__all__ = ("deprecated",)
+import snakeoil
from snakeoil.deprecation import Registry
-deprecated = Registry("snakeoil")
+deprecated = Registry(
+ "snakeoil",
+ version=snakeoil.__version_info__,
+ python_mininum_version=snakeoil.__python_mininum_version__,
+)
# See Registry implementation
deprecated.code_directive(
"snakeoil.deprecation.Registry.is_enabled will always have
warnings.deprecated, this must be updated.",
- removal_in_py=(3, 13, 0),
+ removal_in_python=(3, 13, 0),
)
diff --git a/src/snakeoil/deprecation/__init__.py
b/src/snakeoil/deprecation/__init__.py
index 83067a3..443aab1 100644
--- a/src/snakeoil/deprecation/__init__.py
+++ b/src/snakeoil/deprecation/__init__.py
@@ -149,13 +149,13 @@ warning_category: typing.TypeAlias = type[Warning]
class Record:
msg: str
removal_in: Version | None = None
- removal_in_py: Version | None = None
+ removal_in_python: Version | None = None
def _collect_strings(self) -> typing.Iterator[str]:
if self.removal_in:
yield "removal in version=" + (".".join(map(str, self.removal_in)))
- if self.removal_in_py:
- yield "removal in python=" + (".".join(map(str,
self.removal_in_py)))
+ if self.removal_in_python:
+ yield "removal in python=" + (".".join(map(str,
self.removal_in_python)))
yield f"reason: {self.msg}"
def __str__(self) -> str:
@@ -211,6 +211,8 @@ class Registry:
"record_class",
"_qualname",
"_qualname_suppressions",
+ "version",
+ "python_mininum_version",
)
record_class: type[RecordCallable]
@@ -230,6 +232,8 @@ class Registry:
project: str,
/,
*,
+ version: Version,
+ python_mininum_version: Version,
qualname: str | None = None,
record_class: type[RecordCallable] = RecordCallable,
qualname_suppressions: typing.Sequence[str] = (),
@@ -237,6 +241,8 @@ class Registry:
self.project = project
self._qualname = qualname if qualname is not None else project
self._qualname_suppressions = tuple(qualname_suppressions)
+ self.version = version
+ self.python_mininum_version = python_mininum_version
# TODO: py3.13, change this to T per the cvar comments
self.record_class = record_class
self._deprecations: list[Record | RecordCallable] = []
@@ -248,7 +254,7 @@ class Registry:
/,
*,
removal_in: Version | None = None,
- removal_in_py: Version | None = None,
+ removal_in_python: Version | None = None,
qualname: str | None = None,
category=DeprecationWarning,
stacklevel=1,
@@ -269,7 +275,7 @@ class Registry:
r = self.record_class(
msg,
removal_in=removal_in,
- removal_in_py=removal_in_py,
+ removal_in_python=removal_in_python,
qualname=qualname,
**kwargs,
)
@@ -278,7 +284,7 @@ class Registry:
functor,
msg,
removal_in=removal_in,
- removal_in_py=removal_in_py,
+ removal_in_python=removal_in_python,
**kwargs,
)
self._deprecations.append(r)
@@ -290,13 +296,13 @@ class Registry:
self,
msg: str,
removal_in: Version | None = None,
- removal_in_py: Version | None = None,
+ removal_in_python: Version | None = None,
) -> None:
- if not removal_in and not removal_in_py:
- raise ValueError("either removal_in or removal_in_py must be set")
+ if not removal_in and not removal_in_python:
+ raise ValueError("either removal_in or removal_in_python must be
set")
"""Add a directive in the code that if invoked, records the
deprecation"""
self._deprecations.append(
- Record(msg=msg, removal_in=removal_in, removal_in_py=removal_in_py)
+ Record(msg=msg, removal_in=removal_in,
removal_in_python=removal_in_python)
)
def module(
@@ -304,7 +310,7 @@ class Registry:
msg: str,
qualname: str,
removal_in: Version | None = None,
- removal_in_py: Version | None = None,
+ removal_in_python: Version | None = None,
) -> None:
"""Deprecation notice that fires for the first import of this
module."""
if not self.is_enabled:
@@ -314,7 +320,7 @@ class Registry:
msg,
qualname=qualname,
removal_in=removal_in,
- removal_in_py=removal_in_py,
+ removal_in_python=removal_in_python,
)
)
# fire the warning; we're triggering it a frame deep from the actual
issue (the module itself), thus adjust the stack level
@@ -337,10 +343,20 @@ class Registry:
def expired_deprecations(
self,
- project_version: Version,
- python_version: Version,
+ /,
force_load=True,
+ project_version: Version | None = None,
+ python_version: Version | None = None,
) -> typing.Iterator[Record]:
+ """Enumerate the deprecations that exceed the minimum versions
+
+ By default it uses the registries configured norms, but for evaluation
of things
+ to resolve for upcoming releases, you can override the versioning used.
+ """
+ project_version = self.version if project_version is None else
project_version
+ python_version = (
+ self.python_mininum_version if python_version is None else
python_version
+ )
if force_load:
for _ in get_submodules_of(
self._qualname, dont_import=self._qualname_suppressions
@@ -353,7 +369,7 @@ class Registry:
):
yield deprecation
elif (
- deprecation.removal_in_py is not None
- and python_version >= deprecation.removal_in_py
+ deprecation.removal_in_python is not None
+ and python_version >= deprecation.removal_in_python
):
yield deprecation
diff --git a/src/snakeoil/test/code_quality.py
b/src/snakeoil/test/code_quality.py
index 13ec9a2..6088dbe 100644
--- a/src/snakeoil/test/code_quality.py
+++ b/src/snakeoil/test/code_quality.py
@@ -119,16 +119,12 @@ class ExpiredDeprecations(NamespaceCollector,
still_abstract=True):
strict = ("test_has_expired_deprecations",)
registry: deprecation.Registry = abstractclassvar(deprecation.Registry)
- version: deprecation.Version = abstractclassvar(deprecation.Version)
- python_minimum_version: deprecation.Version =
abstractclassvar(deprecation.Version)
def test_has_expired_deprecations(self, subtests):
# force full namespace load to ensure all deprecations get registry.
with deprecation.suppress_deprecations():
for _ in self.collect_modules():
pass
- for deprecated in self.registry.expired_deprecations(
- self.version, self.python_minimum_version
- ):
+ for deprecated in self.registry.expired_deprecations():
with subtests.test(deprecated=str(deprecated)):
pytest.fail(f"deprecation has expired: {deprecated}")
diff --git a/tests/test_code_quality.py b/tests/test_code_quality.py
index 31a13d4..35abb1b 100644
--- a/tests/test_code_quality.py
+++ b/tests/test_code_quality.py
@@ -41,5 +41,3 @@ class TestModules(code_quality.Modules):
class TestExpiredDeprecations(code_quality.ExpiredDeprecations):
namespaces = ("snakeoil",)
registry = snakeoil._internals.deprecated
- version = snakeoil.__version_info__
- python_minimum_version = snakeoil.__python_mininum_version__
diff --git a/tests/test_deprecation.py b/tests/test_deprecation.py
index b9a3e0e..83d667b 100644
--- a/tests/test_deprecation.py
+++ b/tests/test_deprecation.py
@@ -21,12 +21,14 @@ requires_enabled = pytest.mark.skipif(
class TestRegistry:
+ default_versions = dict(version=(10, 0, 0), python_mininum_version=(10, 0,
0))
+
def test_is_enabled(self):
assert (sys.version_info >= (3, 13, 0)) == Registry.is_enabled
@requires_enabled
def test_it(self):
- r = Registry("tests")
+ r = Registry("tests", **self.default_versions)
assert "tests" == r.project
assert [] == list(r)
assert not r
@@ -54,9 +56,9 @@ class TestRegistry:
== list(r)[-1]
)
- r("test3", removal_in_py=(4, 0, 0), qualname="test3")(f)
+ r("test3", removal_in_python=(4, 0, 0), qualname="test3")(f)
assert (
- RecordCallable("test3", qualname="test3", removal_in_py=(4, 0, 0))
+ RecordCallable("test3", qualname="test3", removal_in_python=(4, 0,
0))
) == list(r)[-1]
class MyDeprecation(DeprecationWarning): ...
@@ -69,7 +71,7 @@ class TestRegistry:
Registry.is_enabled, reason="test is only for python 3.12 and lower"
)
def test_disabled(self):
- r = Registry("tests")
+ r = Registry("tests", **self.default_versions)
def f(): ...
@@ -96,7 +98,7 @@ class TestRegistry:
@requires_enabled
def test_subclassing(self):
# just assert record class can be extended- so downstream can add more
metadata.
- assert RecordCallable is Registry("asdf").record_class
+ assert RecordCallable is Registry("asdf",
**self.default_versions).record_class
@dataclasses.dataclass(slots=True, frozen=True, kw_only=True)
class MyRecord(RecordCallable):
@@ -105,7 +107,7 @@ class TestRegistry:
def f(): ...
- r = Registry("test", record_class=MyRecord)
+ r = Registry("test", record_class=MyRecord, **self.default_versions)
r("asdf", extra_val1=3, extra_val2=4, qualname="myrecord")(f)
assert 1 == len(r)
@@ -121,15 +123,15 @@ class TestRegistry:
@requires_enabled
def test_expired_deprecations(self):
- r = Registry("asdf")
+ r = Registry("asdf", **self.default_versions)
def f(): ...
- r("python", removal_in_py=(1, 0, 0))(f)
+ r("python", removal_in_python=(1, 0, 0))(f)
r("project", removal_in=(1, 0, 0))(f)
r(
"combined",
- removal_in_py=(
+ removal_in_python=(
2,
0,
0,
@@ -139,25 +141,29 @@ class TestRegistry:
assert 3 == len(r)
assert [] == list(
- r.expired_deprecations((0, 0, 0), (0, 0, 0), force_load=False)
+ r.expired_deprecations(
+ python_version=(0, 0, 0), project_version=(0, 0, 0),
force_load=False
+ )
)
assert ["python"] == [
x.msg
for x in r.expired_deprecations(
- (0, 0, 0), python_version=(1, 0, 0), force_load=False
+ project_version=(0, 0, 0), python_version=(1, 0, 0),
force_load=False
)
]
assert ["project"] == [
x.msg
for x in r.expired_deprecations(
- (1, 0, 0), python_version=(0, 0, 0), force_load=False
+ project_version=(1, 0, 0), python_version=(0, 0, 0),
force_load=False
)
]
assert ["combined", "project", "python"] == list(
sorted(
x.msg
for x in r.expired_deprecations(
- (2, 0, 0), python_version=(2, 0, 0), force_load=False
+ project_version=(2, 0, 0),
+ python_version=(2, 0, 0),
+ force_load=False,
)
)
)
@@ -165,13 +171,14 @@ class TestRegistry:
# this is the seul registry functionality which still will test validly in
<py3.13. We flex
# it solely to confirm we're not causing runtime issues in those
environments.
def test_code_directive(self):
- r = Registry("test")
+ r = Registry("test", **self.default_versions)
assert None is r.code_directive(
- "asdf", removal_in=(1, 0, 0), removal_in_py=(2, 0, 0)
+ "asdf", removal_in=(1, 0, 0), removal_in_python=(2, 0, 0)
)
assert 1 == len(r)
assert (
- Record("asdf", removal_in=(1, 0, 0), removal_in_py=(2, 0, 0)) ==
list(r)[0]
+ Record("asdf", removal_in=(1, 0, 0), removal_in_python=(2, 0, 0))
+ == list(r)[0]
)
@requires_enabled
@@ -183,7 +190,7 @@ class TestRegistry:
dedent(
"""
from snakeoil.deprecation import Registry
- Registry("test").module('deprecation test', 'this_is_deprecated')
+ Registry("test", version=(0,0,0),
python_mininum_version=(1,0,0)).module('deprecation test',
'this_is_deprecated', removal_in_python=(1,0,0))
"""
)
)
@@ -290,13 +297,13 @@ class TestRegistry:
def test_RecordModule_str():
assert "module='foon.blah', removal in python=3.0.2, reason: why not" ==
str(
- RecordModule("why not", qualname="foon.blah", removal_in_py=(3, 0, 2))
+ RecordModule("why not", qualname="foon.blah", removal_in_python=(3, 0,
2))
)
def test_Record_str():
assert "removal in version=1.0.2, removal in python=3.0.2, reason: blah"
== str(
- Record("blah", removal_in=(1, 0, 2), removal_in_py=(3, 0, 2))
+ Record("blah", removal_in=(1, 0, 2), removal_in_python=(3, 0, 2))
)