-
Notifications
You must be signed in to change notification settings - Fork 25
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
How to use @dispatch with @staticmethod inside a class? #35
Comments
Can you provide a short script that reproduces the error? |
|
It looks like that
does not work because import plum
from inspect import signature
from typing import Callable
class Test:
@staticmethod
def test(arg):
return arg
print(signature(Test.test)) #(arg)
def decorator(fun):
print(signature(fun))
return fun
class Test2:
@decorator
@staticmethod
def test(arg):
return arg the first printing works, but when defining Test2 using the decorator we get the error Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in Test
File "<stdin>", line 2, in decorator
File "/Users/filippovicentini/.pyenv/versions/3.9.7/lib/python3.9/inspect.py", line 3111, in signature
return Signature.from_callable(obj, follow_wrapped=follow_wrapped)
File "/Users/filippovicentini/.pyenv/versions/3.9.7/lib/python3.9/inspect.py", line 2860, in from_callable
return _signature_from_callable(obj, sigcls=cls,
File "/Users/filippovicentini/.pyenv/versions/3.9.7/lib/python3.9/inspect.py", line 2259, in _signature_from_callable
raise TypeError('{!r} is not a callable object'.format(obj))
TypeError: <staticmethod object at 0x108865250> is not a callable object I suspect this is a python bug that should be reported upstream... Inverting the order, ( cc @wesselb |
Thanks for the explanation; it's definitely interesting that a staticmethod In my case, I think we will completely remove the classes (since they really do not have a deeper purpose than being a "container"). Anyways, would be interesting, whether it "could be supported" or not. |
If we could access the wrapped method we could special case it, but it seems that if you do def test(arg):
return arg
tm = staticmethod(test) you can't get out whatever is wrapped inside of the static method. If you manage to find how to get it out (I suspect it might be possible with the C api) then it would be easy to support it. |
Hey both, I’m currently away on holidays, but I’ll get back to this as soon as I’m back. On a first thought, perhaps this SO answer is useful: could we extract the function by using the descriptor protocol? |
It seems that you can extract the method as follows: In [1]: def f(x):
...: return x
...:
In [2]: f_static = staticmethod(f)
In [3]: f_static.__get__(object())
Out[3]: <function __main__.f(x)>
In [4]: f
Out[4]: <function __main__.f(x)>
In [6]: f_static.__get__(object()) is f
Out[6]: True This means that we could potentially treat it specially, as @PhilipVinc suggests. However, it appears that from plum import dispatch
class A:
@staticmethod
@dispatch
def f(x: int):
return 1
@staticmethod
@dispatch
def f(x: str):
return "1"
@classmethod
@dispatch
def g(cls, x: int):
return cls, 1
@classmethod
@dispatch
def g(cls, x: str):
return cls, "1"
@dispatch
def _(self):
pass
The reason why it didn't work for @Imipenem is that there is some complicated logic going on to enable the functions to hold a reference to the class, which requires the class to have at least one function which has
would work. Perhaps there is a better way? |
I've added a section to the README. A better solution would be preferable, of course. |
I see, many thanks for the detailed explanation. Thanks also for the README section about this. |
Hey,
consider the following code snippet:
and
So I have two staticmethods inside a class and I want to use dispatch on them.
When I try to run the code above it always fails with:
I read in your docs, that the dispatch decorator should be the outermost decorator. But doing so with staticmethod, will also result in an error indicating that the dispatch operator does not get a callable object (but a staticmethod object) passed.
Any ideas whats going on here and how to resolve this?
Many thanks ;)
The text was updated successfully, but these errors were encountered: