Skip to content

Preserve variadic annotations in formatargspec - #363

Merged
GrahamDumpleton merged 1 commit into
GrahamDumpleton:developfrom
galafis:fix-formatargspec-variadic-annotations
Oct 30, 2026
Merged

GrahamDumpleton merged 1 commit into
GrahamDumpleton:developfrom
galafis:fix-formatargspec-variadic-annotations

Conversation

@galafis

@galafis galafis commented Oct 24, 2026

Copy link
Copy Markdown
Contributor

formatargspec(*getfullargspec(function)) loses annotations on *args and **kwargs while preserving positional, keyword-only and return annotations. For example, a function declared as def f(*args: int, **kwargs: str) produces (*args, **kwargs).

Pass each variadic parameter annotation into inspect.Parameter, using Parameter.empty when none is supplied. Add separate regressions for both parameter kinds and one mixed signature, retaining the existing unannotated controls.

Before the fix, all three new regressions fail and both existing tests pass. Afterward, the core suite on Windows/Python 3.12.14 reports 1376 passed, 8 skipped and 43 subtests passed. Black 26.10.1 and git diff --check pass.

Testing limitations: the editable source build selected the pure Python implementation (wrapt.wrappers); the core suite also passes with WRAPT_DISABLE_EXTENSIONS=true. No compiled C extension was available, so this is not C-extension validation. The complete Justfile Python-version/build matrix and mypy matrix were not run in this Windows environment.

@GrahamDumpleton

Copy link
Copy Markdown
Owner

Thanks, this is correct and I'll merge it. For the record, the practical
impact is smaller than the description might suggest.

The only caller of formatargspec() within wrapt is the adapter argument
of wrapt.decorator, when it is passed an argument specification tuple
rather than a callable. That code path deliberately strips the annotations
from the tuple before calling formatargspec(), since the resulting string
is compiled in an empty namespace where non builtin names in annotations
would not resolve, and then assigns the annotations dict directly onto the
generated adapter function. So annotations on *args and **kwargs were
already preserved for adapters, and this change does not alter what
wrapt.decorator produces.

The adapter mechanism itself is planned for deprecation in favour of
wrapt.with_signature, which works from inspect.Signature objects and
never needs to render a signature as a string. The wrapt.arguments module
is only retained to support adapter until then and is not part of the
documented public API, so nothing outside wrapt should be calling
formatargspec() directly. Still, as it is intended as a stand in for the
removed inspect.formatargspec(), it is better that it behave the same way,
so the fix is welcome.

I'll add a change log entry on develop after merging.

@GrahamDumpleton
GrahamDumpleton merged commit 36306dc into GrahamDumpleton:develop Oct 30, 2026
28 of 40 checks passed
GrahamDumpleton added a commit that referenced this pull request Oct 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants