Add stubs for WebOb (#9874)

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
This commit is contained in:
David Salvisberg
2023-06-18 16:32:49 +02:00
committed by GitHub
parent 7544b60db7
commit df795220a3
20 changed files with 1854 additions and 0 deletions

View File

@@ -0,0 +1,153 @@
# Error: is not present in stub
# =============================
# These are plain strings, regex strings or compiled regex patterns
# which are used internally for parsing, so they should not be public API
webob.acceptparse.Accept.accept_compiled_re
webob.acceptparse.Accept.accept_ext_compiled_re
webob.acceptparse.Accept.accept_ext_re
webob.acceptparse.Accept.accept_params_re
webob.acceptparse.Accept.media_range_n_accept_params_compiled_re
webob.acceptparse.Accept.media_range_n_accept_params_re
webob.acceptparse.Accept.media_range_re
webob.acceptparse.Accept.media_type_compiled_re
webob.acceptparse.Accept.media_type_re
webob.acceptparse.Accept.obs_text_re
webob.acceptparse.Accept.parameter_re
webob.acceptparse.Accept.parameters_compiled_re
webob.acceptparse.Accept.qdtext_re
webob.acceptparse.Accept.quoted_pair_re
webob.acceptparse.Accept.quoted_string_re
webob.acceptparse.Accept.subtype_re
webob.acceptparse.Accept.type_re
webob.acceptparse.Accept.vchar_re
webob.acceptparse.AcceptCharset.accept_charset_compiled_re
webob.acceptparse.AcceptCharset.charset_n_weight_compiled_re
webob.acceptparse.AcceptCharset.charset_n_weight_re
webob.acceptparse.AcceptCharset.charset_re
webob.acceptparse.AcceptEncoding.accept_encoding_compiled_re
webob.acceptparse.AcceptEncoding.codings_n_weight_compiled_re
webob.acceptparse.AcceptEncoding.codings_n_weight_re
webob.acceptparse.AcceptEncoding.codings_re
webob.acceptparse.AcceptLanguage.accept_language_compiled_re
webob.acceptparse.AcceptLanguage.lang_range_n_weight_compiled_re
webob.acceptparse.AcceptLanguage.lang_range_n_weight_re
webob.acceptparse.AcceptLanguage.lang_range_re
webob.acceptparse.OWS_re
webob.acceptparse.qvalue_re
webob.acceptparse.tchar_re
webob.acceptparse.token_compiled_re
webob.acceptparse.token_re
webob.acceptparse.weight_re
webob.cachecontrol.need_quote_re
webob.cachecontrol.token_re
webob.client.SendRequest.MULTILINE_RE
webob.descriptors.CHARSET_RE
webob.descriptors.SCHEME_RE
webob.acceptparse.MIMEAccept # Deprecated API
# PY2 compat stuff that has already been removed upstream
webob.compat
webob.multidict.MultiDict.iteritems
webob.multidict.MultiDict.iterkeys
webob.multidict.MultiDict.itervalues
webob.multidict.NestedMultiDict.iteritems
webob.multidict.NestedMultiDict.iterkeys
webob.multidict.NestedMultiDict.itervalues
webob.multidict.NoVars.iterkeys
# NoVars implements the MultiDict interface for better runtime errors
# but it is annoying for type checking, so the methods that are not
# valid to call on NoVars have been removed. In the future we would
# like to switch to a @type_error() decorator
webob.multidict.NoVars.__getitem__
webob.multidict.NoVars.__setitem__
webob.multidict.NoVars.__delitem__
webob.multidict.NoVars.add
webob.multidict.NoVars.setdefault
webob.multidict.NoVars.update
webob.multidict.NoVars.clear
webob.multidict.NoVars.pop
webob.multidict.NoVars.popitem
webob.multidict.NoVars.getone
# ResponseBodyFile cannot be closed and emits an Exception, so we're better
# off pretending the method doesn't exist
webob.response.ResponseBodyFile.close
# Error: is inconsistent
# ======================
# set_cookie has a deprecated argument `expires` which has been removed upstream
webob.Response.set_cookie
webob.response.Response.set_cookie
# These methods have been moved from their subclasses to the shared hidden superclass
# since the method signatures are the same, so this saves some copy pasta and should
# not affect type checking or runtime behavior in any way
webob.acceptparse._AcceptCharsetInvalidOrNoHeader.__add__
webob.acceptparse._AcceptCharsetInvalidOrNoHeader.__radd__
webob.acceptparse._AcceptCharsetInvalidOrNoHeader.copy
webob.acceptparse._AcceptCharsetInvalidOrNoHeader.parsed
webob.acceptparse._AcceptEncodingInvalidOrNoHeader.__add__
webob.acceptparse._AcceptEncodingInvalidOrNoHeader.__radd__
webob.acceptparse._AcceptEncodingInvalidOrNoHeader.copy
webob.acceptparse._AcceptEncodingInvalidOrNoHeader.parsed
webob.acceptparse._AcceptInvalidOrNoHeader.__add__
webob.acceptparse._AcceptInvalidOrNoHeader.__radd__
webob.acceptparse._AcceptInvalidOrNoHeader.copy
webob.acceptparse._AcceptInvalidOrNoHeader.parsed
webob.acceptparse._AcceptLanguageInvalidOrNoHeader.__add__
webob.acceptparse._AcceptLanguageInvalidOrNoHeader.__radd__
webob.acceptparse._AcceptLanguageInvalidOrNoHeader.copy
webob.acceptparse._AcceptLanguageInvalidOrNoHeader.lookup
webob.acceptparse._AcceptLanguageInvalidOrNoHeader.parsed
# These are here due to the slightly more strict nature of the type annotation
# of these descriptors for type checking, it does not really have any runtime
# consequences since `_IntValueProperty` derives from `value_property` and
# only makes `__set__` slightly more strict.
webob.cachecontrol.CacheControl.max_age
webob.cachecontrol.CacheControl.max_stale
webob.cachecontrol.CacheControl.min_fresh
webob.cachecontrol.CacheControl.s_max_age
webob.cachecontrol.CacheControl.s_maxage
webob.cachecontrol.CacheControl.stale_if_error
webob.cachecontrol.CacheControl.stale_while_revalidate
webob.cachecontrol.CacheControl.update_dict
webob.cachecontrol.UpdateDict.setdefault
# These need to be ignored due to how WebOb decided to let people know
# that certain methods on `NestedMultiDict` should not be called since
# they are immutable, compared to a MultiDict, but still can be used
# interchangeably in some parts of the API. So they re-use generic functions
# that accept any parameters and assign them to methods which should still
# satisfy the same interface. The type annotations enforce the correct
# input arguments instead of the generic ones.
webob.multidict.NestedMultiDict.popitem
webob.multidict.NestedMultiDict.clear
# The `DEFAULT` parameter on these dunder methods don't really make sense as
# part of the public API, so they have been removed from the stubs
webob.request.AdhocAttrMixin.__delattr__
webob.request.AdhocAttrMixin.__getattr__
webob.request.AdhocAttrMixin.__setattr__
# BaseRequest has a bunch of named parameters that have been deprecated and
# removed upstream, since there's a `**kwargs` anyways, it doesn't really
# make sense to annotate them and pretend they're part of the API.
webob.request.BaseRequest.__init__
# Error: is not present at runtime
# =============================
# This attribute is there to help mypy type narrow NoVars based on its static
# falsyness, so it's to make it possible to narrow the type union in request.POST
# without importing MultiDict or NoVars
webob.multidict.NoVars.__bool__
# This attribute is set on the instance instead of the class in the `__init__`
# so the type annotation is technically wrong, however I am unsure about
# whether the ResponseBodyFile would satisfy some of the IO Protocols if
# `write` was defined as a Callable instance attribute. It's hard to come up
# with a use-case where the distinction matters, besides inherting from
# the class and overwriting the __init__ and forgetting to populate `write`.
webob.response.ResponseBodyFile.write

View File

@@ -0,0 +1 @@
version = "1.8.*"

View File

@@ -0,0 +1,13 @@
from webob.datetime_utils import (
UTC as UTC,
day as day,
hour as hour,
minute as minute,
month as month,
second as second,
week as week,
year as year,
)
from webob.request import LegacyRequest as LegacyRequest, Request as Request
from webob.response import Response as Response
from webob.util import html_escape as html_escape

View File

@@ -0,0 +1,503 @@
from _typeshed import SupportsItems
from collections.abc import Callable, Iterable, Iterator
from typing import Any, NamedTuple, TypeVar, overload
from typing_extensions import Literal, Self, TypeAlias
_T = TypeVar("_T")
_ListOrTuple: TypeAlias = list[_T] | tuple[_T, ...]
_ParsedAccept: TypeAlias = tuple[str, float, list[tuple[str, str]], list[str | tuple[str, str]]]
class AcceptOffer(NamedTuple):
type: str
subtype: str
params: tuple[tuple[str, str], ...]
class Accept:
@classmethod
def parse(cls, value: str) -> Iterator[_ParsedAccept]: ...
@classmethod
def parse_offer(cls, offer: str | AcceptOffer) -> AcceptOffer: ...
class AcceptValidHeader(Accept):
@property
def header_value(self) -> str: ...
@property
def parsed(self) -> list[_ParsedAccept] | None: ...
def __init__(self, header_value: str) -> None: ...
def copy(self) -> Self: ...
@overload
def __add__(self, other: str | None) -> Self: ...
@overload
def __add__(self, other: AcceptNoHeader | AcceptValidHeader | AcceptInvalidHeader) -> Self: ...
@overload
def __add__(self, other: SupportsItems[str, float | tuple[float, str]]) -> Self: ...
@overload
def __add__(self, other: _ListOrTuple[str | tuple[str, float, str] | list[Any]]) -> Self: ...
def __bool__(self) -> Literal[True]: ...
def __contains__(self, offer: str) -> bool: ...
def __iter__(self) -> Iterator[str]: ...
@overload
def __radd__(self, other: str | None) -> Self: ...
@overload
def __radd__(self, other: SupportsItems[str, float | tuple[float, str]]) -> Self: ...
@overload
def __radd__(self, other: _ListOrTuple[str | tuple[str, float, str] | list[Any]]) -> Self: ...
def accept_html(self) -> bool: ...
@property
def accepts_html(self) -> bool: ...
def acceptable_offers(self, offers: Iterable[str | AcceptOffer]) -> list[tuple[str, float]]: ...
@overload
def best_match(self, offers: Iterable[str | tuple[str, float] | list[Any]], default_match: None = None) -> str | None: ...
@overload
def best_match(self, offers: Iterable[str | tuple[str, float] | list[Any]], default_match: str) -> str: ...
def quality(self, offer: str) -> float | None: ...
class _AcceptInvalidOrNoHeader(Accept):
@property
def parsed(self) -> None: ...
def copy(self) -> Self: ...
@overload
def __add__(self, other: None) -> AcceptNoHeader: ...
@overload
def __add__(self, other: str) -> AcceptValidHeader | AcceptNoHeader: ...
@overload
def __add__(self, other: AcceptValidHeader) -> AcceptValidHeader: ...
@overload
def __add__(self, other: AcceptNoHeader | AcceptInvalidHeader) -> AcceptNoHeader: ...
@overload
def __add__(self, other: SupportsItems[str, float | tuple[float, str]]) -> AcceptValidHeader | AcceptNoHeader: ...
@overload
def __add__(self, other: _ListOrTuple[str | tuple[str, float, str] | list[Any]]) -> AcceptValidHeader | AcceptNoHeader: ...
@overload
def __radd__(self, other: None) -> AcceptNoHeader: ...
@overload
def __radd__(self, other: str) -> AcceptValidHeader | AcceptNoHeader: ...
@overload
def __radd__(self, other: AcceptValidHeader) -> AcceptValidHeader: ...
@overload
def __radd__(self, other: AcceptNoHeader | AcceptInvalidHeader) -> AcceptNoHeader: ...
@overload
def __radd__(self, other: SupportsItems[str, float | tuple[float, str]]) -> AcceptValidHeader | AcceptNoHeader: ...
@overload
def __radd__(self, other: _ListOrTuple[str | tuple[str, float, str] | list[Any]]) -> AcceptValidHeader | AcceptNoHeader: ...
def __bool__(self) -> Literal[False]: ...
def __contains__(self, offer: str) -> Literal[True]: ...
def __iter__(self) -> Iterator[str]: ...
def accept_html(self) -> bool: ...
@property
def accepts_html(self) -> bool: ...
def acceptable_offers(self, offers: Iterable[str | AcceptOffer]) -> list[tuple[str, float]]: ...
@overload
def best_match(self, offers: Iterable[str | tuple[str, float] | list[Any]], default_match: None = None) -> str | None: ...
@overload
def best_match(self, offers: Iterable[str | tuple[str, float] | list[Any]], default_match: str) -> str: ...
def quality(self, offer: str) -> float: ...
class AcceptNoHeader(_AcceptInvalidOrNoHeader):
@property
def header_value(self) -> None: ...
def __init__(self) -> None: ...
class AcceptInvalidHeader(_AcceptInvalidOrNoHeader):
@property
def header_value(self) -> str: ...
def __init__(self, header_value: str) -> None: ...
@overload
def create_accept_header(header_value: None) -> AcceptNoHeader: ...
@overload
def create_accept_header(header_value: str) -> AcceptValidHeader | AcceptInvalidHeader: ...
class _AcceptProperty:
@overload
def __get__(self, __obj: None, __type: type | None = ...) -> property: ...
@overload
def __get__(self, __obj: Any, __type: type | None = ...) -> AcceptNoHeader | AcceptValidHeader | AcceptInvalidHeader: ...
@overload
def __set__(self, __obj: Any, __value: str | None) -> None: ...
@overload
def __set__(self, __obj: Any, __value: AcceptNoHeader | AcceptValidHeader | AcceptInvalidHeader) -> None: ...
@overload
def __set__(self, __obj: Any, __value: SupportsItems[str, float | tuple[float, str]]) -> None: ...
@overload
def __set__(self, __obj: Any, __value: _ListOrTuple[str | tuple[str, float, str] | list[Any]]) -> None: ...
def __delete__(self, __obj: Any) -> None: ...
def accept_property() -> _AcceptProperty: ...
class AcceptCharset:
@classmethod
def parse(cls, value: str) -> Iterator[tuple[str, float]]: ...
class AcceptCharsetValidHeader(AcceptCharset):
@property
def header_value(self) -> str: ...
@property
def parsed(self) -> list[tuple[str, float]]: ...
def __init__(self, header_value: str) -> None: ...
def copy(self) -> Self: ...
@overload
def __add__(self, other: str | None) -> Self: ...
@overload
def __add__(self, other: AcceptCharsetValidHeader | AcceptCharsetNoHeader | AcceptCharsetInvalidHeader) -> Self: ...
@overload
def __add__(self, other: SupportsItems[str, float]) -> Self: ...
@overload
def __add__(self, other: _ListOrTuple[str | tuple[str, float] | list[Any]]) -> Self: ...
def __bool__(self) -> Literal[True]: ...
def __contains__(self, offer: str) -> bool: ...
def __iter__(self) -> Iterator[str]: ...
@overload
def __radd__(self, other: str | None) -> Self: ...
@overload
def __radd__(self, other: AcceptCharsetValidHeader | AcceptCharsetNoHeader | AcceptCharsetInvalidHeader) -> Self: ...
@overload
def __radd__(self, other: SupportsItems[str, float]) -> Self: ...
@overload
def __radd__(self, other: _ListOrTuple[str | tuple[str, float] | list[Any]]) -> Self: ...
def acceptable_offers(self, offers: Iterable[str]) -> list[tuple[str, float]]: ...
@overload
def best_match(self, offers: Iterable[str], default_match: None = None) -> str | None: ...
@overload
def best_match(self, offers: Iterable[str], default_match: str) -> str: ...
def quality(self, offer: str) -> float | None: ...
class _AcceptCharsetInvalidOrNoHeader(AcceptCharset):
@property
def parsed(self) -> None: ...
def __bool__(self) -> Literal[False]: ...
def __contains__(self, offer: str) -> Literal[True]: ...
def __iter__(self) -> Iterator[str]: ...
@overload
def __add__(self, other: None) -> AcceptCharsetNoHeader: ...
@overload
def __add__(self, other: str) -> AcceptCharsetValidHeader | AcceptCharsetNoHeader: ...
@overload
def __add__(self, other: AcceptCharsetValidHeader) -> AcceptCharsetValidHeader: ...
@overload
def __add__(self, other: AcceptCharsetNoHeader | AcceptCharsetInvalidHeader) -> AcceptCharsetNoHeader: ...
@overload
def __add__(self, other: SupportsItems[str, float]) -> AcceptCharsetValidHeader | AcceptCharsetNoHeader: ...
@overload
def __add__(
self, other: _ListOrTuple[str | tuple[str, float] | list[Any]]
) -> AcceptCharsetValidHeader | AcceptCharsetNoHeader: ...
@overload
def __radd__(self, other: None) -> AcceptCharsetNoHeader: ...
@overload
def __radd__(self, other: str) -> AcceptCharsetValidHeader | AcceptCharsetNoHeader: ...
@overload
def __radd__(self, other: AcceptCharsetValidHeader) -> AcceptCharsetValidHeader: ...
@overload
def __radd__(self, other: AcceptCharsetNoHeader | AcceptCharsetInvalidHeader) -> AcceptCharsetNoHeader: ...
@overload
def __radd__(self, other: SupportsItems[str, float]) -> AcceptCharsetValidHeader | AcceptCharsetNoHeader: ...
@overload
def __radd__(
self, other: _ListOrTuple[str | tuple[str, float] | list[Any]]
) -> AcceptCharsetValidHeader | AcceptCharsetNoHeader: ...
def copy(self) -> Self: ...
def acceptable_offers(self, offers: Iterable[str]) -> list[tuple[str, float]]: ...
@overload
def best_match(self, offers: Iterable[str], default_match: None = None) -> str | None: ...
@overload
def best_match(self, offers: Iterable[str], default_match: str) -> str: ...
def quality(self, offer: str) -> float | None: ...
class AcceptCharsetNoHeader(_AcceptCharsetInvalidOrNoHeader):
@property
def header_value(self) -> None: ...
def __init__(self) -> None: ...
class AcceptCharsetInvalidHeader(_AcceptCharsetInvalidOrNoHeader):
@property
def header_value(self) -> str: ...
def __init__(self, header_value: str) -> None: ...
@overload
def create_accept_charset_header(header_value: None) -> AcceptCharsetNoHeader: ...
@overload
def create_accept_charset_header(header_value: str) -> AcceptCharsetValidHeader | AcceptCharsetInvalidHeader: ...
class _AcceptCharsetProperty:
@overload
def __get__(self, __obj: None, __type: type | None = ...) -> property: ...
@overload
def __get__(
self, __obj: Any, __type: type | None = ...
) -> AcceptCharsetNoHeader | AcceptCharsetValidHeader | AcceptCharsetInvalidHeader: ...
@overload
def __set__(self, __obj: Any, __value: str | None) -> None: ...
@overload
def __set__(
self, __obj: Any, __value: AcceptCharsetNoHeader | AcceptCharsetValidHeader | AcceptCharsetInvalidHeader
) -> None: ...
@overload
def __set__(self, __obj: Any, __value: SupportsItems[str, float]) -> None: ...
@overload
def __set__(self, __obj: Any, __value: _ListOrTuple[str | tuple[str, float] | list[Any]]) -> None: ...
def __delete__(self, __obj: Any) -> None: ...
def accept_charset_property() -> _AcceptCharsetProperty: ...
class AcceptEncoding:
@classmethod
def parse(cls, value: str) -> Iterator[tuple[str, float]]: ...
class AcceptEncodingValidHeader(AcceptEncoding):
@property
def header_value(self) -> str: ...
@property
def parsed(self) -> list[tuple[str, float]]: ...
def __init__(self, header_value: str) -> None: ...
def copy(self) -> Self: ...
@overload
def __add__(self, other: str | None) -> Self: ...
@overload
def __add__(self, other: AcceptEncodingValidHeader | AcceptEncodingNoHeader | AcceptEncodingInvalidHeader) -> Self: ...
@overload
def __add__(self, other: SupportsItems[str, float]) -> Self: ...
@overload
def __add__(self, other: _ListOrTuple[str | tuple[str, float] | list[Any]]) -> Self: ...
def __bool__(self) -> Literal[True]: ...
def __contains__(self, offer: str) -> bool: ...
def __iter__(self) -> Iterator[str]: ...
@overload
def __radd__(self, other: str | None) -> Self: ...
@overload
def __radd__(self, other: AcceptEncodingValidHeader | AcceptEncodingNoHeader | AcceptEncodingInvalidHeader) -> Self: ...
@overload
def __radd__(self, other: SupportsItems[str, float]) -> Self: ...
@overload
def __radd__(self, other: _ListOrTuple[str | tuple[str, float] | list[Any]]) -> Self: ...
def acceptable_offers(self, offers: Iterable[str]) -> list[tuple[str, float]]: ...
@overload
def best_match(self, offers: Iterable[str], default_match: None = None) -> str | None: ...
@overload
def best_match(self, offers: Iterable[str], default_match: str) -> str: ...
def quality(self, offer: str) -> float | None: ...
class _AcceptEncodingInvalidOrNoHeader(AcceptEncoding):
@property
def parsed(self) -> None: ...
def __bool__(self) -> Literal[False]: ...
def __contains__(self, offer: str) -> Literal[True]: ...
def __iter__(self) -> Iterator[str]: ...
@overload
def __add__(self, other: None) -> AcceptEncodingNoHeader: ...
@overload
def __add__(self, other: str) -> AcceptEncodingValidHeader | AcceptEncodingNoHeader: ...
@overload
def __add__(self, other: AcceptEncodingValidHeader) -> AcceptEncodingValidHeader: ...
@overload
def __add__(self, other: AcceptEncodingNoHeader | AcceptEncodingInvalidHeader) -> AcceptEncodingNoHeader: ...
@overload
def __add__(self, other: SupportsItems[str, float]) -> AcceptEncodingValidHeader | AcceptEncodingNoHeader: ...
@overload
def __add__(
self, other: _ListOrTuple[str | tuple[str, float] | list[Any]]
) -> AcceptEncodingValidHeader | AcceptEncodingNoHeader: ...
@overload
def __radd__(self, other: None) -> AcceptEncodingNoHeader: ...
@overload
def __radd__(self, other: str) -> AcceptEncodingValidHeader | AcceptEncodingNoHeader: ...
@overload
def __radd__(self, other: AcceptEncodingValidHeader) -> AcceptEncodingValidHeader: ...
@overload
def __radd__(self, other: AcceptEncodingNoHeader | AcceptEncodingInvalidHeader) -> AcceptEncodingNoHeader: ...
@overload
def __radd__(self, other: SupportsItems[str, float]) -> AcceptEncodingValidHeader | AcceptEncodingNoHeader: ...
@overload
def __radd__(
self, other: _ListOrTuple[str | tuple[str, float] | list[Any]]
) -> AcceptEncodingValidHeader | AcceptEncodingNoHeader: ...
def copy(self) -> Self: ...
def acceptable_offers(self, offers: Iterable[str]) -> list[tuple[str, float]]: ...
@overload
def best_match(self, offers: Iterable[str], default_match: None = None) -> str | None: ...
@overload
def best_match(self, offers: Iterable[str], default_match: str) -> str: ...
def quality(self, offer: str) -> float | None: ...
class AcceptEncodingNoHeader(_AcceptEncodingInvalidOrNoHeader):
@property
def header_value(self) -> None: ...
def __init__(self) -> None: ...
class AcceptEncodingInvalidHeader(_AcceptEncodingInvalidOrNoHeader):
@property
def header_value(self) -> str: ...
def __init__(self, header_value: str) -> None: ...
@overload
def create_accept_encoding_header(header_value: None) -> AcceptEncodingNoHeader: ...
@overload
def create_accept_encoding_header(header_value: str) -> AcceptEncodingValidHeader | AcceptEncodingInvalidHeader: ...
class _AcceptEncodingProperty:
@overload
def __get__(self, __obj: None, __type: type | None = ...) -> property: ...
@overload
def __get__(
self, __obj: Any, __type: type | None = ...
) -> AcceptEncodingNoHeader | AcceptEncodingValidHeader | AcceptEncodingInvalidHeader: ...
@overload
def __set__(self, __obj: Any, __value: str | None) -> None: ...
@overload
def __set__(
self, __obj: Any, __value: AcceptEncodingNoHeader | AcceptEncodingValidHeader | AcceptEncodingInvalidHeader
) -> None: ...
@overload
def __set__(self, __obj: Any, __value: SupportsItems[str, float]) -> None: ...
@overload
def __set__(self, __obj: Any, __value: _ListOrTuple[str | tuple[str, float] | list[Any]]) -> None: ...
def __delete__(self, __obj: Any) -> None: ...
def accept_encoding_property() -> _AcceptEncodingProperty: ...
class AcceptLanguage:
@classmethod
def parse(cls, value: str) -> Iterator[tuple[str, float]]: ...
class AcceptLanguageValidHeader(AcceptLanguage):
@property
def header_value(self) -> str: ...
@property
def parsed(self) -> list[tuple[str, float]]: ...
def __init__(self, header_value: str) -> None: ...
def copy(self) -> Self: ...
@overload
def __add__(self, other: str | None) -> Self: ...
@overload
def __add__(self, other: AcceptLanguageValidHeader | AcceptLanguageNoHeader | AcceptLanguageInvalidHeader) -> Self: ...
@overload
def __add__(self, other: SupportsItems[str, float]) -> Self: ...
@overload
def __add__(self, other: _ListOrTuple[str | tuple[str, float] | list[Any]]) -> Self: ...
def __bool__(self) -> Literal[True]: ...
def __contains__(self, offer: str) -> bool: ...
def __iter__(self) -> Iterator[str]: ...
@overload
def __radd__(self, other: str | None) -> Self: ...
@overload
def __radd__(self, other: AcceptLanguageValidHeader | AcceptLanguageNoHeader | AcceptLanguageInvalidHeader) -> Self: ...
@overload
def __radd__(self, other: SupportsItems[str, float]) -> Self: ...
@overload
def __radd__(self, other: _ListOrTuple[str | tuple[str, float] | list[Any]]) -> Self: ...
def basic_filtering(self, language_tags: Iterable[str]) -> list[tuple[str, float]]: ...
@overload
def best_match(self, offers: Iterable[str], default_match: None = None) -> str | None: ...
@overload
def best_match(self, offers: Iterable[str], default_match: str) -> str: ...
@overload
def lookup(
self,
language_tags: Iterable[str],
default_range: str | None = None,
default_tag: str = ...,
default: str | Callable[[], str | None] | None = None,
) -> str | None: ...
@overload
def lookup(
self,
language_tags: Iterable[str],
default_range: str | None = None,
default_tag: str | None = None,
default: str | Callable[[], str | None] = ...,
) -> str | None: ...
def quality(self, offer: str) -> float | None: ...
class _AcceptLanguageInvalidOrNoHeader(AcceptLanguage):
@property
def parsed(self) -> None: ...
def __bool__(self) -> Literal[False]: ...
def __contains__(self, offer: str) -> Literal[True]: ...
def __iter__(self) -> Iterator[str]: ...
@overload
def __add__(self, other: None) -> AcceptLanguageNoHeader: ...
@overload
def __add__(self, other: str) -> AcceptLanguageValidHeader | AcceptLanguageNoHeader: ...
@overload
def __add__(self, other: AcceptLanguageValidHeader) -> AcceptLanguageValidHeader: ...
@overload
def __add__(self, other: AcceptLanguageNoHeader | AcceptLanguageInvalidHeader) -> AcceptLanguageNoHeader: ...
@overload
def __add__(self, other: SupportsItems[str, float]) -> AcceptLanguageValidHeader | AcceptLanguageNoHeader: ...
@overload
def __add__(
self, other: _ListOrTuple[str | tuple[str, float] | list[Any]]
) -> AcceptLanguageValidHeader | AcceptLanguageNoHeader: ...
@overload
def __radd__(self, other: None) -> AcceptLanguageNoHeader: ...
@overload
def __radd__(self, other: str) -> AcceptLanguageValidHeader | AcceptLanguageNoHeader: ...
@overload
def __radd__(self, other: AcceptLanguageValidHeader) -> AcceptLanguageValidHeader: ...
@overload
def __radd__(self, other: AcceptLanguageNoHeader | AcceptLanguageInvalidHeader) -> AcceptLanguageNoHeader: ...
@overload
def __radd__(self, other: SupportsItems[str, float]) -> AcceptLanguageValidHeader | AcceptLanguageNoHeader: ...
@overload
def __radd__(
self, other: _ListOrTuple[str | tuple[str, float] | list[Any]]
) -> AcceptLanguageValidHeader | AcceptLanguageNoHeader: ...
def copy(self) -> Self: ...
def basic_filtering(self, language_tags: Iterable[str]) -> list[tuple[str, float]]: ...
@overload
def best_match(self, offers: Iterable[str], default_match: None = None) -> str | None: ...
@overload
def best_match(self, offers: Iterable[str], default_match: str) -> str: ...
@overload
def lookup(
self,
language_tags: Iterable[str],
default_range: str | None = None,
default_tag: str = ...,
default: str | Callable[[], str | None] | None = None,
) -> str | None: ...
@overload
def lookup(
self,
language_tags: Iterable[str],
default_range: str | None = None,
default_tag: str | None = None,
default: str | Callable[[], str | None] = ...,
) -> str | None: ...
def quality(self, offer: str) -> float | None: ...
class AcceptLanguageNoHeader(_AcceptLanguageInvalidOrNoHeader):
def __init__(self) -> None: ...
@property
def header_value(self) -> None: ...
class AcceptLanguageInvalidHeader(_AcceptLanguageInvalidOrNoHeader):
def __init__(self, header_value: str) -> None: ...
@property
def header_value(self) -> str: ...
@overload
def create_accept_language_header(header_value: None) -> AcceptLanguageNoHeader: ...
@overload
def create_accept_language_header(header_value: str) -> AcceptLanguageValidHeader | AcceptLanguageInvalidHeader: ...
class _AcceptLanguageProperty:
@overload
def __get__(self, __obj: None, __type: type | None = ...) -> property: ...
@overload
def __get__(
self, __obj: Any, __type: type | None = ...
) -> AcceptLanguageNoHeader | AcceptLanguageValidHeader | AcceptLanguageInvalidHeader: ...
@overload
def __set__(self, __obj: Any, __value: str | None) -> None: ...
@overload
def __set__(
self, __obj: Any, __value: AcceptLanguageNoHeader | AcceptLanguageValidHeader | AcceptLanguageInvalidHeader
) -> None: ...
@overload
def __set__(self, __obj: Any, __value: SupportsItems[str, float]) -> None: ...
@overload
def __set__(self, __obj: Any, __value: _ListOrTuple[str | tuple[str, float] | list[Any]]) -> None: ...
def __delete__(self, __obj: Any) -> None: ...
def accept_language_property() -> _AcceptLanguageProperty: ...

View File

@@ -0,0 +1,28 @@
from collections.abc import Iterator
from typing import overload
from typing_extensions import Self
class Range:
start: int | None
end: int | None
@overload
def __init__(self, start: None, end: None): ...
@overload
def __init__(self, start: int, end: int | None): ...
def range_for_length(self, length: int | None) -> tuple[int, int] | None: ...
def content_range(self, length: int | None) -> ContentRange | None: ...
def __iter__(self) -> Iterator[int | None]: ...
@classmethod
def parse(cls, header: str | None) -> Self: ...
class ContentRange:
start: int | None
stop: int | None
length: int | None
@overload
def __init__(self, start: None, stop: None, length: int | None): ...
@overload
def __init__(self, start: int, stop: int, length: int | None): ...
def __iter__(self) -> Iterator[int | None]: ...
@classmethod
def parse(cls, value: str | None) -> Self: ...

View File

@@ -0,0 +1,96 @@
from collections.abc import Callable, MutableMapping
from typing import Any, Generic, TypeVar, overload
from typing_extensions import Literal, Self, TypeAlias
from webob.request import Request
from webob.response import Response
_T = TypeVar("_T")
_KT = TypeVar("_KT")
_VT = TypeVar("_VT")
_NoneLiteral = TypeVar("_NoneLiteral")
_Type: TypeAlias = type
class UpdateDict(dict[_KT, _VT]):
updated: Callable[..., Any] | None
updated_args: tuple[Any, ...] | None
class exists_property:
prop: str
type: str | None
def __init__(self, prop: str, type: str | None = None): ...
@overload
def __get__(self, obj: None, type: _Type | None = None) -> Self: ...
@overload
def __get__(self, obj: Any, type: _Type | None = None) -> bool: ...
def __set__(self, obj: Any, value: bool) -> None: ...
def __delete__(self, obj: Any) -> None: ...
class value_property(Generic[_T, _NoneLiteral]):
prop: str
default: _T | None
none: _NoneLiteral
type: str | None
@overload
def __init__(self, prop: str, default: None = None, none: None = None, type: str | None = None): ...
@overload
def __init__(self, prop: str, default: _T, none: _NoneLiteral, type: str | None = None): ...
@overload
def __get__(self, obj: None, type: _Type | None = None) -> Self: ...
@overload
def __get__(self, obj: Any, type: _Type | None = None) -> _T | _NoneLiteral | None: ...
def __set__(self, obj: Any, value: _T | Literal[True]) -> None: ...
def __delete__(self, obj: Any) -> None: ...
class _IntValueProperty(value_property[int, _NoneLiteral]):
def __set__(self, obj: Any, value: int) -> None: ...
class _BaseCacheControl:
update_dict = UpdateDict
properties: MutableMapping[str, Any]
type: Literal["request", "response"] | None
@classmethod
@overload
def parse(cls, header: str, updates_to: None = None, type: None = None) -> _AnyCacheControl: ...
@classmethod
@overload
def parse(cls, header: str, updates_to: Request, type: Literal["request"]) -> _RequestCacheControl: ...
@classmethod
@overload
def parse(cls, header: str, updates_to: Response, type: Literal["response"]) -> _ResponseCacheControl: ...
no_cache: value_property[str, Literal["*"]]
no_store: exists_property
no_transform: exists_property
max_age: _IntValueProperty[Literal[-1]]
def copy(self) -> Self: ...
class _RequestCacheControl(_BaseCacheControl):
type: Literal["request"]
max_stale: _IntValueProperty[Literal["*"]]
min_fresh: _IntValueProperty[None]
only_if_cached: exists_property
class _ResponseCacheControl(_BaseCacheControl):
type: Literal["response"]
public: exists_property
private: value_property[str, Literal["*"]]
must_revalidate: exists_property
proxy_revalidate: exists_property
s_maxage: _IntValueProperty[None]
s_max_age: _IntValueProperty[None]
stale_while_revalidate: _IntValueProperty[None]
stale_if_error: _IntValueProperty[None]
class _AnyCacheControl(_RequestCacheControl, _ResponseCacheControl):
type: None # type:ignore[assignment]
class CacheControl(_AnyCacheControl):
@overload
def __init__(self: _AnyCacheControl, properties: MutableMapping[str, Any], type: None) -> None: ...
@overload
def __init__(self: _RequestCacheControl, properties: MutableMapping[str, Any], type: Literal["request"]) -> None: ...
@overload
def __init__(self: _ResponseCacheControl, properties: MutableMapping[str, Any], type: Literal["response"]) -> None: ...
def serialize_cache_control(properties: MutableMapping[str, Any] | _BaseCacheControl) -> str: ...

View File

@@ -0,0 +1,12 @@
from _typeshed.wsgi import StartResponse, WSGIEnvironment
from collections.abc import Iterable
from http.client import HTTPMessage
from typing import ClassVar
class SendRequest:
def __init__(self, HTTPConnection=..., HTTPSConnection=...) -> None: ...
def __call__(self, environ: WSGIEnvironment, start_response: StartResponse) -> Iterable[bytes]: ...
filtered_headers: ClassVar[tuple[str, ...]]
def parse_headers(self, message: HTTPMessage) -> list[tuple[str, str]]: ...
send_request_app: SendRequest

View File

@@ -0,0 +1,148 @@
from _typeshed import Incomplete
from _typeshed.wsgi import WSGIEnvironment
from collections.abc import ItemsView, Iterator, KeysView, MutableMapping, ValuesView
from datetime import date, datetime, timedelta
from typing import TypeVar, overload
from typing_extensions import Literal
from webob.descriptors import _AsymmetricProperty
_T = TypeVar("_T")
class RequestCookies(MutableMapping[str, str]):
def __init__(self, environ: WSGIEnvironment) -> None: ...
def __setitem__(self, name: str, value: str) -> None: ...
def __getitem__(self, name: str) -> str: ...
@overload
def get(self, name: str, default: None = None) -> str | None: ...
@overload
def get(self, name: str, default: str | _T) -> str | _T: ...
def __delitem__(self, name: str) -> None: ...
def keys(self) -> KeysView[str]: ...
def values(self) -> ValuesView[str]: ...
def items(self) -> ItemsView[str, str]: ...
def __contains__(self, name: object) -> bool: ...
def __iter__(self) -> Iterator[str]: ...
def __len__(self) -> int: ...
def clear(self) -> None: ...
class Cookie(dict[str, Morsel]):
def __init__(self, input: str | None = None) -> None: ...
def load(self, data: str) -> None: ...
def add(self, key: str | bytes, val: str | bytes) -> Morsel: ...
def __setitem__(self, key: str | bytes, val: str | bytes) -> Morsel: ... # type:ignore[override]
def serialize(self, full: bool = True) -> str: ...
def values(self) -> list[Morsel]: ... # type:ignore[override]
def __str__(self, full: bool = True) -> str: ...
class Morsel(dict[bytes, bytes | bool | None]):
name: bytes
value: bytes
def __init__(self, name: str | bytes, value: str | bytes) -> None: ...
@property
def path(self) -> bytes | None: ...
@path.setter
def path(self, v: bytes | None) -> None: ...
@property
def domain(self) -> bytes | None: ...
@domain.setter
def domain(self, v: bytes | None) -> None: ...
@property
def comment(self) -> bytes | None: ...
@comment.setter
def comment(self, v: bytes | None) -> None: ...
expires: _AsymmetricProperty[bytes | None, datetime | date | timedelta | int | str | bytes | None]
max_age: _AsymmetricProperty[bytes | None, timedelta | int | str | bytes]
@property
def httponly(self) -> bool | None: ...
@httponly.setter
def httponly(self, v: bool) -> None: ...
@property
def secure(self) -> bool | None: ...
@secure.setter
def secure(self, v: bool) -> None: ...
samesite: _AsymmetricProperty[bytes | None, Literal["strict", "lax", "none"] | None]
def serialize(self, full: bool = True) -> str: ...
def __str__(self, full: bool = True) -> str: ...
def make_cookie(
name: str | bytes,
value: str | bytes | None,
max_age: int | timedelta | None = None,
path: str = "/",
domain: str | None = None,
secure: bool = False,
httponly: bool = False,
comment: str | None = None,
samesite: Literal["strict", "lax", "none"] | None = None,
) -> str: ...
class JSONSerializer:
def dumps(self, appstruct): ...
def loads(self, bstruct): ...
class Base64Serializer:
serializer: Incomplete
def __init__(self, serializer: Incomplete | None = None) -> None: ...
def dumps(self, appstruct): ...
def loads(self, bstruct): ...
class SignedSerializer:
salt: Incomplete
secret: Incomplete
hashalg: Incomplete
salted_secret: Incomplete
digestmod: Incomplete
digest_size: Incomplete
serializer: Incomplete
def __init__(self, secret, salt, hashalg: str = "sha512", serializer: Incomplete | None = None) -> None: ...
def dumps(self, appstruct): ...
def loads(self, bstruct): ...
class CookieProfile:
cookie_name: Incomplete
secure: Incomplete
max_age: Incomplete
httponly: Incomplete
samesite: Incomplete
path: Incomplete
domains: Incomplete
serializer: Incomplete
request: Incomplete
def __init__(
self,
cookie_name,
secure: bool = False,
max_age: Incomplete | None = None,
httponly: Incomplete | None = None,
samesite: Incomplete | None = None,
path: str = "/",
domains: Incomplete | None = None,
serializer: Incomplete | None = None,
) -> None: ...
def __call__(self, request): ...
def bind(self, request): ...
def get_value(self): ...
def set_cookies(self, response, value, domains=..., max_age=..., path=..., secure=..., httponly=..., samesite=...): ...
def get_headers(self, value, domains=..., max_age=..., path=..., secure=..., httponly=..., samesite=...): ...
class SignedCookieProfile(CookieProfile):
secret: Incomplete
salt: Incomplete
hashalg: Incomplete
original_serializer: Incomplete
def __init__(
self,
secret,
salt,
cookie_name,
secure: bool = False,
max_age: Incomplete | None = None,
httponly: bool = False,
samesite: Incomplete | None = None,
path: str = "/",
domains: Incomplete | None = None,
hashalg: str = "sha512",
serializer: Incomplete | None = None,
) -> None: ...
def bind(self, request): ...

View File

@@ -0,0 +1,23 @@
from datetime import datetime, timedelta, tzinfo
class _UTC(tzinfo):
def dst(self, dt: datetime | None) -> timedelta: ...
def utcoffset(self, dt: datetime | None) -> timedelta: ...
def tzname(self, dt: datetime | None) -> str: ...
UTC: _UTC
def timedelta_to_seconds(td: timedelta) -> int: ...
day: timedelta
week: timedelta
hour: timedelta
minute: timedelta
second: timedelta
month: timedelta
year: timedelta
def parse_date(value: str | bytes) -> datetime | None: ...
def serialize_date(dt) -> str: ...
def parse_date_delta(value: str | bytes) -> datetime | None: ...
def serialize_date_delta(value) -> str: ...

49
stubs/WebOb/webob/dec.pyi Normal file
View File

@@ -0,0 +1,49 @@
from _typeshed import Incomplete
from _typeshed.wsgi import WSGIApplication
from typing import ClassVar, overload
from typing_extensions import Self
from webob.request import Request
class wsgify:
RequestClass: ClassVar[type[Request]]
func: Incomplete
args: Incomplete
kwargs: Incomplete
middleware_wraps: Incomplete
def __init__(
self,
func: Incomplete | None = None,
RequestClass: Incomplete | None = None,
args=...,
kwargs: Incomplete | None = None,
middleware_wraps: Incomplete | None = None,
) -> None: ...
@overload
def __get__(self, obj: None, type: type | None = None) -> Self: ...
@overload
def __get__(self, obj: object, type: type | None = None) -> WSGIApplication: ...
def __call__(self, req, *args, **kw): ...
def get(self, url, **kw): ...
def post(self, url, POST: Incomplete | None = None, **kw): ...
def request(self, url, **kw): ...
def call_func(self, req, *args, **kwargs): ...
def clone(self, func: Incomplete | None = None, **kw): ...
@property
def undecorated(self): ...
@classmethod
def middleware(cls, middle_func: Incomplete | None = None, app: Incomplete | None = None, **kw): ...
class _UnboundMiddleware:
wrapper_class: Incomplete
app: Incomplete
kw: Incomplete
def __init__(self, wrapper_class, app, kw) -> None: ...
def __call__(self, func, app: Incomplete | None = None): ...
class _MiddlewareFactory:
wrapper_class: Incomplete
middleware: Incomplete
kw: Incomplete
def __init__(self, wrapper_class, middleware, kw) -> None: ...
def __call__(self, app: Incomplete | None = None, **config): ...

View File

@@ -0,0 +1,58 @@
from _typeshed import Incomplete
from collections.abc import Iterable
from datetime import date, datetime, timedelta
from time import _TimeTuple, struct_time
from typing import Any, Generic, NamedTuple, TypeVar, overload
_GetterReturnType = TypeVar("_GetterReturnType")
_SetterValueType = TypeVar("_SetterValueType")
class _AsymmetricProperty(Generic[_GetterReturnType, _SetterValueType]):
@overload
def __get__(self, __obj: None, __type: type | None = ...) -> property: ...
@overload
def __get__(self, __obj: Any, __type: type | None = ...) -> _GetterReturnType: ...
def __set__(self, __obj: Any, __value: _SetterValueType) -> None: ...
class _AsymmetricPropertyWithDelete(_AsymmetricProperty[_GetterReturnType, _SetterValueType]):
def __delete__(self, __obj: Any) -> None: ...
class _StringProperty(_AsymmetricPropertyWithDelete[str | None, str | None]): ...
class _ListProperty(_AsymmetricPropertyWithDelete[tuple[str, ...] | None, Iterable[str] | str | None]): ...
class _DateProperty(
_AsymmetricPropertyWithDelete[datetime | None, date | datetime | timedelta | _TimeTuple | struct_time | float | str | None]
): ...
def environ_getter(key, default=..., rfc_section: Incomplete | None = None): ...
def environ_decoder(key, default=..., rfc_section: Incomplete | None = None, encattr: Incomplete | None = None): ...
def upath_property(key): ...
def deprecated_property(attr, name, text, version): ...
def header_getter(header: str, rfc_section: str) -> _StringProperty: ...
def converter(prop, parse, serialize, convert_name: Incomplete | None = None): ...
def list_header(header: str, rfc_section: str) -> _ListProperty: ...
def parse_list(value): ...
def serialize_list(value): ...
def converter_date(prop): ...
def date_header(header: str, rfc_section: str) -> _DateProperty: ...
def parse_etag_response(value, strong: bool = False): ...
def serialize_etag_response(value): ...
def serialize_if_range(value): ...
def parse_range(value): ...
def serialize_range(value): ...
def parse_int(value): ...
def parse_int_safe(value): ...
serialize_int = str
def parse_content_range(value): ...
def serialize_content_range(value): ...
def parse_auth_params(params): ...
known_auth_schemes: dict[str, None]
class _authorization(NamedTuple):
authtype: str
params: dict[str, str] | str
def parse_auth(val): ...
def serialize_auth(val): ...

View File

@@ -0,0 +1,53 @@
from collections.abc import Collection
from datetime import datetime
from typing import Any, overload
from typing_extensions import TypeAlias
from webob.response import Response
_ETag: TypeAlias = _AnyETag | _NoETag | ETagMatcher
class _ETagProperty:
@overload
def __get__(self, __obj: None, __type: type | None = ...) -> property: ...
@overload
def __get__(self, __obj: Any, __type: type | None = ...) -> _ETag: ...
@overload
def __set__(self, __obj: Any, __value: str | None) -> None: ...
@overload
def __set__(self, __obj: Any, __value: _ETag) -> None: ...
def __delete__(self, __obj: Any) -> None: ...
def etag_property(key: str, default: _ETag, rfc_section: str, strong: bool = True) -> _ETagProperty: ...
class _AnyETag:
def __bool__(self) -> bool: ...
def __contains__(self, other: str) -> bool: ...
AnyETag: _AnyETag
class _NoETag:
def __bool__(self) -> bool: ...
def __contains__(self, other: str) -> bool: ...
NoETag: _NoETag
class ETagMatcher:
etags: Collection[str]
def __init__(self, etags: Collection[str]) -> None: ...
def __contains__(self, other: str) -> bool: ...
@classmethod
def parse(cls, value: str, strong: bool = True) -> ETagMatcher | _AnyETag: ...
class IfRange:
etag: _ETag
def __init__(self, etag: _ETag) -> None: ...
@classmethod
def parse(cls, value: str) -> IfRange | IfRangeDate: ...
def __contains__(self, resp: Response) -> bool: ...
def __bool__(self) -> bool: ...
class IfRangeDate:
date: datetime
def __init__(self, date: datetime) -> None: ...
def __contains__(self, resp: Response) -> bool: ...

126
stubs/WebOb/webob/exc.pyi Normal file
View File

@@ -0,0 +1,126 @@
from _typeshed import SupportsItems, SupportsKeysAndGetItem
from _typeshed.wsgi import StartResponse, WSGIApplication, WSGIEnvironment
from collections.abc import Iterable
from string import Template
from typing import Any, Protocol
from typing_extensions import Literal, Self
from webob.response import Response
class _JSONFormatter(Protocol):
def __call__(self, body: str, status: str, title: str, environ: WSGIEnvironment) -> str: ...
class HTTPException(Exception):
wsgi_response: Response
def __init__(self, message: str, wsgi_response: Response) -> None: ...
def __call__(self, environ: WSGIEnvironment, start_response: StartResponse) -> Iterable[bytes]: ...
class WSGIHTTPException(Response, HTTPException):
code: int
title: str
explanation: str
body_template_obj: Template
plain_template_obj: Template
html_template_obj: Template
empty_body: bool
detail: str | None
comment: str | None
def __init__(
self,
detail: str | None = None,
headers: SupportsItems[str, str] | SupportsKeysAndGetItem[str, str] | Iterable[tuple[str, str]] | None = None,
comment: str | None = None,
body_template: str | None = None,
json_formatter: _JSONFormatter | None = None,
**kw: Any,
) -> None: ...
def plain_body(self, environ: WSGIEnvironment) -> str: ...
def html_body(self, environ: WSGIEnvironment) -> str: ...
def json_formatter(self, body: str, status: str, title: str, environ: WSGIEnvironment) -> str: ...
def json_body(self, environ: WSGIEnvironment) -> str: ...
def generate_response(self, environ: WSGIEnvironment, start_response: StartResponse) -> Iterable[bytes]: ...
@property
def wsgi_response(self) -> Self: ... # type:ignore[override]
def __str__(self) -> str: ... # type:ignore[override] # noqaY029
class HTTPError(WSGIHTTPException): ...
class HTTPRedirection(WSGIHTTPException): ...
class HTTPOk(WSGIHTTPException): ...
class HTTPCreated(HTTPOk): ...
class HTTPAccepted(HTTPOk): ...
class HTTPNonAuthoritativeInformation(HTTPOk): ...
class HTTPNoContent(HTTPOk):
empty_body: Literal[True]
class HTTPResetContent(HTTPOk):
empty_body: Literal[True]
class HTTPPartialContent(HTTPOk): ...
class _HTTPMove(HTTPRedirection):
explanation: str
add_slash: bool
def __init__(
self,
detail: str | None = None,
headers: str | None = None,
comment: str | None = None,
body_template: str | None = None,
location: str | None = None,
add_slash: bool = False,
) -> None: ...
class HTTPMultipleChoices(_HTTPMove): ...
class HTTPMovedPermanently(_HTTPMove): ...
class HTTPFound(_HTTPMove): ...
class HTTPSeeOther(_HTTPMove): ...
class HTTPNotModified(HTTPRedirection):
empty_body: Literal[True]
class HTTPUseProxy(_HTTPMove): ...
class HTTPTemporaryRedirect(_HTTPMove): ...
class HTTPPermanentRedirect(_HTTPMove): ...
class HTTPClientError(HTTPError): ...
class HTTPBadRequest(HTTPClientError): ...
class HTTPUnauthorized(HTTPClientError): ...
class HTTPPaymentRequired(HTTPClientError): ...
class HTTPForbidden(HTTPClientError): ...
class HTTPNotFound(HTTPClientError): ...
class HTTPMethodNotAllowed(HTTPClientError): ...
class HTTPNotAcceptable(HTTPClientError): ...
class HTTPProxyAuthenticationRequired(HTTPClientError): ...
class HTTPRequestTimeout(HTTPClientError): ...
class HTTPConflict(HTTPClientError): ...
class HTTPGone(HTTPClientError): ...
class HTTPLengthRequired(HTTPClientError): ...
class HTTPPreconditionFailed(HTTPClientError): ...
class HTTPRequestEntityTooLarge(HTTPClientError): ...
class HTTPRequestURITooLong(HTTPClientError): ...
class HTTPUnsupportedMediaType(HTTPClientError): ...
class HTTPRequestRangeNotSatisfiable(HTTPClientError): ...
class HTTPExpectationFailed(HTTPClientError): ...
class HTTPUnprocessableEntity(HTTPClientError): ...
class HTTPLocked(HTTPClientError): ...
class HTTPFailedDependency(HTTPClientError): ...
class HTTPPreconditionRequired(HTTPClientError): ...
class HTTPTooManyRequests(HTTPClientError): ...
class HTTPRequestHeaderFieldsTooLarge(HTTPClientError): ...
class HTTPUnavailableForLegalReasons(HTTPClientError): ...
class HTTPServerError(HTTPError): ...
class HTTPInternalServerError(HTTPServerError): ...
class HTTPNotImplemented(HTTPServerError): ...
class HTTPBadGateway(HTTPServerError): ...
class HTTPServiceUnavailable(HTTPServerError): ...
class HTTPGatewayTimeout(HTTPServerError): ...
class HTTPVersionNotSupported(HTTPServerError): ...
class HTTPInsufficientStorage(HTTPServerError): ...
class HTTPNetworkAuthenticationRequired(HTTPServerError): ...
class HTTPExceptionMiddleware:
application: WSGIApplication
def __init__(self, application: WSGIApplication) -> None: ...
def __call__(self, environ: WSGIEnvironment, start_response: StartResponse) -> Iterable[bytes]: ...
status_map: dict[int, WSGIHTTPException]

View File

@@ -0,0 +1,17 @@
from _typeshed.wsgi import WSGIEnvironment
from collections.abc import Iterator, MutableMapping
from webob.multidict import MultiDict
class ResponseHeaders(MultiDict[str, str]): ...
class EnvironHeaders(MutableMapping[str, str]):
environ: WSGIEnvironment
def __init__(self, environ: WSGIEnvironment) -> None: ...
def __getitem__(self, hname: str) -> str: ...
def __setitem__(self, hname: str, value: str) -> None: ...
def __delitem__(self, hname: str) -> None: ...
def keys(self) -> list[str]: ... # type:ignore[override]
def __contains__(self, hname: object) -> bool: ...
def __len__(self) -> int: ...
def __iter__(self) -> Iterator[str]: ...

View File

@@ -0,0 +1,105 @@
from _typeshed import SupportsItems, SupportsKeysAndGetItem
from _typeshed.wsgi import WSGIEnvironment
from cgi import FieldStorage
from collections.abc import Collection, Iterable, Iterator, MutableMapping
from typing import Any, TypeVar, overload
from typing_extensions import Literal, Self
_T = TypeVar("_T")
_KT = TypeVar("_KT")
_VT = TypeVar("_VT")
class MultiDict(MutableMapping[_KT, _VT]):
@overload
def __init__(self, __m: SupportsItems[_KT, _VT], **kwargs: _VT): ...
@overload
def __init__(self, __m: Iterable[tuple[_KT, _VT]], **kwargs: _VT): ...
@overload
def __init__(self, **kwargs: _VT) -> None: ...
@classmethod
def view_list(cls, lst: list[tuple[_KT, _VT]]) -> MultiDict[_KT, _VT]: ...
@classmethod
def from_fieldstorage(cls, fs: FieldStorage) -> MultiDict[str, str | FieldStorage]: ...
def __getitem__(self, key: _KT) -> _VT: ...
def __setitem__(self, key: _KT, value: _VT) -> None: ...
def add(self, key: _KT, value: _VT) -> None: ...
@overload
def get(self, key: _KT) -> _VT: ...
@overload
def get(self, key: _KT, default: _T) -> _VT | _T: ...
def getall(self, key: _KT) -> list[_VT]: ...
def getone(self, key: _KT) -> _VT: ...
def mixed(self) -> dict[_KT, _VT | list[_VT]]: ...
def dict_of_lists(self) -> dict[_KT, list[_VT]]: ...
def __delitem__(self, key: _KT) -> None: ...
def __contains__(self, key: object) -> bool: ...
has_key = __contains__
def clear(self) -> None: ...
def copy(self) -> Self: ...
@overload
def setdefault(self, key: _KT, default: None = None) -> _VT | None: ... # type:ignore[misc]
@overload
def setdefault(self, key: _KT, default: _VT) -> _VT: ...
@overload
def pop(self, key: _KT) -> _VT: ...
@overload
def pop(self, key: _KT, default: _T) -> _VT | _T: ...
def popitem(self) -> tuple[_KT, _VT]: ...
@overload # type:ignore[override]
def update(self, __m: Collection[tuple[_KT, _VT]], **kwargs: _VT) -> None: ...
@overload
def update(self, **kwargs: _VT) -> None: ...
@overload
def extend(self, other: SupportsItems[_KT, _VT], **kwargs: _VT) -> None: ...
@overload
def extend(self, other: SupportsKeysAndGetItem[_KT, _VT], **kwargs: _VT) -> None: ...
@overload
def extend(self, other: Iterable[tuple[_KT, _VT]], **kwargs: _VT) -> None: ...
@overload
def extend(self, other: None = None, **kwargs: _VT) -> None: ...
def __len__(self) -> int: ...
def keys(self) -> Iterator[_KT]: ... # type:ignore[override]
__iter__ = keys
def values(self) -> Iterator[_VT]: ... # type:ignore[override]
def items(self) -> Iterator[tuple[_KT, _VT]]: ... # type:ignore[override]
class GetDict(MultiDict[str, str]):
env: WSGIEnvironment
@overload
def __init__(self, data: SupportsItems[str, str], env: WSGIEnvironment) -> None: ...
@overload
def __init__(self, data: Iterable[tuple[str, str]], env: WSGIEnvironment) -> None: ...
def on_change(self) -> None: ...
class NestedMultiDict(MultiDict[_KT, _VT]):
dicts: tuple[MultiDict[_KT, _VT] | NoVars, ...]
def __init__(self, *dicts: MultiDict[_KT, _VT] | NoVars) -> None: ...
def __setitem__(self, key: _KT, value: _VT) -> None: ...
def add(self, key: _KT, value: _VT) -> None: ...
def __delitem__(self, key: _KT) -> None: ...
def clear(self) -> None: ...
def setdefault(self, key: _KT, default: _VT | None = ...) -> Any: ...
def pop(self, key: _KT, default: Any = ...) -> Any: ...
def popitem(self) -> tuple[_KT, _VT]: ...
def update(self, *args: Any, **kwargs: _VT) -> None: ...
def copy(self) -> MultiDict[_KT, _VT]: ... # type:ignore[override]
class NoVars:
reason: str
def __init__(self, reason: str | None = None) -> None: ...
@overload
def get(self, key: str, default: None = None) -> None: ...
@overload
def get(self, key: str, default: _T) -> _T: ...
def getall(self, key: str) -> list[str]: ...
def mixed(self) -> dict[str, str | list[str]]: ...
def dict_of_lists(self) -> dict[str, list[str]]: ...
def __contains__(self, key: object) -> Literal[False]: ...
has_key = __contains__
def copy(self) -> Self: ...
def __len__(self) -> Literal[0]: ...
def __iter__(self) -> Iterator[str]: ...
def keys(self) -> Iterator[str]: ...
def values(self) -> Iterator[str]: ...
def items(self) -> Iterator[tuple[str, str]]: ...
def __bool__(self) -> Literal[False]: ...

View File

@@ -0,0 +1,238 @@
import datetime
import io
from _typeshed import (
ExcInfo,
Incomplete,
ReadableBuffer,
SupportsItems,
SupportsKeysAndGetItem,
SupportsNoArgReadline,
SupportsRead,
)
from _typeshed.wsgi import WSGIApplication, WSGIEnvironment
from cgi import FieldStorage
from collections.abc import Iterable, Mapping
from re import Pattern
from tempfile import _TemporaryFileWrapper
from typing import IO, Any, ClassVar, Protocol, TypeVar, overload
from typing_extensions import Literal, Self, TypeAlias, TypedDict
from webob.acceptparse import _AcceptCharsetProperty, _AcceptEncodingProperty, _AcceptLanguageProperty, _AcceptProperty
from webob.byterange import Range
from webob.cachecontrol import _RequestCacheControl
from webob.cookies import RequestCookies
from webob.descriptors import _AsymmetricProperty, _AsymmetricPropertyWithDelete, _authorization, _DateProperty
from webob.etag import IfRange, IfRangeDate, _ETagProperty
from webob.headers import EnvironHeaders
from webob.multidict import GetDict, MultiDict, NestedMultiDict, NoVars
from webob.response import Response, _HTTPHeader
_T = TypeVar("_T")
_HTTPMethod: TypeAlias = Literal["GET", "HEAD", "POST", "PUT", "DELETE", "PATCH"]
_ListOrTuple: TypeAlias = list[_T] | tuple[_T, ...]
class _SupportsReadAndNoArgReadline(SupportsRead[bytes], SupportsNoArgReadline[bytes], Protocol): ...
class _RequestCacheControlDict(TypedDict, total=False):
max_stale: int
min_stale: int
only_if_cached: bool
no_cache: Literal[True] | str
no_store: bool
no_transform: bool
max_age: int
class _FieldStorageWithFile(FieldStorage):
file: IO[bytes]
filename: str
class _NoDefault: ...
NoDefault: _NoDefault
class BaseRequest:
request_body_tempfile_limit: ClassVar[int]
environ: WSGIEnvironment
method: _HTTPMethod
def __init__(self, environ: WSGIEnvironment, **kw: Any) -> None: ...
def encget(self, key: str, default: Any = ..., encattr: str | None = None) -> Any: ...
def encset(self, key: str, val: Any, encattr: str | None = None) -> None: ...
@property
def charset(self) -> str | None: ...
def decode(self, charset: str | None = None, errors: str = "strict") -> Self: ...
@property
def body_file(self) -> SupportsRead[bytes]: ...
@body_file.setter
def body_file(self, value: SupportsRead[bytes]) -> None: ...
content_length: int | None
body_file_raw: SupportsRead[bytes]
is_body_seekable: bool
@property
def body_file_seekable(self) -> IO[bytes]: ...
url_encoding: str
@property
def scheme(self) -> str | None: ...
@scheme.setter
def scheme(self, value: str | None) -> None: ...
@property
def http_version(self) -> str | None: ...
@http_version.setter
def http_version(self, value: str | None) -> None: ...
remote_user: str | None
remote_host: str | None
remote_addr: str | None
query_string: str
@property
def server_name(self) -> str | None: ...
@server_name.setter
def server_name(self, value: str | None) -> None: ...
@property
def server_port(self) -> int | None: ...
@server_port.setter
def server_port(self, value: int | None) -> None: ...
script_name: str
@property
def path_info(self) -> str | None: ...
@path_info.setter
def path_info(self, value: str | None) -> None: ...
uscript_name: str # bw compat
upath_info = path_info # bw compat
content_type: str | None
headers: _AsymmetricProperty[EnvironHeaders, SupportsItems[str, str] | Iterable[tuple[str, str]]]
@property
def client_addr(self) -> str | None: ...
@property
def host_port(self) -> str: ...
@property
def host_url(self) -> str: ...
@property
def application_url(self) -> str: ...
@property
def path_url(self) -> str: ...
@property
def path(self) -> str: ...
@property
def path_qs(self) -> str: ...
@property
def url(self) -> str: ...
def relative_url(self, other_url: str, to_application: bool = False) -> str: ...
def path_info_pop(self, pattern: Pattern[str] | None = None) -> str | None: ...
def path_info_peek(self) -> str | None: ...
urlvars: dict[str, str]
urlargs: tuple[str]
@property
def is_xhr(self) -> bool: ...
host: str
@property
def domain(self) -> str: ...
body: bytes
json: Any
json_body: Any
text: str
@property
def POST(self) -> MultiDict[str, str | _FieldStorageWithFile] | NoVars: ...
@property
def GET(self) -> GetDict: ...
@property
def params(self) -> NestedMultiDict[str, str | _FieldStorageWithFile]: ...
cookies: _AsymmetricProperty[RequestCookies, SupportsKeysAndGetItem[str, str] | Iterable[tuple[str, str]]]
def copy(self) -> Self: ...
def copy_get(self) -> Self: ...
@property
def is_body_readable(self) -> bool: ...
@is_body_readable.setter
def is_body_readable(self, flag: bool) -> None: ...
def make_body_seekable(self) -> None: ...
def copy_body(self) -> None: ...
def make_tempfile(self) -> _TemporaryFileWrapper[bytes]: ...
def remove_conditional_headers(
self, remove_encoding: bool = True, remove_range: bool = True, remove_match: bool = True, remove_modified: bool = True
) -> None: ...
accept: _AcceptProperty
accept_charset: _AcceptCharsetProperty
accept_encoding: _AcceptEncodingProperty
accept_language: _AcceptLanguageProperty
authorization: _AsymmetricPropertyWithDelete[_authorization | None, tuple[str, str | dict[str, str]] | list[Any] | str | None]
cache_control: _AsymmetricPropertyWithDelete[
_RequestCacheControl | None, _RequestCacheControl | _RequestCacheControlDict | str | None
]
if_match: _ETagProperty
if_none_match: _ETagProperty
date: _DateProperty
if_modified_since: _DateProperty
if_unmodified_since: _DateProperty
if_range: _AsymmetricPropertyWithDelete[
IfRange | IfRangeDate | None, IfRange | IfRangeDate | datetime.datetime | datetime.date | str | None
]
max_forwards: int | None
pragma: str | None
range: _AsymmetricPropertyWithDelete[Range, tuple[int, int | None] | list[int | None] | str | None]
referer: str | None
referrer: str | None
user_agent: str | None
def as_bytes(self, skip_body: bool = False) -> bytes: ...
def as_text(self) -> str: ...
@classmethod
def from_bytes(cls, b: bytes) -> Self: ...
@classmethod
def from_text(cls, s: str) -> Self: ...
@classmethod
def from_file(cls, fp: _SupportsReadAndNoArgReadline) -> Self: ...
@overload
def call_application(
self, application: WSGIApplication, catch_exc_info: Literal[False] = False
) -> tuple[str, list[_HTTPHeader], Iterable[bytes]]: ...
@overload
def call_application(
self, application: WSGIApplication, catch_exc_info: Literal[True]
) -> tuple[str, list[_HTTPHeader], Iterable[bytes], ExcInfo | None]: ...
ResponseClass: type[Response]
def send(self, application: WSGIApplication | None = None, catch_exc_info: bool = False) -> Response: ...
get_response = send
def make_default_send_app(self) -> WSGIApplication: ...
@classmethod
def blank(
cls,
path: str,
environ: dict[str, None] | None = None,
base_url: str | None = None,
headers: Mapping[str, str] | None = None,
POST: str | bytes | Mapping[Any, Any] | Mapping[Any, _ListOrTuple[Any]] | None = None,
**kw,
) -> Self: ...
class LegacyRequest(BaseRequest):
uscript_name: Incomplete
upath_info: Incomplete
def encget(self, key, default=..., encattr: Incomplete | None = None): ...
class AdhocAttrMixin:
def __setattr__(self, attr: str, value: Any) -> None: ...
def __getattr__(self, attr: str) -> Any: ...
def __delattr__(self, attr: str) -> None: ...
class Request(AdhocAttrMixin, BaseRequest): ...
class DisconnectionError(IOError): ...
def environ_from_url(path: str) -> WSGIEnvironment: ...
def environ_add_POST(
env: WSGIEnvironment,
data: str | bytes | Mapping[Any, Any] | Mapping[Any, _ListOrTuple[Any]] | None,
content_type: str | None = None,
) -> None: ...
class LimitedLengthFile(io.RawIOBase):
file: SupportsRead[bytes]
maxlen: int
remaining: int
def __init__(self, file: SupportsRead[bytes], maxlen: int) -> None: ...
@staticmethod
def readable() -> Literal[True]: ...
def readinto(self, buff: ReadableBuffer) -> int: ...
class Transcoder:
charset: str
errors: str
def __init__(self, charset: str, errors: str = "strict") -> None: ...
def transcode_query(self, q: str) -> str: ...
def transcode_fs(self, fs: FieldStorage, content_type: str) -> io.BytesIO: ...

View File

@@ -0,0 +1,179 @@
from _typeshed import SupportsItems, SupportsRead
from _typeshed.wsgi import StartResponse, WSGIApplication, WSGIEnvironment
from collections.abc import Iterable, Iterator, Sequence
from datetime import timedelta
from typing import IO, Any, Protocol
from typing_extensions import Literal, TypeAlias, TypedDict
from webob.byterange import ContentRange
from webob.cachecontrol import _ResponseCacheControl
from webob.descriptors import _AsymmetricProperty, _AsymmetricPropertyWithDelete, _authorization, _DateProperty, _ListProperty
from webob.headers import ResponseHeaders
from webob.request import Request
class _ResponseCacheExpires(Protocol):
def __call__(
self,
seconds: int | timedelta = 0,
*,
public: bool = ...,
private: Literal[True] | str = ...,
no_cache: Literal[True] | str = ...,
no_store: bool = ...,
no_transform: bool = ...,
must_revalidate: bool = ...,
proxy_revalidate: bool = ...,
max_age: int = ...,
s_maxage: int = ...,
s_max_age: int = ...,
stale_while_revalidate: int = ...,
stale_if_error: int = ...,
) -> None: ...
class _ResponseCacheControlDict(TypedDict, total=False):
public: bool
private: Literal[True] | str
no_cache: Literal[True] | str
no_store: bool
no_transform: bool
must_revalidate: bool
proxy_revalidate: bool
max_age: int
s_maxage: int
s_max_age: int
stale_while_revalidate: int
stale_if_error: int
_HTTPHeader: TypeAlias = tuple[str, str]
_ContentRangeParams: TypeAlias = (
ContentRange
| list[int | None]
| tuple[int, int]
| tuple[None, None]
| tuple[int, int, int | None]
| tuple[None, None, int | None]
| str
| None
)
class Response:
default_content_type: str
default_charset: str
unicode_errors: str
default_conditional_response: bool
default_body_encoding: str
request: Request | None
environ: WSGIEnvironment | None
status: str
conditional_response: bool
def __init__(
self,
body: bytes | str | None = None,
status: str | None = None,
headerlist: list[_HTTPHeader] | None = None,
app_iter: Iterator[bytes] | None = None,
content_type: str | None = None,
conditional_response: bool | None = None,
charset: str = ...,
**kw: Any,
) -> None: ...
@classmethod
def from_file(cls, fp: IO[str]) -> Response: ...
def copy(self) -> Response: ...
status_code: int
status_int: int
headerlist: _AsymmetricPropertyWithDelete[list[_HTTPHeader], Iterable[_HTTPHeader] | SupportsItems[str, str]]
headers: _AsymmetricProperty[ResponseHeaders, SupportsItems[str, str] | Iterable[tuple[str, str]]]
body: bytes
json: Any
json_body: Any
@property
def has_body(self) -> bool: ...
text: str
unicode_body: str # deprecated
ubody: str # deprecated
body_file: _AsymmetricPropertyWithDelete[ResponseBodyFile, SupportsRead[bytes]]
content_length: int | None
def write(self, text: str | bytes) -> None: ...
app_iter: Iterator[bytes]
allow: _ListProperty
vary: _ListProperty
content_encoding: str | None
content_language: _ListProperty
content_location: str | None
content_md5: str | None
content_disposition: str | None
accept_ranges: str | None
content_range: _AsymmetricPropertyWithDelete[ContentRange | None, _ContentRangeParams]
date: _DateProperty
expires: _DateProperty
last_modified: _DateProperty
etag: _AsymmetricPropertyWithDelete[str | None, tuple[str, bool] | str | None]
@property
def etag_strong(self) -> str | None: ...
location: str | None
pragma: str | None
age: int | None
retry_after: _DateProperty
server: str | None
www_authenticate: _AsymmetricPropertyWithDelete[
_authorization | None, tuple[str, str | dict[str, str]] | list[Any] | str | None
]
charset: str | None
content_type: str | None
content_type_params: _AsymmetricPropertyWithDelete[dict[str, str], SupportsItems[str, str] | None]
def set_cookie(
self,
name: str,
value: str | None = "",
max_age: int | timedelta | None = None,
path: str = "/",
domain: str | None = None,
secure: bool = False,
httponly: bool = False,
comment: str | None = None,
overwrite: bool = False,
samesite: Literal["strict", "lax", "none"] | None = None,
) -> None: ...
def delete_cookie(self, name: str, path: str = "/", domain: str | None = None) -> None: ...
def unset_cookie(self, name: str, strict: bool = True) -> None: ...
def merge_cookies(self, resp: Response | WSGIApplication) -> None: ...
cache_control: _AsymmetricProperty[_ResponseCacheControl, _ResponseCacheControl | _ResponseCacheControlDict | str | None]
cache_expires: _AsymmetricProperty[_ResponseCacheExpires, timedelta | int | bool | None]
def encode_content(self, encoding: Literal["gzip", "identity"] = "gzip", lazy: bool = False) -> None: ...
def decode_content(self) -> None: ...
def md5_etag(self, body: bytes | None = None, set_content_md5: bool = False) -> None: ...
def __call__(self, environ: WSGIEnvironment, start_response: StartResponse) -> Iterable[bytes]: ...
def conditional_response_app(self, environ: WSGIEnvironment, start_response: StartResponse) -> Iterable[bytes]: ...
def app_iter_range(self, start: int, stop: int | None) -> AppIterRange: ...
def __str__(self, skip_body: bool = False) -> str: ...
class ResponseBodyFile:
mode: Literal["wb"]
closed: Literal[False]
response: Response
def __init__(self, response: Response): ...
@property
def encoding(self) -> str | None: ...
def write(self, text: str | bytes) -> int: ...
def writelines(self, seq: Sequence[str | bytes]) -> int: ...
def flush(self) -> None: ...
def tell(self) -> int: ...
class AppIterRange:
app_iter: Iterator[bytes]
start: int
stop: int | None
def __init__(self, app_iter: Iterator[bytes], start: int, stop: int | None) -> None: ...
def __iter__(self) -> Iterator[bytes]: ...
def next(self) -> bytes: ...
__next__ = next
def close(self) -> None: ...
class EmptyResponse:
def __init__(self, app_iter: Iterator[bytes] | None = None) -> None: ...
def __iter__(self) -> Iterator[bytes]: ...
def __len__(self) -> int: ...
def next(self) -> bytes: ...
__next__ = next

View File

@@ -0,0 +1,37 @@
from _typeshed import StrOrBytesPath
from collections.abc import Iterator
from typing import IO, Any
from webob.dec import wsgify
from webob.request import Request
from webob.response import Response
BLOCK_SIZE: int
class FileApp:
filename: StrOrBytesPath
kw: dict[str, Any]
def __init__(self, filename: StrOrBytesPath, **kw: Any) -> None: ...
@wsgify
def __call__(self, req: Request) -> Response: ...
class FileIter:
file: IO[bytes]
def __init__(self, file: IO[bytes]) -> None: ...
def app_iter_range(
self, seek: int | None = None, limit: int | None = None, block_size: int | None = None
) -> Iterator[bytes]: ...
__iter__ = app_iter_range
class DirectoryApp:
path: str | bytes
index_page: str | None
hide_index_with_redirect: bool
fileapp_kw: dict[str, Any]
def __init__(
self, path: StrOrBytesPath, index_page: str = "index.html", hide_index_with_redirect: bool = False, **kw: Any
) -> None: ...
def make_fileapp(self, path: StrOrBytesPath) -> FileApp: ...
@wsgify
def __call__(self, req: Request) -> Response | FileApp: ...
def index(self, req: Request, path: StrOrBytesPath) -> Response | FileApp: ...

View File

@@ -0,0 +1,14 @@
from collections.abc import Callable
from typing import AnyStr, Protocol
class _HasHTML(Protocol):
def __html__(self) -> str: ...
def html_escape(s: str | bytes | _HasHTML) -> str: ...
def header_docstring(header, rfc_section): ...
def warn_deprecation(text, version, stacklevel) -> None: ...
status_reasons: dict[int, str]
status_generic_reasons: dict[int, str]
def strings_differ(string1: AnyStr, string2: AnyStr, compare_digest: Callable[[AnyStr, AnyStr], bool] = ...) -> bool: ...