PEP 749: classmethod and staticmethod do not implement annotation wrapper semantics
Author: youknowoneCreated Aug 11, 2026Updated Aug 12, 2026
LabelsC-compat
Feature
PEP 749 specifies writable __annotate__ and __annotations__ attributes for classmethod and staticmethod. Reading should retrieve and cache the wrapped callable's value in the wrapper's __dict__; writing should update only the wrapper, not the wrapped callable.
Minimal reproduction:
def f() -> Missing:
pass
for wrapper in (classmethod(f), staticmethod(f)):
Missing = int
print(type(wrapper).__name__, wrapper.__annotations__)
print("__annotations__" in wrapper.__dict__)
wrapper.__annotations__ = {"x": str}
print("wrapper:", wrapper.__annotations__)
print("wrapped:", f.__annotations__)
CPython 3.14.6 caches __annotations__ in each wrapper and leaves f.__annotations__ unchanged after assignment.
RustPython does not cache the delegated value in the wrapper for the unresolved-name case, and assignment mutates the wrapped function's annotations. This is already represented by the expectedFailure marker on ClassPropertiesAndMethods.test_classmethod_staticmethod_annotations in Lib/test/test_descr.py.
Python Documentation or reference to CPython source code
- PEP 749, “Wrappers that provide
__annotations__”: https://peps.python.org/pep-0749/#wrappers-that-provide-annotations - CPython regression test: https://github.com/python/cpython/blob/3.14/Lib/test/test_descr.py
Source: RustPython/RustPython