from __future__ import print_function

import types
import typing
import unittest
from __builtin__ import unichr as unichr
from functools import wraps as wraps
from StringIO import StringIO as StringIO
from typing import (
    Any,
    AnyStr,
    Callable,
    ItemsView,
    Iterable,
    KeysView,
    Mapping,
    NoReturn,
    Pattern,
    Text,
    TypeVar,
    ValuesView,
    overload,
)
from typing_extensions import Literal

from . import moves

BytesIO = StringIO

_T = TypeVar("_T")
_K = TypeVar("_K")
_V = TypeVar("_V")

__author__: str
__version__: str

PY2: Literal[True]
PY3: Literal[False]
PY34: Literal[False]

string_types: tuple[type[str], type[unicode]]
integer_types: tuple[type[int], type[long]]
class_types: tuple[type[type[Any]], type[types.ClassType]]
text_type: type[unicode]
binary_type: type[str]

MAXSIZE: int

def advance_iterator(it: typing.Iterator[_T]) -> _T: ...

next = advance_iterator

def callable(obj: object) -> bool: ...
def get_unbound_function(unbound: types.MethodType) -> types.FunctionType: ...
def create_bound_method(func: types.FunctionType, obj: object) -> types.MethodType: ...
def create_unbound_method(func: types.FunctionType, cls: type | types.ClassType) -> types.MethodType: ...

class Iterator:
    def next(self) -> Any: ...

def get_method_function(meth: types.MethodType) -> types.FunctionType: ...
def get_method_self(meth: types.MethodType) -> object | None: ...
def get_function_closure(fun: types.FunctionType) -> tuple[types._Cell, ...] | None: ...
def get_function_code(fun: types.FunctionType) -> types.CodeType: ...
def get_function_defaults(fun: types.FunctionType) -> tuple[Any, ...] | None: ...
def get_function_globals(fun: types.FunctionType) -> dict[str, Any]: ...
def iterkeys(d: Mapping[_K, _V]) -> typing.Iterator[_K]: ...
def itervalues(d: Mapping[_K, _V]) -> typing.Iterator[_V]: ...
def iteritems(d: Mapping[_K, _V]) -> typing.Iterator[tuple[_K, _V]]: ...

# def iterlists

def viewkeys(d: Mapping[_K, _V]) -> KeysView[_K]: ...
def viewvalues(d: Mapping[_K, _V]) -> ValuesView[_V]: ...
def viewitems(d: Mapping[_K, _V]) -> ItemsView[_K, _V]: ...
def b(s: str) -> str: ...
def u(s: str) -> unicode: ...

int2byte = chr

def byte2int(bs: str) -> int: ...
def indexbytes(buf: str, i: int) -> int: ...
def iterbytes(buf: str) -> typing.Iterator[int]: ...
def assertCountEqual(self: unittest.TestCase, first: Iterable[_T], second: Iterable[_T], msg: str = ...) -> None: ...
@overload
def assertRaisesRegex(self: unittest.TestCase, msg: str = ...) -> Any: ...
@overload
def assertRaisesRegex(self: unittest.TestCase, callable_obj: Callable[..., Any], *args: Any, **kwargs: Any) -> Any: ...
def assertRegex(self: unittest.TestCase, text: AnyStr, expected_regex: AnyStr | Pattern[AnyStr], msg: str = ...) -> None: ...
def reraise(tp: type[BaseException] | None, value: BaseException | None, tb: types.TracebackType | None = ...) -> NoReturn: ...
def exec_(_code_: unicode | types.CodeType, _globs_: dict[str, Any] = ..., _locs_: dict[str, Any] = ...): ...
def raise_from(value: BaseException | type[BaseException], from_value: BaseException | None) -> NoReturn: ...

print_ = print

def with_metaclass(meta: type, *bases: type) -> type: ...
def add_metaclass(metaclass: type) -> Callable[[_T], _T]: ...
def ensure_binary(s: bytes | Text, encoding: str = ..., errors: str = ...) -> bytes: ...
def ensure_str(s: bytes | Text, encoding: str = ..., errors: str = ...) -> str: ...
def ensure_text(s: bytes | Text, encoding: str = ..., errors: str = ...) -> Text: ...
def python_2_unicode_compatible(klass: _T) -> _T: ...

class _LazyDescr(object):
    name: str
    def __init__(self, name: str) -> None: ...
    def __get__(self, obj: object | None, type: type[Any] | None = ...) -> Any: ...

class MovedModule(_LazyDescr):
    mod: str
    def __init__(self, name: str, old: str, new: str | None = ...) -> None: ...
    def __getattr__(self, attr: str) -> Any: ...

class MovedAttribute(_LazyDescr):
    mod: str
    attr: str
    def __init__(self, name: str, old_mod: str, new_mod: str, old_attr: str | None = ..., new_attr: str | None = ...) -> None: ...

def add_move(move: MovedModule | MovedAttribute) -> None: ...
def remove_move(name: str) -> None: ...
