Skip to content

PEP 649: functools.update_wrapper implementation#124342

@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