-
Notifications
You must be signed in to change notification settings - Fork 170
fix(typing): Narrow TypeVar(s) used in (Data|Lazy)Frame
#2356
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
Revealed quite a few other issues
+ fix related quirks
- I think this whole test needs rewriting - We shouldn't be depending on the internals like this
Spent waaaaaay too long trying to get this working
tests/translate/from_native_test.py
Outdated
| def test_dataframe_recursive_v1() -> None: | ||
| pytest.importorskip("polars") | ||
| import polars as pl | ||
|
|
||
| pl_frame = pl.DataFrame({"a": [1, 2, 3]}) | ||
| nw_frame = nw.from_native(pl_frame) | ||
| with pytest.raises(AssertionError): | ||
| nw.DataFrame(nw_frame, level="full") | ||
|
|
||
| nw_frame_early_return = nw.from_native(nw_frame) | ||
|
|
||
| if TYPE_CHECKING: | ||
| assert_type(pl_frame, pl.DataFrame) | ||
| # TODO @dangotbanned: Fix without breaking something else (1) | ||
| assert_type(nw_frame, nw.DataFrame[pl.DataFrame]) | ||
|
|
||
| nw_frame_depth_2 = nw.DataFrame(nw_frame, level="full") | ||
| # NOTE: Checking that the type is `DataFrame[Unknown]` | ||
| assert_type(nw_frame_depth_2, nw.DataFrame) | ||
| # TODO @dangotbanned: Fix without breaking something else (2) | ||
| assert_type(nw_frame_early_return, nw.DataFrame[pl.DataFrame]) |
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.
- Spent a few hours trying to get this working
- Nothing I've tried worked for both
mypy,pyrightand didn't break something elsewhere
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.
AFAICT, v1s overloads were always returning a Union for the case I was trying to force into DataFrame.
Gave up on trying to resolve in (c4bed59)
| @@ -1,5 +1,6 @@ | |||
| from __future__ import annotations | |||
|
|
|||
| # mypy: disallow-any-generics=false, disable-error-code="var-annotated" | |||
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.
Needed to add this to avoid mypy requiring # type: ignores.
If a line has one (regardless of it is has an error code) pyright won't ever emit a diagnostic
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.
Moved into a docstring for a better explainer (6a66779)
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.
@FBruzzesi in relation to (#2304 (comment))
I think there's quite a lot of things to be learned - by following this PR all the way back to the original issue (#2239) π
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.
Thanks for the ping! I just went through the entire PR, my skill issue is that everything makes sense, but most likely I would not be able to (re)produce it π₯²
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.
@FBruzzesi so if you go through the PR (or (https://github.com/narwhals-dev/narwhals/pull/2347/commits)) in order of commits - there's a pattern in all of this.
Is this a workflow?
- Identify some typing that doesn't meet your expectation ([Bug]:
TypeVar(s) used innw.(BaseFrame|Series)are recursiveΒ #2239) - Make the smallest change you think could fix it (74a03a8)
- Write a test that would demonstrate the bug was fixed (ff841d1)
- I probably should've started with that, but I was eager I guess π
- Add some notes when that didn't work (ff841d1#r2029276670)
- Add even more notes when all seems lost (37549cc)
- Try absolutely anything to fix it (6bd47b4)
- I wasn't happy with this initially, but became more convinced when it didn't break anything else
- Without the tests in place - I might have not even tried this
- Write an essay on why you think that worked (6bd47b4#r2029455047)
- Clean things up (50e4d13)
Back to this PR
You can follow through (aa6578e) and Next > to see a similar thing π
Different issues came up, but I'm mostly trying to isolate small things and see what mypy & pyright spits back out when I attempt a fix
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 also usually try to get the typing right first before I start making "real" code changes.
It is much harder to spot the source of an issue if you only check the types after making lots of changes
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.
thanks @dangotbanned ! just got a question
narwhals/_polars/dataframe.py
Outdated
| index: list[str] | None, | ||
| values: list[str] | None, | ||
| index: str | Sequence[str] | None, | ||
| values: str | Sequence[str] | 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.
why do these change? is Sequence[str] | None not fine?
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.
thanks @dangotbanned ! just got a question
Thanks @MarcoGorelli, happy to answer π
why do these change? is
Sequence[str] | Nonenot fine?
the original annotation was overly narrow, since polars accepts much more than a list
- https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.pivot.html
- https://github.com/pola-rs/polars/blob/py-1.26.0/py-polars/polars/dataframe/frame.py#L8732-L8963
I followed through to pandas to see if that was the source of using list[str], but IIRC it used an alias like IndexLabel.
Sequence[str] | None is equivalent to str | Sequence[str] | None sadly (python/typing#256).
But I prefer being more explicit that it can accept "one or more columns"
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.
if it's str we already make it a list at the narwhals level, can this just be Sequence[str] | 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.
@MarcoGorelli sure thing!
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.
Resolved in (d6cb16b)
|
@MarcoGorelli I've resolved the conflicts from #2380 Are we good to go on this one? |
| class DataFrameGroupBy( | ||
| CompliantGroupBy[CompliantDataFrameT_co, CompliantExprT_contra], | ||
| Protocol38[CompliantDataFrameT_co, CompliantExprT_contra], | ||
| ): | ||
| def __iter__(self) -> Iterator[tuple[Any, CompliantDataFrameT_co]]: ... |
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.
@FBruzzesi I forgot to mention this will probably be helpful in getting the typing working for (#2325).
It means you can use CompliantGroupBy for Polars* and put the unrelated parts here.
I needed to add it to resolve an unrelated issue (1815752)
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.
No worries @MarcoGorelli! I'm just happy we're now in a good place to work on π |


Will close #2344, #2345
What type of PR is this? (check all applicable)
Related issues
TypeVarused inDataFrameΒ #2344TypeVarused inLazyFrameΒ #2345pivotto ArrowΒ #2179Checklist
If you have comments or can explain your changes, please do so below
mainTypeAliass and@overloadsDataFrame._compliant_frameLazyFrame._compliant_framev1LazyFrameoverloadDataFrameoverload