I was integrating slipcover with a project and found that it caused several tests in our test suite to fail. After some debugging, it turns out that it was caused by slipcover making Celery Tasks to be eagerly bound to their Celery app. Specifically:
Inside of is_patchable_function y'all use inspect.isfunction.
Example stack trace
```
File "/usr/local/lib/python3.10/site-packages/slipcover/slipcover.py", line 519, in is_patchable_function
return inspect.isfunction(func) and type(func.__code__) is types.CodeType
File "/usr/local/lib/python3.10/inspect.py", line 288, in isfunction
return isinstance(object, types.FunctionType)
File "/usr/local/lib/python3.10/site-packages/celery/local.py", line 94, in __class__
return self._get_class()
File "/usr/local/lib/python3.10/site-packages/celery/local.py", line 90, in _get_class
return self._get_current_object().__class__
File "/usr/local/lib/python3.10/site-packages/celery/local.py", line 294, in _get_current_object
return self.__evaluate__()
File "/usr/local/lib/python3.10/site-packages/celery/local.py", line 324, in __evaluate__
thing = Proxy._get_current_object(self)
File "/usr/local/lib/python3.10/site-packages/celery/local.py", line 105, in _get_current_object
return loc(*self.__args, **self.__kwargs)
File "/usr/local/lib/python3.10/site-packages/celery/app/base.py", line 489, in _task_from_fun
task.bind(self) # connects task to this app
```
This can cause unexpected changes in a celery Task's behavior because the Task inherits certain configurations from the Celery app at bind-time. Typically it's bound the first time it's executed, but this causes it to be bound at import-time instead.
I think this may be more Celery's fault than slipcover, but I thought you all may want to know about a potential behavior change when using slipcover.
(And: hello from a UMass CS alum. Super cool to see PLASMA continuing to make awesome stuff.)
I was integrating slipcover with a project and found that it caused several tests in our test suite to fail. After some debugging, it turns out that it was caused by
slipcover
making CeleryTask
s to be eagerly bound to theirCelery
app. Specifically:is_patchable_function
y'all useinspect.isfunction
.inspect.isfunction
usesisinstance(<thing>, FunctionType)
.isinstance
causes aTask
to bind to its app.Example stack trace
``` File "/usr/local/lib/python3.10/site-packages/slipcover/slipcover.py", line 519, in is_patchable_function return inspect.isfunction(func) and type(func.__code__) is types.CodeType File "/usr/local/lib/python3.10/inspect.py", line 288, in isfunction return isinstance(object, types.FunctionType) File "/usr/local/lib/python3.10/site-packages/celery/local.py", line 94, in __class__ return self._get_class() File "/usr/local/lib/python3.10/site-packages/celery/local.py", line 90, in _get_class return self._get_current_object().__class__ File "/usr/local/lib/python3.10/site-packages/celery/local.py", line 294, in _get_current_object return self.__evaluate__() File "/usr/local/lib/python3.10/site-packages/celery/local.py", line 324, in __evaluate__ thing = Proxy._get_current_object(self) File "/usr/local/lib/python3.10/site-packages/celery/local.py", line 105, in _get_current_object return loc(*self.__args, **self.__kwargs) File "/usr/local/lib/python3.10/site-packages/celery/app/base.py", line 489, in _task_from_fun task.bind(self) # connects task to this app ```This can cause unexpected changes in a celery
Task
's behavior because theTask
inherits certain configurations from theCelery
app atbind
-time. Typically it's bound the first time it's executed, but this causes it to be bound at import-time instead.I think this may be more Celery's fault than slipcover, but I thought you all may want to know about a potential behavior change when using slipcover.
(And: hello from a UMass CS alum. Super cool to see PLASMA continuing to make awesome stuff.)