Repository: sympy/sympy
File: sympy/logic/boolalg.py (Python)

Code before:
        return false if z else true
    if isinstance(e, Boolean):
        return e
    raise TypeError('expecting bool or Boolean, not `%s`.' % e)


@sympify_method_args
class Boolean(Basic):
    """A Boolean object is an object for which logic operations make sense."""

    __slots__ = ()

    kind = BooleanKind

    if TYPE_CHECKING:
        from sympy.sets.sets import Set
        from sympy.core.relational import Relational

        def __new__(cls, *args: Basic | complex) -> Boolean:
            ...

        @overload # type: ignore
        def subs(self, arg1: Mapping[Basic | complex, Boolean | complex], arg2: None=None) -> Boolean: ...
        @overload
        def subs(self, arg1: Mapping[Relational, BooleanTrue | BooleanFalse], arg2: None=None) -> Boolean: ...
        @overload
        def subs(self, arg1: Iterable[tuple[Basic | complex, Boolean | complex]], arg2: None=None, **kwargs: Any) -> Boolean: ...
        @overload
        def subs(self, arg1: Boolean | complex, arg2: Boolean | complex) -> Boolean: ...
        @overload
        def subs(self, arg1: Mapping[Basic | complex, Basic | complex], arg2: None=None, **kwargs: Any) -> Basic: ...
        @overload
        def subs(self, arg1: Iterable[tuple[Basic | complex, Basic | complex]], arg2: None=None, **kwargs: Any) -> Basic: ...
        @overload
        def subs(self, arg1: Basic | complex, arg2: Basic | complex, **kwargs: Any) -> Basic: ...

        def subs(self, arg1: Mapping[Basic | complex, Basic | complex] | Basic | complex, # type: ignore
                 arg2: Basic | complex | None = None, **kwargs: Any) -> Basic:
            ...

        def simplify(self, **kwargs) -> Boolean:
            ...

    @sympify_return([('other', 'Boolean')], NotImplemented)
    def __and__(self, other: Boolean) -> Boolean:
        return And(self, other)

    __rand__ = __and__

    @sympify_return([('other', 'Boolean')], NotImplemented)
    def __or__(self, other: Boolean) -> Boolean:

Review comment (suggestion):
I was wondering why the first overload here does not cover this but then I remember now that Mapping is not covariant in the key type:
https://github.com/python/typing/issues/445

For now the overload you have added here is fine but in future this could lead to an explosion of overloads. We probably need to define a covariant version of Mapping. Looking at the implementation of Basic.subs the type could be like:
```python
class SupportsItems(Protocol[K, V]):
    def items(self) -> Iterable[tuple[K, V]]:
        ...

@overload
def subs(
    self,
    arg1: Iterable[tuple[Basic | complex, Basic | complex]]
    | SupportsItems[Basic | complex, Basic | complex],
    arg2: None = None,
    **kwargs: Any,
) -> Basic: ...
@overload
def subs(
    self, arg1: Basic | complex, arg2: Basic | complex, **kwargs: Any
) -> Basic: ...
```
Then SupportsItems is covariant in K and V.

Code after:
            return e
        return false if z else true
    if isinstance(e, Boolean):
        return e
    raise TypeError('expecting bool or Boolean, not `%s`.' % e)


@sympify_method_args
class Boolean(Basic):
    """A Boolean object is an object for which logic operations make sense."""

    __slots__ = ()

    kind = BooleanKind

    if TYPE_CHECKING:
        from sympy.sets.sets import Set

        def __new__(cls, *args: Basic | complex) -> Boolean:
            ...

        @overload # type: ignore
        def subs(self, arg1: _SupportsItems[Basic | complex, Boolean | complex]
                 | Iterable[tuple[Basic | complex, Boolean | complex]],
                 arg2: None=None, **kwargs: Any) -> Boolean: ...
        @overload
        def subs(self, arg1: Boolean | complex, arg2: Boolean | complex) -> Boolean: ...
        @overload
        def subs(self, arg1: _SupportsItems[Basic | complex, Basic | complex]
                 | Iterable[tuple[Basic | complex, Basic | complex]],
                 arg2: None=None, **kwargs: Any) -> Basic: ...
        @overload
        def subs(self, arg1: Basic | complex, arg2: Basic | complex, **kwargs: Any) -> Basic: ...

        def subs(self, arg1: _SupportsItems[Basic | complex, Basic | complex] | Basic | complex, # type: ignore
                 arg2: Basic | complex | None = None, **kwargs: Any) -> Basic:
            ...

        def simplify(self, **kwargs) -> Boolean:
            ...

    @sympify_return([('other', 'Boolean')], NotImplemented)
    def __and__(self, other: Boolean | bool) -> Boolean:
        return And(self, other)

    __rand__ = __and__

    @sympify_return([('other', 'Boolean')], NotImplemented)
    def __or__(self, other: Boolean | bool) -> Boolean:
        return Or(self, other)