Skip to content

Conversation

@deniskrds
Copy link
Contributor

@deniskrds deniskrds commented Nov 22, 2025

…n) (#63169)

Previously, Index.intersection and Index.union (including MultiIndex implementations) would return a direct reference to self (or other) if the result was identical to the input. This allowed side effects where mutating the metadata (e.g. .name) of the result would corrupt the original index.

This change forces a shallow copy (deep=False) in these cases. This preserves the performance benefit of sharing the underlying data array while ensuring the Index container itself is a distinct object with independent metadata.

@deniskrds deniskrds force-pushed the fix-index-setops-mutation branch from 88fecc0 to 3e9186d Compare November 23, 2025 10:05
@rhshadrach rhshadrach added Bug Index Related to the Index class or subclasses setops union, intersection, difference, symmetric_difference labels Dec 7, 2025
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.

Looking good, would like a 2nd eye on this. cc @jbrockmendel

tm.assert_index_equal(res, expected)


class TestSetOpsMutation:
Copy link
Member

Choose a reason for hiding this comment

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

We'd like to move away from having test classes in cases where the class itself isn't useful. Can you just make these functions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Got it. I'll convert them to functions shortly.

Copy link
Member

@jorisvandenbossche jorisvandenbossche left a comment

Choose a reason for hiding this comment

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

Looks good!
Could you add a note about this in the 3.0.0.rst whatsnew file? (eg in the indexing subsection in the bug fixes section)

if self.name is not name:
return self.rename(name)
return self
return self.copy()
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
return self.copy()
return self.copy(deep=False)

I know that is the default, but for code readability I might add it explicitly (given the default for Series/DataFrame is True, one might expect that here as well; I was at least confused about when first looking at this)

# Corner cases
inter = first.intersection(first, sort=sort)
assert inter is first
assert inter is not first
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
assert inter is not first
assert inter is not first
tm.assert_index_equal(inter, first)

Just to ensure it are still the same values

@jorisvandenbossche jorisvandenbossche changed the title BUG: Fix metadata mutation in Index set operations (intersection/unio… BUG: ensure to always return new objects in Index set operations (avoid metadata mutation) Dec 17, 2025
@deniskrds
Copy link
Contributor Author

Thanks for the review - all feedback addressed in the recent commits

Copy link
Member

@jorisvandenbossche jorisvandenbossche left a comment

Choose a reason for hiding this comment

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

Thanks!

@jorisvandenbossche jorisvandenbossche dismissed rhshadrach’s stale review December 19, 2025 16:03

comments are addressed

@jorisvandenbossche jorisvandenbossche merged commit d049ddf into pandas-dev:main Dec 19, 2025
41 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug Copy / view semantics Index Related to the Index class or subclasses setops union, intersection, difference, symmetric_difference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BUG: Index.intersection returns reference instead of new instance

3 participants