diff --git a/stubs/httpretty/@tests/test_cases/check_usage.py b/stubs/httpretty/@tests/test_cases/check_usage.py new file mode 100644 index 000000000000..664d8dfbf7fa --- /dev/null +++ b/stubs/httpretty/@tests/test_cases/check_usage.py @@ -0,0 +1,17 @@ +from typing_extensions import assert_type + +import httpretty + + +@httpretty.activate(allow_net_connect=False) +def decorated() -> int: + httpretty.register_uri(httpretty.GET, "https://example.com/", body="ok", status=200, content_type="text/plain") + assert_type(httpretty.last_request(), httpretty.HTTPrettyRequest | httpretty.HTTPrettyRequestEmpty) + assert_type(httpretty.latest_requests(), list[httpretty.HTTPrettyRequest]) + assert_type(httpretty.has_request(), bool) + return 1 + + +with httpretty.enabled(allow_net_connect=False): + response = httpretty.Response("ok", status=201) + assert_type(response, httpretty.Entry) diff --git a/stubs/httpretty/METADATA.toml b/stubs/httpretty/METADATA.toml new file mode 100644 index 000000000000..84ef9a4c2452 --- /dev/null +++ b/stubs/httpretty/METADATA.toml @@ -0,0 +1,6 @@ +version = "1.1.4" +upstream-repository = "https://github.com/gabrielfalcao/HTTPretty" +partial-stub = true + +[tool.stubtest] +ignore-missing-stub = true diff --git a/stubs/httpretty/httpretty/__init__.pyi b/stubs/httpretty/httpretty/__init__.pyi new file mode 100644 index 000000000000..1bea66e0886d --- /dev/null +++ b/stubs/httpretty/httpretty/__init__.pyi @@ -0,0 +1,37 @@ +from .core import ( + EmptyRequestHeaders as EmptyRequestHeaders, + Entry as Entry, + HTTPrettyRequest as HTTPrettyRequest, + HTTPrettyRequestEmpty as HTTPrettyRequestEmpty, + URIInfo as URIInfo, + URIMatcher as URIMatcher, + get_default_thread_timeout as get_default_thread_timeout, + httprettified as httprettified, + httprettized as httprettized, + httpretty as httpretty, + set_default_thread_timeout as set_default_thread_timeout, +) +from .errors import HTTPrettyError as HTTPrettyError, UnmockedError as UnmockedError + +__version__: str +HTTPretty = httpretty +activate = httprettified +enabled = httprettized +enable = httpretty.enable +register_uri = httpretty.register_uri +disable = httpretty.disable +is_enabled = httpretty.is_enabled +reset = httpretty.reset +Response = httpretty.Response +GET: Final = "GET" +PUT: Final = "PUT" +POST: Final = "POST" +DELETE: Final = "DELETE" +HEAD: Final = "HEAD" +PATCH: Final = "PATCH" +OPTIONS: Final = "OPTIONS" +CONNECT: Final = "CONNECT" + +def last_request() -> HTTPrettyRequest | HTTPrettyRequestEmpty: ... +def latest_requests() -> list[HTTPrettyRequest]: ... +def has_request() -> bool: ... diff --git a/stubs/httpretty/httpretty/compat.pyi b/stubs/httpretty/httpretty/compat.pyi new file mode 100644 index 000000000000..aa9ef01dc4b4 --- /dev/null +++ b/stubs/httpretty/httpretty/compat.pyi @@ -0,0 +1,7 @@ +from typing import TypeVar + +_T = TypeVar("_T") + +class BaseClass: ... + +def encode_obj(in_obj: _T) -> _T: ... diff --git a/stubs/httpretty/httpretty/core.pyi b/stubs/httpretty/httpretty/core.pyi new file mode 100644 index 000000000000..6a880997776a --- /dev/null +++ b/stubs/httpretty/httpretty/core.pyi @@ -0,0 +1,203 @@ +import re +from collections.abc import Callable, Iterable, Mapping +from contextlib import AbstractContextManager +from http.client import HTTPMessage +from types import TracebackType +from typing import Any, Literal, TypeAlias, overload +from typing_extensions import ParamSpec + +from .http import HttpBaseClass + +_P = ParamSpec("_P") +_HTTPMethod: TypeAlias = Literal["GET", "PUT", "POST", "DELETE", "HEAD", "PATCH", "OPTIONS", "CONNECT"] +_URI: TypeAlias = str | re.Pattern[str] +_HeaderValue: TypeAlias = str | int | bool | None +_Headers: TypeAlias = Mapping[str, _HeaderValue] +_Body: TypeAlias = str | bytes +_ResponseBody: TypeAlias = _Body | Callable[[HTTPrettyRequest, str, _Headers], tuple[int, _Headers, _Body]] + +def set_default_thread_timeout(timeout: float) -> None: ... +def get_default_thread_timeout() -> float: ... + +class HTTPrettyRequest(HttpBaseClass): + headers: HTTPMessage + raw_headers: str + path: str + querystring: dict[str, list[str]] + parsed_body: Any # It can be any object after parsing raw (str) body + created_at: float + def __init__( + self, headers: str | bytes, body: _Body = "", sock: object | None = None, path_encoding: str = "iso-8859-1" + ) -> None: ... + @property + def method(self) -> str: ... + @property + def protocol(self) -> str: ... + + @property + def body(self) -> str: ... + @body.setter + def body(self, value: _Body) -> None: ... + + @property + def url(self) -> str: ... + @property + def host(self) -> str: ... + def parse_querystring(self, qs: str) -> dict[str, list[str]]: ... + def parse_request_body(self, body: str) -> Any: ... + +class EmptyRequestHeaders(dict[str, str]): ... + +class HTTPrettyRequestEmpty: + method: str | None + url: str | None + body: str + headers: EmptyRequestHeaders + +class Entry(HttpBaseClass): + method: _HTTPMethod + uri: str + request: HTTPrettyRequest + body: _Body + status: int + streaming: bool + adding_headers: dict[str, str] + forcing_headers: dict[str, str] + def __init__( + self, + method: str, + uri: str, + body: _ResponseBody, + adding_headers: _Headers | None = None, + forcing_headers: _Headers | None = None, + status: int = 200, + streaming: bool = False, + **headers: str, + ) -> None: ... + def validate(self) -> None: ... + def normalize_headers(self, headers: _Headers) -> dict[str, str]: ... + def fill_filekind(self, fk: _WritableFileobj) -> None: ... + +class URIInfo(HttpBaseClass): + default_str_attrs: tuple[str, ...] + username: str + password: str + hostname: str + port: int + path: str + query: str + scheme: str + fragment: str + last_request: HTTPrettyRequest | None + def __init__( + self, + username: str = "", + password: str = "", + hostname: str = "", + port: int = 80, + path: str = "/", + query: str = "", + fragment: str = "", + scheme: str = "", + last_request: HTTPrettyRequest | None = None, + ) -> None: ... + def to_str(self, attrs: Iterable[str]) -> str: ... + def str_with_query(self) -> str: ... + def full_url(self, use_querystring: bool = True) -> str: ... + def get_full_domain(self) -> str: ... + @classmethod + def from_uri(cls, uri: str, entry: Entry) -> URIInfo: ... + +class URIMatcher: + regex: re.Pattern[str] | None + info: URIInfo | None + entries: list[Entry] + priority: int + uri: _URI + def __init__(self, uri: _URI, entries: Iterable[Entry], match_querystring: bool = False, priority: int = 0) -> None: ... + def matches(self, info: URIInfo) -> bool: ... + def get_next_entry(self, method: _HTTPMethod, info: URIInfo, request: HTTPrettyRequest) -> Entry: ... + +class httpretty(HttpBaseClass): + GET: Final = "GET" + PUT: Final = "PUT" + POST: Final = "POST" + DELETE: Final = "DELETE" + HEAD: Final = "HEAD" + PATCH: Final = "PATCH" + OPTIONS: Final = "OPTIONS" + CONNECT: Final = "CONNECT" + METHODS: tuple[_HTTPMethod, ...] + latest_requests: list[HTTPrettyRequest] + last_request: HTTPrettyRequest | HTTPrettyRequestEmpty + allow_net_connect: bool + @classmethod + def match_uriinfo(cls, info: URIInfo) -> tuple[Entry | None, list[str]]: ... + @classmethod + def match_https_hostname(cls, hostname: str) -> bool: ... + @classmethod + def match_http_address(cls, hostname: str, port: int) -> bool: ... + @classmethod + def record( + cls, + filename: str, + indentation: int = 4, + encoding: str = "utf-8", + verbose: bool = False, + allow_net_connect: bool = True, + pool_manager_params: Mapping[str, Any] | None = None, + ) -> AbstractContextManager[None]: ... + @classmethod + def playback(cls, filename: str, allow_net_connect: bool = True, verbose: bool = False) -> AbstractContextManager[None]: ... + @classmethod + def reset(cls) -> None: ... + @classmethod + def historify_request(cls, headers: str | bytes, body: _Body = "", sock: object | None = None) -> HTTPrettyRequest: ... + @classmethod + def register_uri( + cls, + method: str, + uri: _URI, + body: _ResponseBody = '{"message": "HTTPretty :)"}', + adding_headers: _Headers | None = None, + forcing_headers: _Headers | None = None, + status: int = 200, + responses: Iterable[Entry] | None = None, + match_querystring: bool = False, + priority: int = 0, + **headers: str, + ) -> None: ... + @classmethod + def Response( + cls, + body: _ResponseBody, + method: _HTTPMethod | None = None, + uri: str | None = None, + adding_headers: _Headers | None = None, + forcing_headers: _Headers | None = None, + status: int = 200, + streaming: bool = False, + **headers: str, + ) -> Entry: ... + @classmethod + def disable(cls) -> None: ... + @classmethod + def is_enabled(cls) -> bool: ... + @classmethod + def enable(cls, allow_net_connect: bool = True, verbose: bool = False) -> None: ... + +class httprettized: + allow_net_connect: bool + verbose: bool + def __init__(self, allow_net_connect: bool = True, verbose: bool = False) -> None: ... + def __enter__(self) -> None: ... + def __exit__( + self, exc_type: type[BaseException] | None, exc_value: BaseException | None, traceback: TracebackType | None + ) -> None: ... + +@overload +def httprettified(test: Callable[_P, Any]) -> Callable[_P, Any]: ... +@overload +def httprettified( + test: None = None, allow_net_connect: bool = True, verbose: bool = False +) -> Callable[[Callable[_P, Any]], Callable[_P, Any]]: ... diff --git a/stubs/httpretty/httpretty/errors.pyi b/stubs/httpretty/httpretty/errors.pyi new file mode 100644 index 000000000000..4fb6e583a119 --- /dev/null +++ b/stubs/httpretty/httpretty/errors.pyi @@ -0,0 +1,4 @@ +class HTTPrettyError(Exception): ... + +class UnmockedError(HTTPrettyError): + def __init__(self, message: str = ..., request: object | None = None, address: object | None = None) -> None: ... diff --git a/stubs/httpretty/httpretty/http.pyi b/stubs/httpretty/httpretty/http.pyi new file mode 100644 index 000000000000..c6669544ce5d --- /dev/null +++ b/stubs/httpretty/httpretty/http.pyi @@ -0,0 +1,20 @@ +from collections.abc import Sequence +from typing_extensions import TypeVar + +_T = TypeVar("_T", str, bytes) + +STATUSES: dict[int, str] + +class HttpBaseClass: + GET: Final = "GET" + PUT: Final = "PUT" + POST: Final = "POST" + DELETE: Final = "DELETE" + HEAD: Final = "HEAD" + PATCH: Final = "PATCH" + OPTIONS: Final = "OPTIONS" + CONNECT: Final = "CONNECT" + METHODS: tuple[_HTTPMethod, ...] + +def parse_requestline(s: str) -> tuple[str, str, str]: ... +def last_requestline(sent_data: Sequence[_T]) -> _T | None: ... diff --git a/stubs/httpretty/httpretty/utils.pyi b/stubs/httpretty/httpretty/utils.pyi new file mode 100644 index 000000000000..b38062b2ea81 --- /dev/null +++ b/stubs/httpretty/httpretty/utils.pyi @@ -0,0 +1,2 @@ +def utf8(s: str | bytes) -> bytes: ... +def decode_utf8(s: str | bytes) -> str: ... diff --git a/stubs/httpretty/httpretty/version.pyi b/stubs/httpretty/httpretty/version.pyi new file mode 100644 index 000000000000..c2ee2cab489b --- /dev/null +++ b/stubs/httpretty/httpretty/version.pyi @@ -0,0 +1 @@ +version: str