Skip to content

Conversation

realzachbrownjohn
Copy link

This is my first contribution so I would appreciate your guidance. I think I have fixed the issue, but I'm confused on where to add test(s), or if I need to at all. Would it be acceptable to use Dr-Irv's reproduction script, or perhaps a modified copy?

Copy link
Contributor

@cmp0xff cmp0xff left a comment

Choose a reason for hiding this comment

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

Please look for test_multiindex to place the tests. I think you need to add one or more new test functions in tests/indexes/test_indexes.py.

@realzachbrownjohn
Copy link
Author

Thank you for the feedback! I will work on that shortly.

@realzachbrownjohn
Copy link
Author

realzachbrownjohn commented Oct 22, 2025

I've tried my best to spend a bit of time unpacking this. Ultimately, I didn't think it was best to include all types of Index in the overload because not all types of Index are valid to union with MultiIndex (only those with tuples). Referring to tuples within Indexes wasn't supported so I had to add that support in _typing.pyi.

Happy to adjust recognising that Dr-Irv never mentioned any issue with using the complete Index type.

Additionally, I've attempted to add a test in tests/indexes/test_indexes.py covering the different cases I could think of.

@realzachbrownjohn
Copy link
Author

I can see now that all checks have failed, looks related to my extension of S1 (in adding support for tuple[Hashable, ...] I seem to have violated some sort of constraint). Any guidance would be greatly appreciated.

Copy link
Contributor

@cmp0xff cmp0xff left a comment

Choose a reason for hiding this comment

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

  • You can mark the PR as a draft if you plan to work on it for a while.
    • Just click Re-request review on the top-right corner of the PR when you are done.
  • Please run pre-commit locally to avoid simple mistakes
  • Please use poe to do further tests locally, e.g. poe test_all

@realzachbrownjohn realzachbrownjohn marked this pull request as draft October 22, 2025 13:50
@realzachbrownjohn realzachbrownjohn marked this pull request as ready for review October 22, 2025 14:08
@realzachbrownjohn
Copy link
Author

Ended up removing MultiIndex-Index unions from assumption for returning a MultiIndex - was causing too many problems and Dr-Irv said it was okay to ignore. It was either violating the overload standard or confusing mypy in testing.

swaplevel tests added, MultiIndex tests removed some cases relating to different types of Indexes (since we no longer try checking for those), and S1 changes reverted.

@realzachbrownjohn
Copy link
Author

realzachbrownjohn commented Oct 22, 2025

I'm not sure why it failed. I ran poe test_all locally several times; all successful.

Running the test case locally individually it failed, seems to be a runtime error because Pandas won't accept an Index unionising a MultiIndex (as it should). Removing that test case.

Copy link
Contributor

@cmp0xff cmp0xff left a comment

Choose a reason for hiding this comment

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

Please also run pre-commit locally.

Comment on lines 168 to 169
@overload
def union(self, other: Index | list[HashableT], sort: bool | None = ...,) -> Index: ...
Copy link
Contributor

Choose a reason for hiding this comment

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

If MultiIndex.union does not produce an Index, please remove this overload

| datetime.datetime # includes pd.Timestamp
| datetime.timedelta # includes pd.Timedelta
)

Copy link
Contributor

Choose a reason for hiding this comment

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

This extra empty line can also be removed

Copy link
Contributor

Choose a reason for hiding this comment

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

Would you?

@realzachbrownjohn realzachbrownjohn marked this pull request as draft October 22, 2025 22:15
@realzachbrownjohn
Copy link
Author

Please also run pre-commit locally.

My mistake. I had ran a pre-commit after committing, and didn't commit the refactoring it made.

@realzachbrownjohn realzachbrownjohn marked this pull request as ready for review October 22, 2025 22:34
Copy link
Contributor

@cmp0xff cmp0xff left a comment

Choose a reason for hiding this comment

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

Great, now all checks pass. We are almost there.

Comment on lines +167 to +169
self,
other: Self | Index | list[HashableT],
sort: bool | None = ...,
Copy link
Contributor

Choose a reason for hiding this comment

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

I suppose Index should be removed. It is not tested, either.

Suggested change
self,
other: Self | Index | list[HashableT],
sort: bool | None = ...,
self, other: list[HashableT] | Self, sort: bool | None = ...

| datetime.datetime # includes pd.Timestamp
| datetime.timedelta # includes pd.Timedelta
)

Copy link
Contributor

Choose a reason for hiding this comment

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

Would you?

Comment on lines +1606 to +1622
def test_multiindex_swaplevel_rettype() -> None:
"""Test that union returns MultiIndex on MultiIndex input and swaplevel returns Self"""
mi = pd.MultiIndex.from_product([["a", "b"], [1, 2]], names=["let", "num"])
mi2 = pd.MultiIndex.from_product([["a", "b"], [3, 4]], names=["let", "num"])

check(
assert_type(mi.swaplevel(0, 1), "pd.MultiIndex"),
pd.MultiIndex,
)
check(
assert_type(mi.union(mi2), "pd.MultiIndex"),
pd.MultiIndex,
)
check(
assert_type(mi.union([("c", 3), ("d", 4)]), "pd.MultiIndex"),
pd.MultiIndex,
)
Copy link
Contributor

Choose a reason for hiding this comment

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

Please make two tests, since swaplevel and union are two independent functionalities:

Suggested change
def test_multiindex_swaplevel_rettype() -> None:
"""Test that union returns MultiIndex on MultiIndex input and swaplevel returns Self"""
mi = pd.MultiIndex.from_product([["a", "b"], [1, 2]], names=["let", "num"])
mi2 = pd.MultiIndex.from_product([["a", "b"], [3, 4]], names=["let", "num"])
check(
assert_type(mi.swaplevel(0, 1), "pd.MultiIndex"),
pd.MultiIndex,
)
check(
assert_type(mi.union(mi2), "pd.MultiIndex"),
pd.MultiIndex,
)
check(
assert_type(mi.union([("c", 3), ("d", 4)]), "pd.MultiIndex"),
pd.MultiIndex,
)
def test_multiindex_union() -> None:
"""Test that MultiIndex.union returns MultiIndex"""
mi = pd.MultiIndex.from_product([["a", "b"], [1, 2]], names=["let", "num"])
mi2 = pd.MultiIndex.from_product([["a", "b"], [3, 4]], names=["let", "num"])
check(
assert_type(mi.union(mi2), "pd.MultiIndex"), pd.MultiIndex
)
check(
assert_type(mi.union([("c", 3), ("d", 4)]), "pd.MultiIndex"), pd.MultiIndex
)
def test_multiindex_swaplevel() -> None:
"""Test that MultiIndex.swaplevel returns MultiIndex"""
mi = pd.MultiIndex.from_product([["a", "b"], [1, 2]], names=["let", "num"])
check(
assert_type(mi.swaplevel(0, 1), "pd.MultiIndex"), pd.MultiIndex
)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MultiIndex method corrections

3 participants