You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
(Adding the issue here rather than the CPython repo since the PEP 649 implementation hasn't landed yet)
Since Python 3.2, functools.update_wrapper has eagerly copied o.__annotations__ from the wrapped object to the wrapper object.
This will do the wrong thing under PEP 649, since it will trigger early evaluation of the annotations on wrapped functions (and hence potentially fail if the annotations contain forward references).
I think the following changes will be sufficient to resolve the incompatibility:
remove __annotations__ from the default WRAPPER_ASSIGNMENTS list
set __annotate__ on the wrapper object as described below
update function docs accordingly
For maximum compatibility, I think the wrapper annotations will need to be retrieved as follows:
def__annotate__(format):
ifformat==1:
returnwrapped.__annotations__# Ensure previously cached annotations are respectedimportinspect# Ugh, maybe the guts of `get_annotations` could live down in `functools`?returninspect.get_annotations(wrapped, format)
wrapper.__annotate__=__annotate__
I initially thought we could just add __annotate__ to WRAPPER_ASSIGNMENTS, but I realised that doesn't play nice if a previous decorator has already eagerly evaluated the annotations, and perhaps modified them (in which case, wrapped.__annotate__ may even be None if the other decorator has been updated to behave as PEP 649 recommends).
The comment in the implementation sketch relates to the fact that inspect imports functools, so having functools depend on an inspect API introduces a circular dependency. Perhaps the piece that update_wrapper needs could be factored out to a lower level functools._get_annotations helper API that inspect.get_annotations also invokes? If we did that, the PEP 649 compatible update_wrapper code would become:
(Adding the issue here rather than the CPython repo since the PEP 649 implementation hasn't landed yet)
Since Python 3.2,
functools.update_wrapper
has eagerly copiedo.__annotations__
from the wrapped object to the wrapper object.This will do the wrong thing under PEP 649, since it will trigger early evaluation of the annotations on wrapped functions (and hence potentially fail if the annotations contain forward references).
I think the following changes will be sufficient to resolve the incompatibility:
__annotations__
from the defaultWRAPPER_ASSIGNMENTS
list__annotate__
on the wrapper object as described belowFor maximum compatibility, I think the wrapper annotations will need to be retrieved as follows:
I initially thought we could just add
__annotate__
toWRAPPER_ASSIGNMENTS
, but I realised that doesn't play nice if a previous decorator has already eagerly evaluated the annotations, and perhaps modified them (in which case,wrapped.__annotate__
may even beNone
if the other decorator has been updated to behave as PEP 649 recommends).The comment in the implementation sketch relates to the fact that
inspect
importsfunctools
, so havingfunctools
depend on aninspect
API introduces a circular dependency. Perhaps the piece thatupdate_wrapper
needs could be factored out to a lower levelfunctools._get_annotations
helper API thatinspect.get_annotations
also invokes? If we did that, the PEP 649 compatibleupdate_wrapper
code would become:The text was updated successfully, but these errors were encountered: