from types import ModuleType
from typing import Any
from typing import Callable
from typing import Dict
from typing import Generic
from typing import Iterable
from typing import Iterator
from typing import List
from typing import Mapping
from typing import NoReturn
from typing import Optional
from typing import overload
from typing import Tuple
from typing import Type
from typing import TypeVar
from typing import Union

from . import roles
from .elements import ColumnElement
from .traversals import HasCacheKey
from .traversals import HasCopyInternals
from .visitors import ClauseVisitor
from .. import util
from ..engine import Connection
from ..engine import Engine
from ..util import HasMemoized as HasMemoized
from ..util import langhelpers

_T = TypeVar("_T")
_SC = TypeVar("_SC", bound=SingletonConstant)
_O = TypeVar("_O", bound=Options)
_E = TypeVar("_E", bound=Executable)
_CE = TypeVar("_CE", bound=ColumnElement[Any])
_OCE = TypeVar("_OCE", bound=ColumnElement[Any])

coercions: ModuleType
elements: ModuleType
type_api: ModuleType
PARSE_AUTOCOMMIT: langhelpers._symbol
NO_ARG: langhelpers._symbol

class Immutable:
    def unique_params(self, *optionaldict: Any, **kwargs: Any) -> NoReturn: ...
    def params(self, *optionaldict: Any, **kwargs: Any) -> NoReturn: ...

class SingletonConstant(Immutable):
    def __new__(cls: Type[_SC], *arg: Any, **kw: Any) -> _SC: ...

class _DialectArgView(util.collections_abc.MutableMapping[str, Any]):
    obj: Any = ...
    def __init__(self, obj: Any) -> None: ...
    def __getitem__(self, key: str) -> Any: ...
    def __setitem__(self, key: str, value: Any) -> None: ...
    def __delitem__(self, key: str) -> None: ...
    def __len__(self) -> int: ...
    def __iter__(self) -> Iterator[str]: ...

class _DialectArgDict(util.collections_abc.MutableMapping[str, Any]):
    def __init__(self) -> None: ...
    def __len__(self) -> int: ...
    def __iter__(self) -> Iterator[str]: ...
    def __getitem__(self, key: str) -> Any: ...
    def __setitem__(self, key: str, value: Any) -> None: ...
    def __delitem__(self, key: str) -> None: ...

class DialectKWArgs:
    @classmethod
    def argument_for(
        cls, dialect_name: Any, argument_name: Any, default: Any
    ) -> None: ...
    @util.memoized_property
    def dialect_kwargs(self) -> _DialectArgView: ...
    @property
    def kwargs(self) -> _DialectArgView: ...
    @util.memoized_property
    def dialect_options(self) -> util.PopulateDict[str, _DialectArgDict]: ...

class CompileState:
    plugins: Any = ...
    @classmethod
    def create_for_statement(
        cls, statement: Any, compiler: Any, **kw: Any
    ) -> Any: ...
    statement: Any = ...
    def __init__(self, statement: Any, compiler: Any, **kw: Any) -> None: ...
    @classmethod
    def get_plugin_class(cls, statement: Any) -> Optional[Any]: ...
    @classmethod
    def plugin_for(
        cls, plugin_name: Any, visit_name: Any
    ) -> Callable[[_T], _T]: ...

class Generative(HasMemoized): ...
class InPlaceGenerative(HasMemoized): ...
class HasCompileState(Generative): ...

class _MetaOptions(type):
    def __init__(cls, classname: Any, bases: Any, dict_: Any) -> None: ...
    def __add__(self: Type[_T], other: Any) -> _T: ...

class Options(metaclass=_MetaOptions):
    def __init__(self, **kw: Any) -> None: ...
    def __add__(self: _O, other: Any) -> _O: ...
    def __eq__(self, other: Any) -> bool: ...
    @classmethod
    def isinstance(cls, klass: Any) -> bool: ...
    def add_to_element(self: _O, name: Any, value: Any) -> _O: ...
    @classmethod
    def safe_merge(cls: Type[_O], other: Any) -> _O: ...
    @classmethod
    def from_execution_options(
        cls,
        key: Any,
        attrs: Any,
        exec_options: Any,
        statement_exec_options: Any,
    ) -> Tuple[Any, Any]: ...

