from typing import Any
from typing import Callable
from typing import Iterator
from typing import Optional
from typing import Type

from . import elements
from . import roles
from .base import Options
from .operators import ColumnOperators

class LambdaOptions(Options):
    enable_tracking: bool = ...
    track_closure_variables: bool = ...
    track_on: Any = ...
    global_track_bound_values: bool = ...
    track_bound_values: bool = ...
    lambda_cache: Any = ...

def lambda_stmt(
    lmb: Any,
    enable_tracking: bool = ...,
    track_closure_variables: bool = ...,
    track_on: Optional[Any] = ...,
    global_track_bound_values: bool = ...,
    track_bound_values: bool = ...,
    lambda_cache: Optional[Any] = ...,
) -> StatementLambdaElement: ...

class LambdaElement(elements.ClauseElement):
    __visit_name__: str = ...
    parent_lambda: Any = ...
    fn: Callable[..., elements.ClauseElement] = ...
    role: Type[Any] = ...
    tracker_key: Any = ...
    opts: Any = ...
    def __init__(
        self,
        fn: Callable[..., elements.ClauseElement],
        role: Type[Any],
        opts: Any = ...,
        apply_propagate_attrs: Optional[Any] = ...,
    ) -> None: ...
    def __getattr__(self, key: Any) -> Any: ...

class DeferredLambdaElement(LambdaElement):
    lambda_args: Any = ...
    def __init__(
        self,
        fn: Callable[..., elements.ClauseElement],
        role: Type[Any],
        opts: Any = ...,
        lambda_args: Any = ...,
    ) -> None: ...

class StatementLambdaElement(roles.AllowsLambdaRole, LambdaElement):
    def __add__(self, other: Any) -> LinkedLambdaElement: ...
    def add_criteria(
        self,
        other: Any,
        enable_tracking: bool = ...,
        track_on: Optional[Any] = ...,
        track_closure_variables: bool = ...,
        track_bound_values: bool = ...,
    ) -> LinkedLambdaElement: ...
    def spoil(self) -> NullLambdaStatement: ...

class NullLambdaStatement(roles.AllowsLambdaRole, elements.ClauseElement):
    __visit_name__: str = ...
    def __init__(self, statement: Any) -> None: ...
    def __getattr__(self, key: Any) -> Any: ...
    def __add__(self, other: Any) -> NullLambdaStatement: ...
    def add_criteria(self, other: Any, **kw: Any) -> NullLambdaStatement: ...

class LinkedLambdaElement(StatementLambdaElement):
    role: Any = ...
    opts: Any = ...
    fn: Any = ...
    parent_lambda: Any = ...
    tracker_key: Any = ...
    def __init__(
        self,
        fn: Callable[..., elements.ClauseElement],
        parent_lambda: StatementLambdaElement,
        opts: Any,
    ) -> None: ...

class AnalyzedCode:
    @classmethod
    def get(
        cls,
        fn: Callable[..., elements.ClauseElement],
        lambda_element: LambdaElement,
        lambda_kw: Any,
        **kw: Any,
    ) -> Any: ...
    track_bound_values: Any = ...
    track_closure_variables: Any = ...
    bindparam_trackers: Any = ...
    closure_trackers: Any = ...
    build_py_wrappers: Any = ...
    def __init__(
        self,
        fn: Callable[..., elements.ClauseElement],
        lambda_element: LambdaElement,
        opts: Any,
    ) -> None: ...

class AnalyzedFunction:
    analyzed_code: Any = ...
    fn: Callable[..., elements.ClauseElement] = ...
    bindparam_trackers: Any = ...
    def __init__(
        self,
        analyzed_code: Any,
        lambda_element: LambdaElement,
        apply_propagate_attrs: Any,
        fn: Callable[..., elements.ClauseElement],
    ) -> None: ...

class PyWrapper(ColumnOperators):
    fn: Callable[..., elements.ClauseElement] = ...
    track_bound_values: Any = ...
    def __init__(
        self,
        fn: Callable[..., elements.ClauseElement],
        name: str,
        to_evaluate: Any,
        closure_index: Optional[Any] = ...,
        getter: Optional[Any] = ...,
        track_bound_values: bool = ...,
    ) -> None: ...
    def __call__(self, *arg: Any, **kw: Any) -> Any: ...
    def operate(
        self, op: Any, *other: Any, **kwargs: Any
    ) -> elements.ClauseElement: ...
    def reverse_operate(
        self, op: Any, other: Any, **kwargs: Any
    ) -> elements.ClauseElement: ...
    def __clause_element__(self) -> elements.ClauseElement: ...
    def __bool__(self) -> bool: ...
    def __nonzero__(self) -> bool: ...
    def __getattribute__(self, key: Any) -> Any: ...
    def __iter__(self) -> Iterator[Any]: ...
    def __getitem__(self, key: Any) -> Any: ...

def insp(lmb: Any) -> Any: ...
