Beartype and TypeVar for type consistency accross arguments #284
-
Hello, First of all thanks for beartype ! It helps me a lot for detecting bugs and increasing the confidence in the consistency of my code. My question is about the interaction between TypeVar and beartype. The following code defines an from typing import TypeVar, Union
from beartype import beartype
number = Union[int, float]
T = TypeVar('T', number, str)
@beartype
def add(a: T, b: T) -> T:
return a + b According to my understanding of PEP484, I read this as : If I try to call I expected a beartype error when calling Thanks in advance for your help |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments
-
tl;dr: Plum. Plum is what you need in your life. A longer and tedious explanation now follows that will exhaust you and make you punch the air in frustration. Also, I provide working code that solves your problem below! "Please keep reading" is what I'm saying.
Aww. 🤗 Thanks so much for the kind words, @Louis-Pujol. Python really is the Wild West of code, isn't it? Everything's anarchic, ill-defined, duck-typed, and constantly on fire. This is why we @beartype. Sadly, even @beartype sometimes falls down on the job. Case in point: this discussion.
...heh. Yeah. Currently, @beartype reduces all constrained type variables (i.e., from typing import TypeVar, Union
from beartype import beartype
T = Union[int, float, str]
@beartype
def add(a: T, b: T) -> T:
return a + b And... now we understand why the following erroneous call raises the following unexpected non-human-readable >>> add(3, 'cat')
Traceback (most recent call last):
File "/home/leycec/tmp/mopy.py", line 13, in <module>
add(3, 'cat')
File "<@beartype(__main__.add) at 0x7ff9745fdf80>", line 55, in add
File "/home/leycec/tmp/mopy.py", line 11, in add
return a + b
~~^~~
TypeError: unsupported operand type(s) for +: 'int' and 'str' You are now thinking to yourself: "@beartype sucks. Mypy rocks. Everybody, throw rocks at @beartype until it bleeds!" You aren't necessarily wrong. @beartype should (and will eventually) do better here. In fact, our feature request #236 documents exactly the functionality you were expecting here: "Type-stable callable declarations (i.e., Oh My Gods. @beartype Sucks, Everybody!...heh. @beartype may suck for this use case – but Plum doesn't. Plum is built on the back of @beartype. Therefore, by extension, if we squint our eyes, @beartype doesn't suck either! everybody pats everybody on the back Okay. Look. What I'm trying (and failing) to say is that your use case can be refactored into multiple dispatch. Python's primary competitor, Julia, comes with multiple dispatch built-in. Although Python currently fails to ship with out-of-box support for multiple dispatch, fear not! Plum succeeds where Python itself fails. Let's refactor your @beartype-unfriendly example into a @beartype-friendly example driven by Plum's multiple dispatch mechanism, the from plum import dispatch
from typing import Union
number = Union[int, float]
@dispatch # <-- awesome magic
def add(a: number, b: number) -> number:
'''
Numerically add the passed two integers and/or floating-point numbers.
'''
return a + b
@dispatch # <-- more awesome magic
def add(a: str, b: str) -> str:
'''
Concatenate the passed two strings.
'''
return a + b That's actually considerably easier to both read and reason about than the original There's a Tradeoff and It Kinda Sucks (But It's Not Too Bad)There always is, right? This is Python. Gotta be fire-breathing tradeoffs lurking around every corner or it isn't Python. The tradeoff here is that mypy will probably now hate you. I consider this a worthwhile tradeoff. After all: what's better? Type hints that are enforced at runtime via @beartype + Plum or type hints that are ignored at runtime but complained about in a whining voice inside your IDE by mypy or Runtime >>>>>> IDE. At the end of the working day, IDEs are ignorable. Runtime is not. That said... This Is an Open Question in the Typing Community, ActuallyMypy integration is actually on open question over at the Plum issue tracker. I recall reading that @wesselb (i.e., the awesome Plum guy) and @gabrieldemarmiesse (i.e., the awesome Python-on-whales guy) are tag-teaming this on Python's official discussion forum to standardize a new Python Enhancement Proposal (PEP). Lastly, since:
@wesselb: Pinging you here because you are Plum incarnate and I probably got everything wrong. 😩 |
Beta Was this translation helpful? Give feedback.
-
Hi ! For the moment it's not a bottleneck in my work, I'm 100% happy with beartype only. I was just trying to decipher python's typing world reading PEPs/beartype/mypy/typing... docs and do some small tests to understand how things are working. I opened this discussion as I wasn't sure to understand the role of TypeVar. Your answer goes further from my expectations, thanks for the workaround and for pointing me out Plum, I didn't know about it. I'll have a closer look and follow the discussions about overloading ! Not easy for a newcomer to figure out the current state of typing in Python and the possibilities it offers ! The fact that the python documentation is 100% static typing oriented doesn't help... I only do runtime type checking for the moment, I consider it sufficient to be confident in my codebase in combination with tests, and my priority is to raise meaningful errors to the user. Thanks a lot for the detailed answer and the work you are doing on beartype, I'll continue to explore these topics ! |
Beta Was this translation helpful? Give feedback.
-
Just briefly dipping into the discussion here to say that, of course, @leycec is right on all fronts. :) Whereas Unfortunately, at the moment neither @Louis-Pujol should you have a question about any of this, about Beartype, or about Plum, please feel free to ask it here or elsewhere. :) |
Beta Was this translation helpful? Give feedback.
tl;dr: Plum. Plum is what you need in your life.
A longer and tedious explanation now follows that will exhaust you and make you punch the air in frustration. Also, I provide working code that solves your problem below! "Please keep reading" is what I'm saying.
Aww. 🤗
Thanks so much for the kind words, @Louis-Pujol. Python really is the Wild West of code, isn't it? Everything's anarchic, ill-defined, duck-typed, and constantly on fire. This is why we @beartype.
Sadly, even @beartype sometimes falls down on the job. Case in point: this discussion.