Description
The patching code added in #434 breaks if the run
attribute on a thread is not a method.
I’m using sentry-sdk==0.11.1
with Python 3.7.4.
Put the following code in demo.py
:
import sentry_sdk
from sentry_sdk.integrations.threading import ThreadingIntegration
sentry_sdk.init(default_integrations=False, integrations=[ThreadingIntegration()])
from threading import Thread
class MyThread(Thread):
def __init__(self):
super().__init__()
self.run = lambda: print("hello")
t = MyThread()
t.start()
t.join()
Run python3 demo.py
:
Traceback (most recent call last):
File "demo.py", line 18, in <module>
t.start()
File "/myapp/venv/lib/python3.7/site-packages/sentry_sdk/integrations/threading.py", line 41, in sentry_start
self.run = _wrap_run(hub_, self.run.__func__)
AttributeError: 'function' object has no attribute '__func__'
Remove Sentry:
from threading import Thread
class MyThread(Thread):
def __init__(self):
super().__init__()
self.run = lambda: print("hello")
t = MyThread()
t.start()
t.join()
Run it again: python3 demo.py
hello
It runs fine.
The issue is that the patching code relies on self.run.__func__
but that attribute is only defined on methods, not on functions.
You can see that with this code:
>>> class A():
... def f(self):
... pass
... def set_f(self):
... self.f = lambda _: 42
...
>>> a = A()
>>> a.f.__func__
<function A.f at 0x106dfaef0>
>>> a.set_f()
>>> a.f.__func__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute '__func__'
According to the Python docs, one can call inspect.ismethod
on an object to check if it’s a method and so if it has a ___func__
attribute (you could even use hasattr
).
I haven’t tested it, but I believe something like this would do the job:
run_function = self.run.__func__ if inspect.ismethod(self.run) else self.run
self.run = _wrap_run(hub_, run_function)
Note that this self.run
assigment code (already in the patch) transforms self.run
in a function rather than a method if it were one before, meaning that in my example code MyThread().run.__func__
is defined only if I don’t use Sentry (or at least its Thread
integration).
What do you think? I can move forward and make a pull-request with a test and a fix if the solution above suits you.