from collections.abc import Iterator
from io import BytesIO, StringIO
from typing import Any

from django.http.request import QueryDict
from django.utils.datastructures import ImmutableList, MultiValueDict

class MultiPartParserError(Exception): ...
class InputStreamExhausted(Exception): ...

class MultiPartParser:
    def __init__(
        self,
        META: dict[str, Any],
        input_data: StringIO | BytesIO,
        upload_handlers: list[Any] | ImmutableList[Any],
        encoding: str | None = ...,
    ) -> None: ...
    def parse(self) -> tuple[QueryDict, MultiValueDict[Any, Any]]: ...
    def handle_file_complete(
        self, old_field_name: str, counters: list[int]
    ) -> None: ...
    def IE_sanitize(self, filename: str) -> str: ...

class LazyStream:
    length: None = ...
    position: int = ...
    def __init__(
        self, producer: BoundaryIter | ChunkIter, length: None = ...
    ) -> None: ...
    def tell(self) -> Any: ...
    def read(self, size: int | None = ...) -> bytes: ...
    def __next__(self) -> bytes: ...
    def close(self) -> None: ...
    def __iter__(self) -> LazyStream: ...
    def unget(self, bytes: bytes) -> None: ...

class ChunkIter:
    flo: BytesIO = ...
    chunk_size: int = ...
    def __init__(self, flo: BytesIO, chunk_size: int = ...) -> None: ...
    def __next__(self) -> bytes: ...
    def __iter__(self) -> Any: ...

class InterBoundaryIter:
    def __init__(self, stream: LazyStream, boundary: bytes) -> None: ...
    def __iter__(self) -> InterBoundaryIter: ...
    def __next__(self) -> LazyStream: ...

class BoundaryIter:
    def __init__(self, stream: LazyStream, boundary: bytes) -> None: ...
    def __iter__(self) -> Any: ...
    def __next__(self) -> bytes: ...

class Parser:
    def __init__(self, stream: LazyStream, boundary: bytes) -> None: ...
    def __iter__(
        self,
    ) -> Iterator[
        tuple[str, dict[str, tuple[str, dict[str, bytes | str]]], LazyStream]
    ]: ...

def parse_header(line: bytes) -> tuple[str, dict[str, Any]]: ...
