Repository navigation
Conversation
llucax
force-pushed
the
alias-messages
branch
from
September 28, 2026 21:00
cdd6029 to
184e615
Compare
llucax
force-pushed
the
alias-messages
branch
3 times, most recently
from
October 5, 2026 14:11
434b45f to
39e2aa2
Compare
This was referenced Oct 5, 2026
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Generic fallback handling can render a different message from metadata supplied by an earlier extension.
Review effort: Balanced
Findings: 1
What changed in this PR
Updates deprecation parsing for frequenz-core v1.5.0’s per-alias API.
Changes:
- Parses
DeprecatedAliasentries and their individual messages or versions. - Adds best-effort generic notices for unreadable declarations.
- Updates documentation, fixtures, compatibility tests, and dependency pinning.
| File | Description |
|---|---|
src/griffe_frequenz_core/deprecations.py |
Implements new alias parsing and fallback notices. |
tests/test_deprecations.py |
Expands behavioral coverage. |
tests/test_warnings.py |
Tests warning emission. |
tests/compat/test_frequenz_core_compat.py |
Verifies runtime compatibility. |
tests/compat/fixture_aliases.py |
Adds real-core alias fixtures. |
tests/fixtures/samplepkg/statuses.py |
Updates enum fallback fixture. |
tests/fixtures/samplepkg/oldmod2.py |
Exercises module-qualified helpers. |
tests/fixtures/samplepkg/oldmod.py |
Migrates aliases to DeprecatedAlias. |
tests/fixtures/samplepkg/nonliteral.py |
Covers partially readable entries. |
tests/fixtures/samplepkg/edge.py |
Updates external-target aliases. |
tests/fixtures/samplepkg/constant.py |
Covers constant-held entries. |
tests/fixtures/numpymod.py |
Updates NumPy-style fixture. |
README.md |
Documents behavior and options. |
RELEASE_NOTES.md |
Records migration and fixes. |
pyproject.toml |
Pins frequenz-core 1.5.0 for tests. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Pin the test-only core dependency to the first release containing the final DeprecatedAlias API. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
`frequenz.core.warnings.deprecated_aliases()` no longer takes a dict
mapping every name to its target plus one call-level `message`: each
alias is now its own `DeprecatedAlias` entry passed positionally after
the module, giving either `since="v1.2.0"` or a `message` template of
its own, exactly one of them. This lets every alias say since which
version it is deprecated, which a single message for the whole table
could not. The dict form was never in a released `frequenz-core`, so it
is dropped here instead of being read alongside the new one.
Calls to the configured alias table functions are now read with the
signature `deprecated_aliases(module, /, *aliases)`: every positional
argument after the module must be a call to one of the new
`alias_classes` (by default `frequenz.core.warnings.DeprecatedAlias`),
bound as `DeprecatedAlias(name, /, *, new_module=None, new_name=None,
since=None, message=None)` with string literals, at least one of
`new_module` and `new_name`, and exactly one of `since` and `message`. A
keyword passed as `None` counts as not passed, as at runtime. The alias
points at `new_module`, or the module defining it when there is none,
followed by `new_name`, or its own name when there is none, the same way
core resolves it. Entries are read one by one, so one that cannot be
read is skipped with a debug log and the others are still marked.
Keyword arguments of the table call, such as `category` and
`stacklevel`, are ignored as before.
The deprecations guide separates the runtime warning, written for a
terminal, from the notice in the documentation, which says since which
version the symbol is deprecated and links what to use instead. So the
notice comes from `since` and the target only, and an entry's `message`
is never read: it is only the runtime warning. The `default_message`
option stays, with a new job: it is the template of that notice, and its
default is now ``Deprecated since {since}. Use {new_link} instead.``.
Unlike the runtime warning, it is only shown in the documentation of
the alias itself, so repeating its name adds nothing. `{old}` and
`{new}` are plain paths, and the new `{new_link}` links the target in
code font, by its name alone when it is in the same module, since the
context makes it obvious. `since` is inserted as written, braces
included, as core does. An entry giving `message` has no version to
say, so its notice only says what to use instead, and a hand-written one
can say more.
The link is a normal cross-reference rather than v1.0.0's optional
autoref, so a target that can't be resolved is reported by
`mkdocs-autorefs` instead of silently becoming plain text; a project
aliasing symbols from another one adds that project's inventory.
The fixtures move to the new form, mostly with `since`, and add an
import through a module alias (`w.DeprecatedAlias`), which Griffe
resolves to the real path.
Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
Until now only `deprecated_member()` was checked against a real
`frequenz-core`, since no release had `frequenz.core.warnings`. With
`deprecated_aliases()` and `DeprecatedAlias` available, a fixture now
declares four aliases, one giving `since`, one moved and renamed and
giving a message of its own, one renamed in the fixture itself, without
`new_module`, and one moved giving a message, and is both loaded by
Griffe and imported, so the documentation of each alias is compared with
the warning the real helper emits. A notice is worded for the
documentation, so it is not the runtime warning: the ones giving `since`
must say the same version and the same replacement, and the ones giving
a message must warn with it and document the same replacement the
runtime resolves.
The runtime `{old}` comes from the module's `__name__`, so Griffe loads
the fixture under the same dotted path pytest imported it as.
Two more tests pin the parameter layout the extension relies on:
`DeprecatedAlias(name, /, *, new_module=None, new_name=None, since=None,
message=None)` and `deprecated_aliases(module, /, *aliases, ...)` with
only keyword-only parameters after the entries.
Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
A wrapped enum member whose message comes from a constant or a helper
call, like `BREAKER = deprecated_member(7, _member_message("BREAKER"))`,
was left unmarked and rendered as the whole wrapper call, because the
value was only rewritten after the message had been read as a string
literal. The wrapper call alone says the member is deprecated, though:
only its message is unknown.
Once the call is known to bind exactly a value and a message, the value
is now rewritten regardless of the message, as written rather than
evaluated, and the member is marked with a generic message, `Deprecated.
It will be removed in a future release.`. Like any text the extension
writes itself, it is only shown in the docs of the member, so it doesn't
say which member it is, and it says nothing it cannot know. A message
another extension already set is used instead, in the field and the
admonition alike, and a hand-written notice is kept instead of the
generic one.
A wrapper whose arguments are unpacked from `*args` or `**kwargs` is
marked with the generic message too, since it deprecates the member all
the same, but its value is left as written, since the positions cannot
be trusted. A call that does not bind a value and a message would fail
at runtime, so it is still left alone.
Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
An alias entry was only documented when every one of its arguments was a string literal, so a `since` shared through a constant left the alias looking like a current symbol: no label, no notice, and its private type-checking value instead of the target. The name is all it takes to know what to mark, so it is now the only argument that has to be a literal; the message is never read anyway. The rest is used as far as it can be read: - The target is linked in the notice and shown as the value only when `new_module` and `new_name` can both be read. - `default_message` is used when `since` and the target are known and it can be formatted. - Otherwise a generic notice stands in for it, saying as much as is known, in the wording of `default_message`: `Deprecated since <since>. Use <new> instead.`, dropping ` since <since>` when the version is unknown and `Use <new> instead.` when the target is. With neither, it is the enum members' `Deprecated. It will be removed in a future release.`. What the notice can't say is logged at debug level. The same applies when the entry's keyword arguments are unpacked from a `**kwargs`, as long as the name is passed on its own: it is the only thing that can be known. An entry whose name cannot be read, or that would not bind at runtime, is still skipped, since it either names nothing or deprecates nothing. A bad `default_message` now falls back to the generic notice too, instead of leaving `since` entries unmarked. This mirrors enum members, which are marked with the same generic notice when their message cannot be read. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
Whatever the extension could not read was only logged at debug level, so the documentation could quietly show less than the code says, and nobody noticed unless they ran `mkdocs build --verbose` and looked. The deprecations guide treats the notice as the only channel that reaches users of an alias or an enum member, and asks it to say since which version the symbol is deprecated and what to use instead, so a notice short of that should not pass silently. Every such case is now logged as a warning, so a `mkdocs build --strict` fails until it is fixed, and a project that prefers not to fail on these can build without `--strict`: - A notice that can't say since which version or what to use instead, because an argument cannot be read or an alias gives a message instead of `since`, and a generic notice standing in for an enum message that cannot be read. - An enum member with only its runtime warning, which is then shown as its notice: the wrapper can't say more, so the guide asks for a hand-written notice. - A value left as written: an alias whose target cannot be read, or an enum member whose wrapper arguments are unpacked. - A valid alias entry that cannot be documented at all, since its name cannot be read. - A call whose arguments don't bind the way the runtime binds them, such as a wrapper or an alias entry with missing arguments: the documentation doesn't show it as a deprecation either. Argument values are not validated beyond that: documenting the code is not linting it, and the project's own tests catch a call that fails at import. A hand-written notice, or a message another extension found, rules out the ones about the notice, since the documentation is complete then. Why something could not be read is still logged at debug level. The tests go in a module of their own. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
A generated notice goes at the very top of the docstring, above the summary, while a hand-written one can only come after the summary, since a docstring has to start with it. A page mixing both showed the notices in different places, and the deprecations guide asks for a hand-written notice wherever the helper can't generate a complete one, which for an enum member is always. When the extension marks an alias or an enum member whose docstring already has a deprecation notice, it now moves that notice to the top, where a generated one would go. Only objects the extension marks are touched: anywhere else, such as a function documenting one deprecated argument, a `Deprecated:` section doesn't mean the whole object is deprecated, so it stays where it was written. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
The enum member examples used messages like "PENDING is deprecated, use OPEN instead", while the deprecations guide asks for runtime warnings starting with the plain fully qualified name and saying what to use instead, also by its fully qualified name, and for a hand-written notice saying since which version and linking the replacement, since the wrapper only carries the warning. The guide's own-deprecations pytest filter relies on the first part, and these examples are what people copy, so they now follow it. The README keeps one member without a notice to show what happens then. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
The rework of this release settled a few rules that are easy to break again in a later change, mainly that the extension follows the deprecations guide's split between the runtime warning and the notice, that anything short of what the guide asks for must warn instead of passing silently, that a hand-written notice always wins, that the extension's own text is docs-only, that links are never optional, and that calls are read the way the runtime binds them without validating argument values. They are written down for agents and contributors alike, kept short and general. It is left out of the source distribution, like `CONTRIBUTING.md`. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
Replaces the first release's notes with the ones for the next release,
a fix release: the dict form v1.0.0 read never made it into a
`frequenz-core` release, so reading the released `DeprecatedAlias` form
instead is a bug fix, and so are the notices following the deprecations
guide and the generic notices. The changed meaning, fields and default
of `default_message` go under "Upgrading", since a value set for v1.0.0
has no `{since}` and no longer gets a link for `{new}`, and so do the
alias `message` no longer being documented, the hand-written notices
enum members now need, and the new warnings, since they can make a
strict build fail where v1.0.0 passed.
Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Reads the final call shape of
frequenz.core.warnings.deprecated_aliases()released in frequenz-core v1.5.0, where every alias is aDeprecatedAliasentry saying where the symbol is now (new_module,new_nameor both) and eithersince="vX.Y.Z"or amessageof its own. The dict form v1.0.0 read never made it into a core release, so it is dropped.Notices follow the deprecations guide, which separates the runtime warning, written for a terminal, from the notice in the documentation, which says since which version and links what to use instead:
sinceand its target, throughdefault_message, nowDeprecated since {since}. Use {new_link} instead.: the reader is already looking at the alias, so it doesn't repeat its name, and the new{new_link}field links the target in code font, by its name alone when it is in the same module. An alias'messageis only its runtime warning and is never read.Deprecated:notice always replaces the generated one, and on aliases and enum members it is moved to the top of the docstring, where generated notices go.Deprecations whose arguments can't be read statically are documented on a best-effort basis instead of being left unmarked, the same way for enum members and aliases: a generic notice says as much as can be read (
Deprecated[ since V].[ Use [`Y`][] instead.], orDeprecated. It will be removed in a future release.when neither is known), and enum values are unwrapped even then. Anything short of what the guide asks for is a warning, so strict builds catch it: a notice without the version or the replacement, a runtime warning shown as the notice, a value left as written, a deprecation left unmarked, a call that doesn't bind the way the runtime binds it, or a link that can't be resolved. Argument values aren't validated beyond that, since documenting the code isn't linting it. Reading module-level constants is left for #8, reading the structured forms proposed in frequenz-floss/frequenz-core-python#206 for #10, and handling@deprecatedtoo for #9. The design rules behind all this are in a new, shortAGENTS.md.This is meant as v1.0.1: what it drops only ever matched unreleased core code. The release notes cover what a v1.0.0 user can notice: the new
default_messageand its fields, the aliasmessageno longer being documented, the hand-written notices enum members need, and the new warnings. The test-only core dependency is pinned to the releasedfrequenz-core == 1.5.0and is still absent from runtime dependencies.