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]):
    @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 __getitem__(self, k: _S) -> _T: ...
    def __setitem__(self, k: _S, v: _T) -> None: ...
    def __delitem__(self, v: _S) -> None: ...
    def __iter__(self) -> Iterator[_S]: ...
    def __len__(self) -> int: ...

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

    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: ...

    @overload
    def popone(self, key: _S) -> _T: ...
    @overload
    def popone(self, key: _S, default: _T=...) -> _T: ...

    @overload
    def popall(self, key: _S) -> List[_T]: ...
    @overload
    def popall(self, key: _S, default: _T=...) -> List[_T]: ...


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


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

    def __getitem__(self, k: _S) -> _T: ...
    def __iter__(self) -> Iterator[_S]: ...
    def __len__(self) -> int: ...

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

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



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


def getversion(md: Union[MultiDict[_T],
                         CIMultiDict[_T],
                         MultiDictProxy[_T],
                         CIMultiDictProxy[_T]]) -> int: ...
