-
-
Notifications
You must be signed in to change notification settings - Fork 30.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PEP 649: functools.update_wrapper
implementation
#124342
Comments
The PR failed a test in test_inspect. The test looks like this:
This is because we now unconditionally set an What should we do here?
|
After thinking about this some more and looking at the examples @vstinner posted on the PR (#124346 (comment)), I now prefer to stick with the implementation that is currently on main, which is to copy
On the negative side, it does not preserve the previous behavior in cases where the annotations dict is modified before the function is wrapped, like in @ncoghlan's example in larryhastings/co_annotations#21. But code that modifies annotations is always on thin ground; I think in the long term we're better off with a simpler implementation. |
I wonder if we could add back the copying of already created annotations, but special-case it to avoid triggering evaluation of not-yet-created lazy annotations. That is:
The generalised version of the idea would be a module level set specifying "known lazy attributes" that are only assigned/updated if they already exist in the instance dictionary. I'm less concerned about the "annotations have been modified" case (that was just an easy demonstration) and more about the "annotations have been defined, but an annotate function has not" case. Edit: fixed to make it clear that the wrapper's annotation dict is still separate from the wrapped object's annotations. |
For functions, the annotations are not in the instance dictionary, so it can't work exactly as you described, and indeed there isn't a way to ask a function object "do you already have cached
I don't think updating (as in
This can never happen with builtin objects (classes, functions, modules); they always have both or neither. Of course, user-defined objects could do this. One approach could be to copy |
The current implementation of PEP-649 and PEP-749 on main simply copies functions'
__annotate__
infunctools.update_wrapper
(and thencefunctools.wraps
):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: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 intoupdate_wrapper
's current structure of WRAPPER_ASSIGNMENTS and WRAPPER_UPDATES, so we should add a third bucket, maybe WRAPPER_DELEGATIONS.Linked PRs
The text was updated successfully, but these errors were encountered: