You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
mypy doesn't understand set operations on optional #13192
I have tried to search for similar issues but failed because I can't find the keywords to limit the open issues to a manageable list. Sorry if it's indeed an old bug. Hope someone here can help
Bug Report
mypy doesn't seem to understand that Set[Optional[T]] minus None is just Set[T]
> python3 -m mypy temp.py
temp.py:3: error: Incompatible types in assignment (expression has type "Set[Optional[str]]", variable has type "Set[str]")
temp.py:5: error: Incompatible types in assignment (expression has type "Optional[Set[Optional[str]]]", variable has type "Optional[Set[str]]")
Found 2 errors in 1 file (checked 1 source file)
Well that one is different since it's about is and if - core syntax, unlike set operations here which are regular magic method operations.
Implementing the other singleton objects too would be tricky, since you'd need to account for all possible combinations of NotImplemented, None, Ellipsis, True and False. Bools might not really work since {False, True} is just going to have a type of set[bool], it's not going to track whether or not both values are present which you'd need in order to remove from the union.
I agree with @TeamSpen210. There's no generalised way in the type system at the moment of indicating that a type is a singleton, and I don't think there would be enough use cases to make it worth the added complexity of creating a generalised way of doing that. The changes made in #13117 are highly specific to EllipsisType; it's the opposite of "special casing for singleton types in general".
I'm closing this as I don't think there's anything actionable for mypy here. If we did want to do something in this area, the change would have to be made over at typeshed.
Thanks, @erictraut! (I hadn't considered a comprehension because it wasn't verifying the type of the set, but that works 99% of the time. Where zero-copy/performance really matters, there's always cast().)
If this issue is ever reconsidered, I'd like to offer a thought: perhaps an every() function would help make set narrowing more type-agnostic and relatively affordable to implement:
Te=TypeVar('Te', bound=bool|Enum|Ellipsis|None)
defevery(type_: Type[Te], /) ->CompleteFrozenSet[Te]:
'''returns every member of an enumerable type Args: type_: 'None', 'bool', 'Ellipsis', or an 'Enum' type Returns: a frozen set containing every value of the given type '''# magic happensreturn ...
classCompleteFrozenSet(FrozenSet[T]):
'''(empty body)'''# (I'm not sure if this would work as written:)classSet(...):
...
@overloaddef__isub__(self: Set[A|B], other: CompleteFrozenSet[B]) ->Set[A]: ...
....
I suppose an def __every__(self: Type[Te]) -> CompleteFrozenSet[Te]: ... magic method would be the natural extension to other types.
Activity
AlexWaygood commentedon Jul 20, 2022
The typeshed stub for the
__sub__method ofbuiltins.setis currently:I guess we could special-case
Nonein the stub:But I'm not sure this kind of thing is common enough to be worth special-casing here.
Such a change would have to happen over at the typeshed repo rather than the mypy repo, since mypy vendors its stdlib stubs from typeshed.
tungol commentedon Jul 22, 2022
Shouldn't the special casing should really be for singleton types in general, similar to the changes made here? #13117
TeamSpen210 commentedon Jul 22, 2022
Well that one is different since it's about
isandif- core syntax, unlike set operations here which are regular magic method operations.Implementing the other singleton objects too would be tricky, since you'd need to account for all possible combinations of
NotImplemented,None,Ellipsis,TrueandFalse. Bools might not really work since{False, True}is just going to have a type ofset[bool], it's not going to track whether or not both values are present which you'd need in order to remove from the union.AlexWaygood commentedon Jul 23, 2022
I agree with @TeamSpen210. There's no generalised way in the type system at the moment of indicating that a type is a singleton, and I don't think there would be enough use cases to make it worth the added complexity of creating a generalised way of doing that. The changes made in #13117 are highly specific to
EllipsisType; it's the opposite of "special casing for singleton types in general".I'm closing this as I don't think there's anything actionable for mypy here. If we did want to do something in this area, the change would have to be made over at typeshed.
finite-state-machine commentedon Feb 11, 2024
Is there a suggested workaround, short of resorting to a
cast()?I've tried the kitchen sink without success (mypy-play.net):
[edited to use
frozenset()rather thanset()]erictraut commentedon Feb 11, 2024
Here's a straightforward workaround:
finite-state-machine commentedon Feb 11, 2024
Thanks, @erictraut! (I hadn't considered a comprehension because it wasn't verifying the type of the set, but that works 99% of the time. Where zero-copy/performance really matters, there's always
cast().)If this issue is ever reconsidered, I'd like to offer a thought: perhaps an
every()function would help make set narrowing more type-agnostic and relatively affordable to implement:I suppose an
def __every__(self: Type[Te]) -> CompleteFrozenSet[Te]: ...magic method would be the natural extension to other types.I do realize this probably isn't a priority.