-
-
Notifications
You must be signed in to change notification settings - Fork 18.4k
Add typing annotation to assert_index_equal #26535
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
Changes from 4 commits
453875e
8c70a15
f176ef5
411dd51
fe9f8e8
571e64f
904a7f2
7de3444
cf96e22
8418a07
de3fbf2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ | |
import string | ||
import tempfile | ||
import traceback | ||
from typing import Union | ||
import warnings | ||
import zipfile | ||
|
||
|
@@ -515,9 +516,14 @@ def equalContents(arr1, arr2): | |
return frozenset(arr1) == frozenset(arr2) | ||
|
||
|
||
def assert_index_equal(left, right, exact='equiv', check_names=True, | ||
check_less_precise=False, check_exact=True, | ||
check_categorical=True, obj='Index'): | ||
def assert_index_equal(left: Index, | ||
right: Index, | ||
exact: Union[bool, str] = 'equiv', | ||
check_names: bool = True, | ||
check_less_precise: Union[bool, int] = False, | ||
check_exact: bool = True, | ||
check_categorical: bool = True, | ||
obj: str = 'Index') -> None: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just a general comment but NoReturn may be applicable here at some point when we drop 3.5, though not sure if Optional[NoReturn] makes sense |
||
"""Check that left and right Index are equal. | ||
|
||
Parameters | ||
|
@@ -587,19 +593,20 @@ def _get_ilevel_values(index, level): | |
raise_assert_detail(obj, msg1, msg2, msg3) | ||
|
||
# MultiIndex special comparison for little-friendly error messages | ||
if left.nlevels > 1: | ||
for level in range(left.nlevels): | ||
# cannot use get_level_values here because it can change dtype | ||
llevel = _get_ilevel_values(left, level) | ||
rlevel = _get_ilevel_values(right, level) | ||
|
||
lobj = 'MultiIndex level [{level}]'.format(level=level) | ||
assert_index_equal(llevel, rlevel, | ||
exact=exact, check_names=check_names, | ||
check_less_precise=check_less_precise, | ||
check_exact=check_exact, obj=lobj) | ||
# get_level_values may change dtype | ||
_check_types(left.levels[level], right.levels[level], obj=obj) | ||
if isinstance(left, MultiIndex) and isinstance(right, MultiIndex): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is needed to avoid type issues? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. Otherwise, mypy showed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't this just replace the existing condition then? Seems duplicative to have both checks There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My point is that Also does this have any impact on assertions given the check previously only looked at the left index and not both? |
||
if left.nlevels > 1: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I still think this line should be removed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or alternately we could keep original code in tact and simply cast inside of this condition; that would prevent any actual code changes but give mypy the inference it needs that we are only working with MI in this branch. I'd actually prefer that but @jreback may have differing thoughts There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah maybe the cast inside the condition is better? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pardon me. I am not familiar with casting in Python. By casting, do you mean Or one more type annotation?
mypy still regards There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
for level in range(left.nlevels): | ||
# cannot use get_level_values here because it can change dtype | ||
llevel = _get_ilevel_values(left, level) | ||
rlevel = _get_ilevel_values(right, level) | ||
|
||
lobj = 'MultiIndex level [{level}]'.format(level=level) | ||
assert_index_equal(llevel, rlevel, | ||
exact=exact, check_names=check_names, | ||
check_less_precise=check_less_precise, | ||
check_exact=check_exact, obj=lobj) | ||
# get_level_values may change dtype | ||
_check_types(left.levels[level], right.levels[level], obj=obj) | ||
|
||
# skip exact index checking when `check_categorical` is False | ||
if check_exact and check_categorical: | ||
|
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.
Instead of a raw Index, is it possible to add a typing.TypeVar to _typing.py:
and then use that here (I'm not super aqianted with typing, so could be wrong)?
That would avoid the need to adapt the code below.
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 ok as all of these are Index subclasses
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 point was that AnyIndex would capture .levels and other attributes that are not set on the base Index.
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 think this is OK too. MyPy would still complain about those attributes not existing on Index