-
-
Notifications
You must be signed in to change notification settings - Fork 19.4k
TYP: Improve clip() return and argument typing. #40860
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
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.
This is off to a good start!
You have overloads for:
- ✅
inplace: Literal[False] = ... - ✅
inplace: bool = ... - ✅
inplace: Literal[True]:- when
lower,upper, andaxisare passed - when
lowerandupper, but notaxis, are passed
- when
You're missing:
inplace: Literal[True]:- when
lowerandaxis, but notupper, are passed - when
upperandaxis, but notlower, are passed - when
lower, but notaxisorupper, is passed - when
upper, but notaxisorlower, is passed - when
axis, but notlowerorupper, is passed - when none of
axis,lower, orupperare passed
- when
Thank you for this nice overview! I will try to add these cases. I am a bit confused on how to handle the syntax for: "when
|
|
can you try @overload
def clip(
self: FrameOrSeries,
*
upper,
inplace: Literal[True],
*args,
**kwargs,
) -> None:
...? |
Thanks! I think I got them all now. Could you check if I did everything right? I am quite new to type overloading. |
Congrats for having braved this not-so-simple issue then! To check if you've done it correctly, could you make a new file If you could do that, and paste here the content of |
|
I think the last one are correct - if If you repeat the first block but put |
|
Yes, just as I left my last comment (which I then deleted), I realized my mistake. Here is the file and the output! |
|
@MarcoGorelli thank you for the guidance and the explanations! |
MarcoGorelli
left a comment
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.
Nice one, thanks @DriesSchaumont ! Just left a small comment about how you've typed axis in some overloads but not in others, other than that this looks good to me (cc @simonjayhawkins in case you have further comments)
simonjayhawkins
left a comment
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.
lgtm
| self: FrameOrSeries, | ||
| lower=..., | ||
| upper=..., | ||
| axis: Axis | None = ..., |
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.
users of the pandas api should not pass None.
axis: int or str axis name, optional
for the default (should be listed in the docstring instead of optional - not for this PR though), the argument should not be passed.
@MarcoGorelli what are you thoughts about not including None in the overloads and also now that we are using PEP 604, removing no_implicit_optional = True from setup.cfg and excluding None actual function signatures too?
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.
Hey @simonjayhawkins
+1 on removing no_implicit_optional
Not sure what you mean about not including None in overloads - if axis=None is passed internally, then won't it need to be in one of the overloads for type checking to work?
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.
I guess the question is (in general) should None ever be passed internally or should kwargs always be (in general) validated at the top level.
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.
IIRC we have had issues reported where None is passed by users and when we change defaults (I think bool True/False in a specific case I remember recently) this is results in a perceived regression. We also sometime use lib.nodefault to detect if a kwarg has been specified. So I was thinking to that discouraging users passing None could be worthwhile.
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.
@simonjayhawkins I looked into the no_implicit_optional = True, but it seems it's only possible to omit if you only have two possible types.
e.g. the following works:
from __future__ import annotations
from typing import Tuple
def foo(
a: str | int | None = None,
b: str = None,
): ...but the following doesn't:
from __future__ import annotations
from typing import Tuple
def foo(
a: str | int = None,
b: str = None,
): ..., we get
t.py:5: error: Incompatible default for argument "a" (default has type "None", argument has type "Union[str, int]") [assignment]
Found 1 error in 1 file (checked 1 source file)
So I think it's cleaerer to keep no_implicit_optional
* Improve clip() typing. * Update typing. * More clip overloads. * Add missing axis types
Uh oh!
There was an error while loading. Please reload this page.