from collections.abc import Callable, Iterable, Iterator
from typing import Any

from django.http.request import HttpRequest
from django.template.base import Node, Origin, Template
from django.template.defaulttags import IfChangedNode
from django.template.loader_tags import IncludeNode

_ContextValues = dict[str, Any] | Context

class ContextPopException(Exception): ...

class ContextDict(dict[Any, Any]):
    context: BaseContext = ...
    def __init__(self, context: BaseContext, *args: Any, **kwargs: Any) -> None: ...
    def __enter__(self) -> ContextDict: ...
    def __exit__(self, *args: Any, **kwargs: Any) -> None: ...

class BaseContext(Iterable[Any]):
    def __init__(self, dict_: Any = ...) -> None: ...
    def __copy__(self) -> BaseContext: ...
    def __iter__(self) -> Iterator[Any]: ...
    def push(self, *args: Any, **kwargs: Any) -> ContextDict: ...
    def pop(self) -> ContextDict: ...
    def __setitem__(self, key: Node | str, value: Any) -> None: ...
    def set_upward(self, key: str, value: int | str) -> None: ...
    def __getitem__(self, key: int | str) -> Any: ...
    def __delitem__(self, key: Any) -> None: ...
    def __contains__(self, key: str) -> bool: ...
    def get(self, key: str, otherwise: Any | None = ...) -> Any | None: ...
    def setdefault(
        self,
        key: IfChangedNode | str,
        default: list[Origin] | int | None = ...,
    ) -> list[Origin] | int | None: ...
    def new(self, values: _ContextValues | None = ...) -> Context: ...
    def flatten(
        self,
    ) -> dict[str, dict[str, type[Any] | str] | int | str | None]: ...

class Context(BaseContext):
    dicts: Any
    autoescape: bool = ...
    use_l10n: bool | None = ...
    use_tz: bool | None = ...
    template_name: str | None = ...
    render_context: RenderContext = ...
    template: Template | None = ...
    def __init__(
        self,
        dict_: Any = ...,
        autoescape: bool = ...,
        use_l10n: bool | None = ...,
        use_tz: None = ...,
    ) -> None: ...
    def bind_template(self, template: Template) -> Iterator[None]: ...
    def update(self, other_dict: dict[str, Any] | Context) -> ContextDict: ...

class RenderContext(BaseContext):
    dicts: list[dict[IncludeNode | str, str]]
    template: Template | None = ...
    def push_state(
        self, template: Template, isolated_context: bool = ...
    ) -> Iterator[None]: ...

class RequestContext(Context):
    autoescape: bool
    dicts: list[dict[str, str]]
    render_context: RenderContext
    template_name: str | None
    use_l10n: None
    use_tz: None
    request: HttpRequest = ...
    def __init__(
        self,
        request: HttpRequest,
        dict_: dict[str, Any] | None = ...,
        processors: list[Callable[..., Any]] | None = ...,
        use_l10n: None = ...,
        use_tz: None = ...,
        autoescape: bool = ...,
    ) -> None: ...
    template: Template | None = ...
    def bind_template(self, template: Template) -> Iterator[None]: ...
    def new(self, values: _ContextValues | None = ...) -> RequestContext: ...

def make_context(
    context: Any, request: HttpRequest | None = ..., **kwargs: Any
) -> Context: ...
