-
Notifications
You must be signed in to change notification settings - Fork 24
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
Is there a way to make pycharm understand what plum does? #89
Comments
Hey @gabrieldemarmiesse! Unfortunately I'm not aware of a way to make PyCharm play nice with Plum. :( Multiple dispatch is a programming pattern that's unfortunately poorly supported by existing Python tooling, not just PyCharm but also e.g. The next big step forward for the package would be to write plugins for e.g. I'm sorry to reply without a solution. I'd love to see support for Plum in PyCharm. |
No worries, I like plum a lot, but IDE integration prevents us from using it in our company, so yeah. But I can see the potential of this package. I think this was a missing feature of python |
It's a shame, albeit completely reasonable of course, to hear that the lack of IDE integration is what's preventing adoption. I've been meaning to look into how difficult some reasonable degree of integration would be. Once I find some time to look into this, I'll update you in this issue! |
I don't know how nuts this is in practice, but what about something like this? from typing import TYPE_CHECKING
from plum import dispatch
if TYPE_CHECKING:
from typing import overload
else:
def overload(f):
return dispatch(f)
@overload
def f(x: int) -> int:
return x
@overload
def f(x: str) -> str:
return x If plum defined overload like above (simply re-exporting from plum import overload
@overload
def f(x: int) -> int:
return x
@overload
def f(x: str) -> str:
return x And then use it not just as a type stub, but also to implement the dispatch. I tested a bit in VS Code and was surprised it showed the overloaded signatures. One downside is that the signature for overload is the one from |
@wch gave some really helpful feedback on this approach. In python 3.11, from typing import overload
from plum import dispatch
@overload
def f(x: int) -> int:
return x
@overload
def f(x: str) -> str:
return x
# here, dispatch could use typing.get_overloads to retrieve the functions above
@dispatch
def f(x):
raise NotImplementedError() edit: for context, it looks like registering function in overload was added to allow |
@machow and @wch, ahhhh that's a super interesting approach. How does the below snippet work for you in VS Code? from typing import Callable, TypeVar, get_overloads, overload
from plum import Function
T = TypeVar("T", bound=Callable)
def dispatch(f: T) -> T:
f_plum = Function(f)
for method in get_overloads(f):
f_plum.dispatch(method)
return f_plum
@overload
def f(x: int) -> int:
return x + 1
@overload
def f(x: str) -> str:
return x
@dispatch
def f(x):
raise NotImplementedError
print(f(1))
print(f("hey"))
# print(f(1.0)) # Wrong type! |
This is some galaxy-size brain stuff right here. I like that a lot. I'll experiment with that on some real-world project :) |
@gabrieldemarmiesse Let us know how that works for you!! |
I tried at and I am very impressed. Pycharm understands the inpout and output, it can't directly jump to the right overload but that's not much of an issue. The only small problem is that we need to use python 3.11 to use this. I wonder if there is a backport of get_overloads() somewhere in the typing_extensions. I don't even need to write the type hints for the function that raises NotImplementedError. So the UX is great! I wonder if this pattern can become part of plum? It's a game changer! |
@gabrieldemarmiesse It seems that In particular, I think I've managed to add from plum.overload import dispatch, overload
@overload
def f(x: int) -> int:
return x + 1
@overload
def f(x: str) -> str:
return x
@dispatch
def f(x):
raise NotImplementedError
print(f(1))
print(f("hey"))
I think so!! I've long been looking for a way to write multiple dispatch that plays nice with type checkings and Although this pattern goes a long way, I think it will be challenging to accommodate the more dynamic use cases of multiple dispatch. For example, a very common way is to import a |
I think we can go there progressively. Document and implement what works now, and we can always support more use cases later on |
I'm working on a couple tools using plum (e.g. https://github.com/machow/quartodoc, which implements a visitor using RE
AFAICT the only way guaranteed across static tools is to add the overload stubs for cases registered in other packages back into where you define the generic function. I think you should be able to do this without actually importing the other packages (using e.g. I think there's a relevant issue on improving the mypy extension for I'm a big fan of this pattern though, so would love to find a way to make it work across packages 😭 |
@gabrieldemarmiesse Alright, that sounds reasonable! Let's start out with a module @machow, Thanks for linking the |
I've taking a stab at adding limited type checking support in #93. |
Hi, I'm here because I noticed the new page in the documentation. It's more than a little mysterious on first and second read what the overload decorator is doing in the provided example, where specialized code should go, and what limitations there might be to the pattern. For example, does the overload pattern work for multi-argument functions? I feel like a fuller code example or fuller explanation of how plum.overload works would help a lot with accessibility. |
Hey @githubpsyche! Thanks for the feedback. It would certainly be possible to elaborate on how the overload pattern works and to expand the code example to multiple arguments. I’ll soon put something together. :) |
Hi @wesselb, first thanks very much for plum! A few years ago I had the urge to write my own configuration library and as plum was on it's early stages, I ended up writing my own multiple-dispatch functionality heavily inspired by plum. Recently, I replaced my own baked solution with plum quite effortlessly. Now back to the topic, the use of multiple dispatch is so fundamental to how type checkers works don't you think it's worth it proposing a PEP? In Python 3.11, a number of changes to PEP-484 were made so as long it's quite self-contained (eg. not proposing full multiple-dispatch support, just adding more flexibility to As for rationale (besides plum): Major scientific libraries such as This would allow at least a cleaner and mypy compliant use of from functools import singledispatch
from typing import Union
@singledispatch
def fun(arg, verbose=False):
if verbose:
print("Let me just say,", end=" ")
print(arg)
@singledispatch
def fun(arg: int, verbose=False):
if verbose:
print("Strength in numbers, eh?", end=" ")
print(arg)
@singledispatch
def fun(arg: list, verbose=False):
if verbose:
print("Enumerate this:")
for i, elem in enumerate(arg):
print(i, elem)
@singledispatch
def fun(arg: int | float, verbose=False):
if verbose:
print("Strength in numbers, eh?", end=" ")
print(arg)
@singledispatch
def fun(arg: Union[list, set], verbose=False):
if verbose:
print("Enumerate this:")
for i, elem in enumerate(arg):
print(i, elem) As for implementation, similar to |
I made a draft for a PEP :) It's very early stages, I'm looking for feedback! |
@githubpsyche I've elaborated in the docs and added a more complete example. I hope things are more clear now! :) |
@cjalmeida It's super nice to hear that you managed to swap in Plum without too much trouble! :) Also very cool that you're working on I think a PEP would be incredibly cool. @gabrieldemarmiesse, your proposal is very interesting. Perhaps it is worthwhile to list the current problems, to find consensus on what a PEP could address. Off the top of my head, in no particular order, some problems with the current state of type checking and multiple dispatch are the following:
@overload
def f(x: int) -> int:
return x
def f(x):
... # The implementation
@overload
def f(x: float) -> float: # This is not allowed, but we would really like to do so...
return x
@overload
def add(x: int, y: Number) -> Number:
return x + y
@overload
def add(x: Number, y: int) -> Number:
return x + y
@overload
def add(x: int, y: int) -> int:
return x + y
add(1, 2)
Reflecting on all these points, I come to two conclusions:
I'd be curious to hear your thoughts on the above points, @cjalmeida and @gabrieldemarmiesse. |
@wesselb that is awesome feedback! I'll work on it and clarify the PEP. Could you post (copy) your message about the PEP here https://discuss.python.org/t/multiple-dispatch-based-on-typing-overload/26197 if you don't mind? When making a PEP, the normal process is to discuss it in discuss.python.org. I don't want to spread the discussion across multiple forums :) |
@gabrieldemarmiesse definitely! I've posted my message on the thread. Thanks :) |
From the readme's example:
Pycharm doesn't understand the signature of the function f. It also can't jump to source according to the correct type. Is this possible to make pycharm work better with plum?
The text was updated successfully, but these errors were encountered: