Repository navigation
Fix set xor return types for abstract sets - #16127
Conversation
This comment has been minimized.
This comment has been minimized.
|
To be 100% correct the input type should be widened to |
| @overload | ||
| def __xor__(self, value: set[_S] | frozenset[_S], /) -> set[_T | _S]: ... | ||
| @overload | ||
| def __xor__(self, value: AbstractSet[_S], /) -> AbstractSet[_T | _S]: ... |
There was a problem hiding this comment.
This seems incorrect, set.__xor__ doesn't return this. It only accepts set and frozenset. xor with AbstractSets instead works through an __rxor__ method on those other sets.
There was a problem hiding this comment.
Updated the builtin signatures to accept only set/frozenset and added AbstractSet.rxor for reflected dispatch; the regression test checks both paths. Could you take another look?
There was a problem hiding this comment.
My comment was completely ignored, but I'm insisting on the fact that AbstractSet inputs should be widened to Iterable. Most are currently incorrectly constrained to AbstractSet.
the actual code:
def __and__(self, other):
if not isinstance(other, Iterable):
return NotImplemented
return self._from_iterable(value for value in other if value in self)
__rand__ = __and__
def isdisjoint(self, other):
"""Return True if two sets have a null intersection."""
for value in other:
if value in self:
return False
return True
def __or__(self, other):
if not isinstance(other, Iterable):
return NotImplemented
chain = (e for s in (self, other) for e in s)
return self._from_iterable(chain)
__ror__ = __or__
def __sub__(self, other):
if not isinstance(other, Set):
if not isinstance(other, Iterable):
return NotImplemented
other = self._from_iterable(other)
return self._from_iterable(value for value in self if value not in other)
def __rsub__(self, other):
if not isinstance(other, Set):
if not isinstance(other, Iterable):
return NotImplemented
other = self._from_iterable(other)
return self._from_iterable(value for value in other if value not in self)
def __xor__(self, other):
if not isinstance(other, Set):
if not isinstance(other, Iterable):
return NotImplemented
other = self._from_iterable(other)
return (self - other) | (other - self)
__rxor__ = __xor__rxor having a signature different to xor don't make sense here. The rxor simply defer to xor.
This comment has been minimized.
This comment has been minimized.
|
The local conflict resolution preserves the newer reflected overloads and restores reflected XOR support for AbstractSet The focused typing checks pass. The update has not been pushed yet |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
According to mypy_primer, this change has no effect on the checked open source code. 🤖🎉 |
Fixes #16115.
set.__xor__andfrozenset.__xor__returnNotImplementedfor arbitrarycollections.abc.Setimplementations, allowing reflected dispatch to determine the result type. Preserve the concrete return typefor built-in set operands and return
AbstractSetfor the general case.The new test covers both built-in left operands with an abstract set right operand.