from typing import Any, Mapping, MutableMapping, List, Union, Iterable
from typing import KeysView, ValuesView, ItemsView, Iterator, Tuple
from typing import overload, TypeVar, Generic, Optional


class istr(str): ...

upstr = istr

_S = Union[str, istr]

_T = TypeVar('_T')


class MultiDict(MutableMapping[_S, _T], Generic[_T]):
    @overload
    def __init__(self) -> None: ...
    @overload
    def __init__(self, map: Mapping[_S, _T]) -> None: ...
    @overload
    def __init__(self, iterable: Iterable[Tuple[_S, _T]]) -> None: ...

    def getall(self, key: _S, default: _T=...) -> List[_T]: ...
    def getone(self, key: _S, default: _T=...) -> _T: ...

    def __getitem__(self, key: _S) -> _T: ...

    def get(self, key: _S, default: Optional[_T]=None) -> _T: ...

    def __iter__(self) -> Iterator[_S]: ...
    def __len__(self) -> int: ...
    def keys(self) -> KeysView[_S]: ...
    def items(self) -> ItemsView[_S, _T]: ...
    def values(self) -> ValuesView[_T]: ...

    def __eq__(self, other) -> bool: ...
    def __contains__(self, key) -> bool: ...
    def __repr__(self) -> str: ...

    def copy(self) -> MultiDict: ...

    def add(self, key: _S, value: _T) -> None: ...

    @overload
    def __extend__(self, dct: MultiDict[_T]) -> None: ...
    @overload
    def __extend__(self, map: Mapping[_S, _T]) -> None: ...
    @overload
    def __extend__(self, iterable: Iterable[Tuple[_S, _T]]) -> None: ...

    def clear(self) -> None: ...
    def __setitem__(self, key: _S, value) -> None: ...
    def __delitem__(self, key: _S) -> None: ...
    def setdefault(self, key: _S, default: _T=None) -> _T: ...
    @overload
    def pop(self, key: _S) -> _T: ...
    @overload
    def pop(self, key: _S, default: _T=...) -> _T: ...
    def popitem(self) -> Tuple[_S, _T]: ...


class CIMultiDict(MultiDict[_T], Generic[_T]):
    def copy(self) -> CIMultiDict[_T]: ...


class MultiDictProxy(Mapping[_S, _T], Generic[_T]):
    def getall(self, key: _S, default: _T=...) -> List[_T]: ...
    def getone(self, key: _S, default: _T=...) -> _T: ...

    def __getitem__(self, key: _S) -> _T: ...

    def get(self, key: _S, default: Optional[_T]=None) -> _T: ...

    def __iter__(self) -> Iterator[_S]: ...
    def __len__(self) -> int: ...
    def keys(self) -> KeysView[_S]: ...
    def items(self) -> ItemsView[_S, _T]: ...
    def values(self) -> ValuesView[_T]: ...

    def __eq__(self, other) -> bool: ...
    def __contains__(self, key) -> bool: ...
    def __repr__(self) -> str: ...

    def copy(self) -> MultiDictProxy: ...

    def __init__(self, arg: Union[MultiDict[_T], MultiDictProxy[_T]]) -> None: ...


class CIMultiDictProxy(MultiDictProxy[_T], Generic[_T]):
    def copy(self) -> CIMultiDictProxy[_T]: ...
