Skip to content

PEP 649: functools.update_wrapper implementation #124342

Closed
@JelleZijlstra

Description

@JelleZijlstra

The current implementation of PEP-649 and PEP-749 on main simply copies functions' __annotate__ in functools.update_wrapper (and thence functools.wraps):

>>> def f(x: y): pass
... 
>>> from functools import wraps
>>> @wraps(f)
... def g(x): pass
... 
>>> g.__annotate__ is f.__annotate__
True

But as @ncoghlan pointed out (larryhastings/co_annotations#21, https://discuss.python.org/t/pep-749-implementing-pep-649/54974/4), this may not be what we want in the case where the original function's __annotations__ have been modified:

>>> def f(x: int): pass
... 
>>> f.__annotations__["x"] = 42
>>> @wraps(f)
... def g(x): pass
... 
>>> f.__annotations__
{'x': 42}
>>> g.__annotations__
{'x': <class 'int'>}

Alyssa therefore suggests making update_wrapper create a wrapper __annotate__ function that looks in the original function's __annotations__ first. This doesn't fit neatly into update_wrapper's current structure of WRAPPER_ASSIGNMENTS and WRAPPER_UPDATES, so we should add a third bucket, maybe WRAPPER_DELEGATIONS.

Linked PRs

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions