Skip to content

TYP: resolve mypy ignores in core/apply.py #47066

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

Merged
merged 5 commits into from
May 30, 2022

Conversation

iasoon
Copy link
Contributor

@iasoon iasoon commented May 19, 2022

xref #37715

def normalize_keyword_aggregation(kwargs: dict) -> tuple[dict, list[str], list[int]]:
def normalize_keyword_aggregation(
kwargs: dict,
) -> tuple[dict, list[str], npt.NDArray[np.intp]]:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

npt.NDArray[intp] is the actual retrun type of Index.get_indexer

@@ -1116,7 +1117,8 @@ def apply_empty_result(self) -> Series:
)

def apply_standard(self) -> DataFrame | Series:
f = self.f
# caller is responsible for ensuring that f is Callable
f = cast(Callable, self.f)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the same approach as taken for the other cases (for example, apply_str).

I think we might be able avoid the casts altogether by passing self.f as an argument to the apply_X functions, if that would be a desirable change.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume self.f : Callable | None? I think it would be nicer to assert f is not None

Copy link
Contributor Author

@iasoon iasoon May 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self.f is typed as AggFuncType (defined here), which does not include None. Do we still have to check in that case?

Copy link
Contributor Author

@iasoon iasoon May 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For context, type checking is done in this method.
Re-reading the code, though, it seems that this method actually does not handle the AggFuncTypeDict case. I'll change the input signature.
IMO this kind of error highlights the reasons for avoiding casts altogether - would it be acceptable to pass self.f as an argument to the specific apply_ functions, so that we can propagate the inferred types?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds reasonable to me, might be good to check git blame and then cc the person who last touched this method.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that would be @rhshadrach 🙂

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Within the init of the Apply class, self.f is packed with args/kwargs when appropriate. This keeps that logic DRY; would passing f instead mean that logic needs to be repeated multiple places? If so, I'd be opposed to the change.

Another option would be to not pack self.f with args/kwargs at all, and only do so in the appropriate circumstances later in the code. That may be a better option altogether, but I'm not sure if there are other issues that might arise if one attempts this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think delaying the arg packing of self.f might be an interesting option, since it looks like this is only used when f is Callable (so the apply_default case). But it seems like that might be a bigger change that affects more code, so I think it's better to explore that in a separate PR.

@jreback jreback added the Typing type annotations, mypy/pyright type checking label May 21, 2022
@@ -1049,7 +1050,7 @@ class SeriesApply(NDFrameApply):
def __init__(
self,
obj: Series,
func: AggFuncType,
func: SeriesAggFuncType,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

func can be a dict here, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apologies, you are right - I did not realize dict was considered to be list-like. I reverted that part.

@jreback jreback added this to the 1.5 milestone May 29, 2022
Copy link
Contributor

@jreback jreback left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm. @rhshadrach over to you

Copy link
Member

@rhshadrach rhshadrach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@rhshadrach rhshadrach added the Apply Apply, Aggregate, Transform, Map label May 30, 2022
@rhshadrach rhshadrach merged commit bc5f206 into pandas-dev:main May 30, 2022
yehoshuadimarsky pushed a commit to yehoshuadimarsky/pandas that referenced this pull request Jul 13, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Apply Apply, Aggregate, Transform, Map Typing type annotations, mypy/pyright type checking
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants