-
Notifications
You must be signed in to change notification settings - Fork 1
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Q about the type hints.
Co-authored-by: Nathaniel Starkman <nstarman@users.noreply.github.com>
def __abs__(self) -> Self[op.CanAbs[V], U]: ... | ||
|
||
def __add__[B](self, other: Self[op.CanAdd[V, B], U], /) -> Self[op.CanAdd[V, B], U]: ... | ||
def __radd__[B](self, other: Self[op.CanAdd[V, B], U], /) -> Self[op.CanAdd[V, B], U]: ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jorenham is this the right way to think about the reflected operators? Just want a second for this motion 😆
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only situation where __radd__
would be called at runtime (apart from calling it directly), is if the right-hand-side is a strict subclass of Quantity
(it's a weird exception). So that way, we can "reflect it back" to the __add__
of the left-hand-side, which tells us that the other
in __add__
should match on op.CanRAdd
instead of op.CanAdd
. It'll be more symmetrical that way, so it's also prettier that way :P
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And the casual higher-kinded typing notation using Self
deserves full marks for creativity 💯
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm now that I think about this a bit more, I can imagine that type-checkers could end up in an infinite loop when analyzing this, just like my brain currently is, judging by the temperature of my office.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh I only just now noticed: op.CanAdd[V, B]
describes a type with a __add__: (self, other: V, /) -> B
. So the return type should instead be Self[B, U]
As much as I'd like it to be, Maybe it's a good idea to add a type-checker to the CI? edit: |
Indeed, I just hit this locally! Yeah, we should set up CI at some point. |
Do you already have some verification code or something in place, that checks if assigning some real-world quantity object to the |
It seemed like I needed to add quotation marks to appease Pylance locally doing this due to errors about |
Strinfying it is indeed a solution. Another option would be to
So no, not yet; that'll have to wait until 3.14: https://docs.python.org/3.14/whatsnew/3.14.html#whatsnew314-pep649 |
Not yet AFAIK, but certainly on the TO-DO list. |
My advice would then be to postpone this PR until you have it. Protocols are very tricky, and might not always work in the way you expect (especially when there are overloads involved). Either way, don't repeat the same mistakes as I did. And even if you might learn some wise lessons by doing so, there are probably more efficient ways to achieve the goal 🤷🏻 |
@andrewgsavage would you mind transferring this PR's changes over to https://github.com/quantity-dev/metrology-apis ? (no rush :) ) |
Do we want to add
__divmod__
,__round__
,__floor__
, and__trunc__
?