Skip to content
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

Accessing a class attribute that is a wrapped function raises an AttributeError #264

Open
contrast-jproberts opened this issue May 21, 2024 · 2 comments

Comments

@contrast-jproberts
Copy link

This issue is similar to #256 , but throws a different exception that might be easier to resolve.

Reproducer

> python --version
Python 3.9.6
> pip show wrapt
Name: wrapt
Version: 1.16.0
Summary: Module for decorators, wrappers and monkey patching.
Home-page: https://github.com/GrahamDumpleton/wrapt
Author: Graham Dumpleton
Author-email: [email protected]
License: BSD
Location: ~/scratch/.venv/lib/python3.9/site-packages
Requires:
import wrapt


@wrapt.patches.patch_function_wrapper("operator", "add")
def passthrough(wrapped, instance, args, kwargs):
    return wrapped(*args, **kwargs)


import operator


class A:
    add = operator.add


print(type(A.add))
print(A.add(1, 2))

Running this program gives

Traceback (most recent call last):
  File "~/scratch/wrapt_bug.py", line 16, in <module>
    print(type(A.add))
AttributeError: 'builtin_function_or_method' object has no attribute '__get__'

If the wrapt patches are removed (commenting out everything before line 9 (import operator)), the program runs as expected

<class 'builtin_function_or_method'>
3

Additional Details

The AttributeError is being thrown on

descriptor = self.__wrapped__.__get__(instance, owner)

Experimenting locally, I found that updating the condition from

if not inspect.isclass(self.__wrapped__):
if not inspect.isclass(self.__wrapped__) and not inspect.isbuiltin(self.__wrapped__):

passes my tests, which include more complex uses than the reproducer I showed. I don't have a very complete understanding of descriptors though, so I may be overlooking edge cases. My change to update the condition based on isbuiltin was inspired by this StackOverflow answer: https://stackoverflow.com/a/52140735 . Hopefully it helps guide you all if I misunderstood the response.

Lastly, I'm new to wrapt and tried to read through all the documentation before opening this issue. If I'm misusing the package, please let me know!

@GrahamDumpleton
Copy link
Owner

Can you try wrapt==1.17.0dev3 from PyPi.

@contrast-jproberts
Copy link
Author

wrapt==1.17.0dev3 passes all my test cases 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants