from contextlib import contextmanager
from types import TracebackType
from typing import Any, BinaryIO, ContextManager, Dict, Iterator, List, Mapping, Optional, Sequence, Tuple, Type, Union

from django.contrib.auth.base_user import AbstractBaseUser
from django.contrib.auth.models import AnonymousUser
from django.http import HttpRequest, QueryDict

from django.contrib.sessions.backends.base import SessionBase
from django.contrib.sites.models import Site
from django.urls import ResolverMatch
from rest_framework.authentication import BaseAuthentication
from rest_framework.authtoken.models import Token

from rest_framework.negotiation import BaseContentNegotiation
from rest_framework.parsers import BaseParser
from rest_framework.versioning import BaseVersioning
from rest_framework.views import APIView
from django.utils.datastructures import MultiValueDict
from django.core.files import uploadedfile, uploadhandler
from django.utils.datastructures import ImmutableList, MultiValueDict
from django.http.request import HttpHeaders

_UploadHandlerList = Union[List[uploadhandler.FileUploadHandler], ImmutableList[uploadhandler.FileUploadHandler]]

def is_form_media_type(media_type: str) -> bool: ...

class override_method(ContextManager["Request"]):
    def __init__(self, view: APIView, request: Request, method: str): ...
    def __enter__(self) -> Request: ...
    def __exit__(
        self,
        exc_type: Optional[Type[BaseException]],
        exc_value: Optional[BaseException],
        traceback: Optional[TracebackType],
    ) -> Optional[bool]: ...

class WrappedAttributeError(Exception): ...

@contextmanager
def wrap_attributeerrors() -> Iterator[None]: ...

class Empty: ...

def clone_request(request: Request, method: str) -> Request: ...

class ForcedAuthentication:
    force_user: Optional[Union[AnonymousUser, AbstractBaseUser]] = ...
    force_token: Optional[str] = ...
    def __init__(
        self, force_user: Optional[Union[AnonymousUser, AbstractBaseUser]], force_token: Optional[str]
    ) -> None: ...
    def authenticate(
        self, request: Request
    ) -> Tuple[Optional[Union[AnonymousUser, AbstractBaseUser]], Optional[Any]]: ...

class Request(HttpRequest):
    parsers: Optional[Sequence[BaseParser]] = ...
    authenticators: Optional[Sequence[Union[BaseAuthentication, ForcedAuthentication]]] = ...
    negotiator: Optional[BaseContentNegotiation] = ...
    parser_context: Optional[Dict[str, Any]] = ...
    version: Optional[str]
    versioning_scheme: Optional[BaseVersioning]
    _request: HttpRequest
    GET: QueryDict = ...
    POST: QueryDict = ...
    COOKIES: Dict[str, str] = ...
    META: Dict[str, Any] = ...
    FILES: MultiValueDict[str, uploadedfile.UploadedFile] = ...
    path: str = ...
    path_info: str = ...
    method: Optional[str] = ...
    resolver_match: ResolverMatch = ...
    content_type: Optional[str] = ...
    content_params: Optional[Dict[str, str]] = ...
    user: Union[AbstractBaseUser, AnonymousUser]
    site: Site
    session: SessionBase
    encoding: Optional[str] = ...
    upload_handlers: _UploadHandlerList = ...
    def __init__(
        self,
        request: HttpRequest,
        parsers: Optional[Sequence[BaseParser]] = ...,
        authenticators: Optional[Sequence[BaseAuthentication]] = ...,
        negotiator: Optional[BaseContentNegotiation] = ...,
        parser_context: Optional[Dict[str, Any]] = ...,
    ) -> None: ...
    def get_host(self) -> str: ...
    def get_port(self) -> str: ...
    def get_full_path(self, force_append_slash: bool = ...) -> str: ...
    def get_full_path_info(self, force_append_slash: bool = ...) -> str: ...
    def get_signed_cookie(
        self, key: str, default: Any = ..., salt: str = ..., max_age: Optional[int] = ...
    ) -> Optional[str]: ...
    def get_raw_uri(self) -> str: ...
    def build_absolute_uri(self, location: Optional[str] = ...) -> str: ...
    @property
    def scheme(self) -> Optional[str]: ...
    def is_secure(self) -> bool: ...
    def is_ajax(self) -> bool: ...
    def parse_file_upload(
        self, META: Mapping[str, Any], post_data: BinaryIO
    ) -> Tuple[QueryDict, MultiValueDict[str, uploadedfile.UploadedFile]]: ...
    @property
    def headers(self) -> HttpHeaders: ...
    @property
    def body(self) -> bytes: ...
    def _load_post_and_files(self) -> None: ...
    def content_type(self) -> str: ...  # type: ignore[override]
    @property
    def stream(self) -> Any: ...
    @property
    def query_params(self) -> QueryDict: ...
    @property
    def data(self) -> Dict[str, Any]: ...
    @property  # type: ignore[override]
    def user(self) -> Union[AbstractBaseUser, AnonymousUser]: ...  # type: ignore[override]
    @user.setter
    def user(self, value: Union[AbstractBaseUser, AnonymousUser]) -> None: ...
    @property
    def auth(self) -> Union[Token, Any]: ...
    @auth.setter
    def auth(self, value: Union[Token, Any]) -> None: ...
    @property
    def successful_authenticator(self) -> Optional[Union[BaseAuthentication, ForcedAuthentication]]: ...
    @property
    def DATA(self) -> None: ...
    @property
    def POST(self) -> QueryDict: ...  # type: ignore[override]
    @property
    def FILES(self) -> Any: ...  # type: ignore [override]
    @property
    def QUERY_PARAMS(self) -> None: ...
    def force_plaintext_errors(self, value: Any) -> None: ...
