from typing import Any, Container, Hashable, Iterable, Iterator, Optional, Sequence, Tuple, Type, TypeVar, Union

from typing_extensions import Protocol  # typing.Protocol is available in Python 3.8+

ExceptionsType = Union[Type[Exception], Tuple[Type[Exception], ...]]
Number = Union[int, float]
T_co = TypeVar("T_co", covariant=True)


class HashableContainer(Protocol[T_co], Hashable, Container[T_co]):
    pass


class SizedIterable(Protocol[T_co]):
    def __len__(self) -> int: ...

    def __iter__(self) -> Iterator[T_co]: ...


class Comparable(Protocol):
    def __eq__(self, other: Any) -> bool: ...

    def __ne__(self, other: Any) -> bool: ...


class Orderable(Protocol):
    def __lt__(self, other: Any) -> bool: ...

    def __gt__(self, other: Any) -> bool: ...

    def __le__(self, other: Any) -> bool: ...

    def __ge__(self, other: Any) -> bool: ...


class Computable(Protocol):
    def __neg__(self) -> Any: ...

    def __add__(self, other: Any) -> Any: ...

    def __sub__(self, other: Any) -> Any: ...

    def __mul__(self, other: Any) -> Any: ...

    def __truediv__(self, other: Any) -> Any: ...

    def __floordiv__(self, other: Any) -> Any: ...

    def __abs__(self) -> Any: ...


class MutableComputable(Protocol):
    def __neg__(self) -> Any: ...

    def __add__(self, other: Any) -> Any: ...

    def __iadd__(self, other: Any) -> Any: ...

    def __sub__(self, other: Any) -> Any: ...

    def __isub__(self, other: Any) -> Any: ...

    def __mul__(self, other: Any) -> Any: ...

    def __imul__(self, other: Any) -> Any: ...

    def __truediv__(self, other: Any) -> Any: ...

    def __itruediv__(self, other: Any) -> Any: ...

    def __floordiv__(self, other: Any) -> Any: ...

    def __ifloordiv__(self, other: Any) -> Any: ...


class Cursor(Protocol):
    def callproc(self, procname: str, parameters: Optional[Sequence[Any]]) -> None: ...

    def close(self) -> None: ...

    def execute(self, operation: str, parameters: Optional[Sequence[Any]]) -> None: ...

    def executemany(self, operation: str, seq_of_parameters: Sequence[Sequence[Any]]) -> None: ...

    def fetchone(self) -> Optional[Sequence[Any]]: ...

    def fetchmany(self, size: Optional[int]) -> Sequence[Sequence[Any]]: ...

    def fetchall(self) -> Sequence[Sequence[Any]]: ...

    def nextset(self) -> Optional[bool]: ...

    def setinputsizes(self, sizes: Sequence[int]) -> None: ...

    def setoutputsize(self, size: int, column: Optional[int]) -> None: ...


class Connection(Protocol):
    def close(self) -> None: ...

    def commit(self) -> None: ...

    def rollback(self) -> None: ...

    def cursor(self) -> Cursor: ...


class CsvWriter(Protocol):
    def writerow(self, row: Iterable[Any]) -> Any: ...

    def writerows(self, rows: Iterable[Iterable[Any]]) -> None: ...
