[NO-SQUASH-MERGE] fix varnames on py3.14 deferred annotations#632
[NO-SQUASH-MERGE] fix varnames on py3.14 deferred annotations#632RonnyPfannschmidt wants to merge 9 commits intopytest-dev:mainfrom
Conversation
3624358 to
e67e13d
Compare
There was a problem hiding this comment.
Pull request overview
Fixes pluggy._hooks.varnames() to avoid inspect.signature() on Python 3.14+ (where deferred/string annotations may be resolved and can fail), and adds coverage + benchmarks around the new behavior.
Changes:
- Reimplements
varnames()using__code__,__defaults__, and__qualname__instead ofinspect.signature(). - Adds a regression test for annotations that cannot be resolved at runtime.
- Extends benchmark suite to compare the new implementation against a legacy
inspect.signature()version.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/pluggy/_hooks.py |
Updates varnames() implementation to avoid annotation resolution and reduce overhead. |
testing/test_helpers.py |
Adds a regression test ensuring varnames() works with unresolvable string annotations. |
testing/benchmark.py |
Adds microbenchmarks comparing new vs legacy varnames() approaches. |
Comments suppressed due to low confidence (1)
src/pluggy/_hooks.py:298
- Typo in the
varnamesdocstring: "keywrord" should be "keyword".
def varnames(func: object) -> tuple[tuple[str, ...], tuple[str, ...]]:
"""Return tuple of positional and keywrord argument names for a function,
method, class or callable.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
b93eafb to
9d852b3
Compare
In Python 3.14+, annotations are evaluated lazily per PEP 649/749. When inspect.signature() is called, it tries to resolve annotations by default, which fails if the annotation references an undefined type. Add a version-gated _signature helper that uses annotation_format=annotationlib.Format.STRING on Python 3.14+ to prevent annotation resolution errors. Fixes pytest-dev#629 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Use code object attributes (co_varnames, co_argcount) and __defaults__ directly instead of inspect.signature(). This avoids annotation resolution entirely, which is simpler and more efficient. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Include both the current implementation and the legacy inspect.signature-based version to clearly demonstrate the ~7-66x speedup from using code objects directly. Co-authored-by: Cursor AI <ai@cursor.sh> Co-authored-by: Anthropic Claude Opus 4 <claude@anthropic.com>
9d852b3 to
d2775b4
Compare
Co-authored-by: Cursor AI <ai@cursor.sh> Co-authored-by: Anthropic Claude Opus 4 <claude@anthropic.com>
A module-level function assigned to a class attribute becomes a bound method on instances, but its __qualname__ has no dot. Track whether the original callable was a bound method before unwrapping to __func__, so self is always stripped for bound methods. Co-authored-by: Cursor AI <ai@cursor.sh> Co-authored-by: Anthropic Claude Opus 4 <claude@anthropic.com>
Replace exec()-based test with a direct function definition. The string annotation "NonExistentType" triggers the same behavior without the indirection. Co-authored-by: Cursor AI <ai@cursor.sh> Co-authored-by: Anthropic Claude Opus 4 <claude@anthropic.com>
Co-authored-by: Cursor AI <ai@cursor.sh> Co-authored-by: Anthropic Claude Opus 4 <claude@anthropic.com>
There was a problem hiding this comment.
I'm a bit wary of stopping to use inspect.signature. It means we drop support for stuff like __signature__ and __text_signature__ and whatever weird stuff inspect.signature supports.
The performance is definitely nice but if I'm not mistaken varnames is only used #hookspecs + #hookimpls times so not very performance critical.
Nonetheless, if you think it should be fine, I would at least suggest running some downstream tests (see downstream/ directory) to make sure there are no regressions (I usually run it before release).
…lusion Co-authored-by: Cursor AI <ai@cursor.sh> Co-authored-by: Anthropic Claude Opus 4 <claude@anthropic.com>
Co-authored-by: Cursor AI <ai@cursor.sh> Co-authored-by: Anthropic Claude Opus 4 <claude@anthropic.com> Made-with: Cursor
38ea6af to
cb5edb6
Compare
|
fixing the downstream tests now (scripts are bitrot affected) |
closes #629
using direct attributes instead of signature to avoid the extra objects