class CacheableOptions(Options, HasCacheKey): ...

class ExecutableOption(HasCopyInternals, HasCacheKey):
    __visit_name__: str = ...

class Executable(roles.CoerceTextStatementRole, Generative):
    supports_execution: bool = ...
    is_select: bool = ...
    is_update: bool = ...
    is_insert: bool = ...
    is_text: bool = ...
    is_delete: bool = ...
    is_dml: bool = ...
    def options(self: _E, *options: Any) -> _E: ...
    def execution_options(self: _E, **kw: Any) -> _E: ...
    def get_execution_options(self) -> Any: ...
    def execute(self, *multiparams: Any, **params: Any) -> Any: ...
    def scalar(self, *multiparams: Any, **params: Any) -> Any: ...
    @property
    def bind(self) -> Optional[Union[Engine, Connection]]: ...

class prefix_anon_map(Dict[str, str]):
    def __missing__(self, key: str) -> str: ...

class SchemaEventTarget: ...

class SchemaVisitor(ClauseVisitor):
    __traverse_options__: Any = ...

class ColumnCollection(Generic[_CE]):
    def __init__(
        self, columns: Optional[Iterable[Tuple[str, _CE]]] = ...
    ) -> None: ...
    def keys(self) -> List[str]: ...
    def values(self) -> List[_CE]: ...
    def items(self) -> List[Tuple[str, _CE]]: ...
    def __bool__(self) -> bool: ...
    def __len__(self) -> int: ...
    def __iter__(self) -> Iterator[_CE]: ...
    def __getitem__(self, key: str) -> _CE: ...
    def __getattr__(self, key: str) -> _CE: ...
    def __contains__(self, key: str) -> bool: ...
    def compare(self, other: Any) -> bool: ...
    def __eq__(self, other: Any) -> bool: ...
    @overload
    def get(self, key: str) -> Optional[_CE]: ...
    @overload
    def get(self, key: str, default: _T) -> Union[_CE, _T]: ...
    def __setitem__(self, key: str, value: _CE) -> None: ...
    def __delitem__(self, key: str) -> None: ...
    def __setattr__(self, key: str, obj: _CE) -> None: ...
    def clear(self) -> None: ...
    def remove(self, column: _CE) -> None: ...
    def update(
        self, iter_: Union[Mapping[str, _CE], Iterable[Tuple[str, _CE]]]
    ) -> None: ...
    __hash__: Any = ...
    def add(self, column: _CE, key: Optional[str] = ...) -> None: ...
    def contains_column(self, col: ColumnElement[Any]) -> bool: ...
    def as_immutable(self) -> ImmutableColumnCollection[_CE]: ...
    def corresponding_column(
        self, column: ColumnElement[Any], require_embedded: bool = ...
    ) -> Optional[_CE]: ...

class DedupeColumnCollection(ColumnCollection[_CE]):
    def add(self, column: _CE, key: Optional[str] = ...) -> None: ...
    def extend(self, iter_: Iterable[_CE]) -> None: ...
    def remove(self, column: _CE) -> None: ...
    def replace(self, column: _CE) -> None: ...

class ImmutableColumnCollection(
    util.ImmutableContainer, ColumnCollection[_CE]
):
    def __init__(self, collection: ColumnCollection[_CE]) -> None: ...
    def add(self, column: _CE, key: Optional[str] = ...) -> NoReturn: ...
    def extend(self, iter_: Iterable[_CE]) -> NoReturn: ...
    def remove(self, column: _CE) -> NoReturn: ...

class ColumnSet(util.ordered_column_set[_CE]):
    def contains_column(self, col: ColumnElement[Any]) -> bool: ...
    def extend(self, cols: Iterable[_CE]) -> None: ...
    def __add__(self, other: Iterable[_OCE]) -> List[Union[_CE, _OCE]]: ...  # type: ignore[override]
    def __eq__(self, other: Any) -> Any: ...
    def __hash__(self) -> int: ...  # type: ignore[override]
