Move class types to init where possible
Some checks failed
Lint code / lint (push) Has been cancelled
Tests / build (macOS-latest, 3.10) (push) Has been cancelled
Tests / build (macOS-latest, 3.11) (push) Has been cancelled
Tests / build (macOS-latest, 3.12) (push) Has been cancelled
Tests / build (macOS-latest, 3.13) (push) Has been cancelled
Tests / build (macOS-latest, 3.14) (push) Has been cancelled
Tests / build (macOS-latest, 3.15-dev) (push) Has been cancelled
Tests / build (macOS-latest, pypy-3.11) (push) Has been cancelled
Tests / build (ubuntu-22.04, 3.10) (push) Has been cancelled
Tests / build (ubuntu-22.04, 3.11) (push) Has been cancelled
Tests / build (ubuntu-22.04, 3.12) (push) Has been cancelled
Tests / build (ubuntu-22.04, 3.13) (push) Has been cancelled
Tests / build (ubuntu-22.04, 3.14) (push) Has been cancelled
Tests / build (ubuntu-22.04, 3.15-dev) (push) Has been cancelled
Tests / build (ubuntu-22.04, pypy-3.11) (push) Has been cancelled
Tests / build (windows-latest, 3.10) (push) Has been cancelled
Tests / build (windows-latest, 3.11) (push) Has been cancelled
Tests / build (windows-latest, 3.12) (push) Has been cancelled
Tests / build (windows-latest, 3.13) (push) Has been cancelled
Tests / build (windows-latest, 3.14) (push) Has been cancelled
Tests / build (windows-latest, 3.15-dev) (push) Has been cancelled
Tests / No Character Detection (push) Has been cancelled
Tests / urllib3 1.x (push) Has been cancelled
Type Check / typecheck (3.10) (push) Has been cancelled
Type Check / typecheck (3.14) (push) Has been cancelled

This commit is contained in:
Nate Prewitt
2026-05-07 17:54:56 -06:00
parent 04d750509b
commit 35ba878a72
8 changed files with 60 additions and 132 deletions

View File

@@ -110,7 +110,7 @@ if TYPE_CHECKING:
HeadersType: TypeAlias = CaseInsensitiveDict[str] | Mapping[str, str | bytes] HeadersType: TypeAlias = CaseInsensitiveDict[str] | Mapping[str, str | bytes]
HeadersUpdateType: TypeAlias = Mapping[str, str | bytes | None] HeadersUpdateType: TypeAlias = Mapping[str, str | bytes | None]
CookiesType: TypeAlias = RequestsCookieJar | Mapping[str, str] CookiesType: TypeAlias = RequestsCookieJar | CookieJar | None
# Building blocks for FilesType # Building blocks for FilesType
_FileName: TypeAlias = str | None _FileName: TypeAlias = str | None

View File

@@ -190,14 +190,6 @@ class HTTPAdapter(BaseAdapter):
"_pool_block", "_pool_block",
] ]
max_retries: Retry
config: dict[str, Any]
proxy_manager: dict[str, Any]
_pool_connections: int
_pool_maxsize: int
_pool_block: bool
poolmanager: _PoolManager
def __init__( def __init__(
self, self,
pool_connections: int = DEFAULT_POOLSIZE, pool_connections: int = DEFAULT_POOLSIZE,
@@ -206,18 +198,19 @@ class HTTPAdapter(BaseAdapter):
pool_block: bool = DEFAULT_POOLBLOCK, pool_block: bool = DEFAULT_POOLBLOCK,
) -> None: ) -> None:
if max_retries == DEFAULT_RETRIES: if max_retries == DEFAULT_RETRIES:
self.max_retries = Retry(0, read=False) self.max_retries: Retry = Retry(0, read=False)
else: else:
self.max_retries = Retry.from_int(max_retries) self.max_retries = Retry.from_int(max_retries)
self.config = {} self.config: dict[str, Any] = {}
self.proxy_manager = {} self.proxy_manager: dict[str, Any] = {}
super().__init__() super().__init__()
self._pool_connections = pool_connections self._pool_connections: int = pool_connections
self._pool_maxsize = pool_maxsize self._pool_maxsize: int = pool_maxsize
self._pool_block = pool_block self._pool_block: bool = pool_block
self.poolmanager: _PoolManager
self.init_poolmanager(pool_connections, pool_maxsize, block=pool_block) self.init_poolmanager(pool_connections, pool_maxsize, block=pool_block)
def __getstate__(self) -> dict[str, Any]: def __getstate__(self) -> dict[str, Any]:

View File

@@ -85,17 +85,14 @@ class AuthBase:
class HTTPBasicAuth(AuthBase): class HTTPBasicAuth(AuthBase):
"""Attaches HTTP Basic Authentication to the given Request object.""" """Attaches HTTP Basic Authentication to the given Request object."""
username: bytes | str
password: bytes | str
@overload @overload
def __init__(self, username: str, password: str) -> None: ... def __init__(self, username: str, password: str) -> None: ...
@overload @overload
def __init__(self, username: bytes, password: bytes) -> None: ... def __init__(self, username: bytes, password: bytes) -> None: ...
def __init__(self, username: bytes | str, password: bytes | str) -> None: def __init__(self, username: bytes | str, password: bytes | str) -> None:
self.username = username self.username: bytes | str = username
self.password = password self.password: bytes | str = password
def __eq__(self, other: object) -> bool: def __eq__(self, other: object) -> bool:
return all( return all(
@@ -124,25 +121,16 @@ class HTTPProxyAuth(HTTPBasicAuth):
class HTTPDigestAuth(AuthBase): class HTTPDigestAuth(AuthBase):
"""Attaches HTTP Digest Authentication to the given Request object.""" """Attaches HTTP Digest Authentication to the given Request object."""
username: bytes | str
password: bytes | str
_thread_local: threading.local
last_nonce: str
nonce_count: int
chal: dict[str, str]
pos: int | None
num_401_calls: int | None
@overload @overload
def __init__(self, username: str, password: str) -> None: ... def __init__(self, username: str, password: str) -> None: ...
@overload @overload
def __init__(self, username: bytes, password: bytes) -> None: ... def __init__(self, username: bytes, password: bytes) -> None: ...
def __init__(self, username: bytes | str, password: bytes | str) -> None: def __init__(self, username: bytes | str, password: bytes | str) -> None:
self.username = username self.username: bytes | str = username
self.password = password self.password: bytes | str = password
# Keep state in per-thread local storage # Keep state in per-thread local storage
self._thread_local = threading.local() self._thread_local: threading.local = threading.local()
def init_per_thread_state(self) -> None: def init_per_thread_state(self) -> None:
# Ensure state is initialized just once per-thread # Ensure state is initialized just once per-thread

View File

@@ -40,13 +40,11 @@ class MockRequest:
probably want `get_cookie_header`, defined below. probably want `get_cookie_header`, defined below.
""" """
type: str
def __init__(self, request: PreparedRequest) -> None: def __init__(self, request: PreparedRequest) -> None:
assert _is_prepared(request) assert _is_prepared(request)
self._r = request self._r = request
self._new_headers: dict[str, str] = {} self._new_headers: dict[str, str] = {}
self.type = urlparse(self._r.url).scheme self.type: str = urlparse(self._r.url).scheme
def get_type(self) -> str: def get_type(self) -> str:
return self.type return self.type

View File

@@ -22,14 +22,11 @@ class RequestException(IOError):
request. request.
""" """
response: Response | None
request: Request | PreparedRequest | None
def __init__(self, *args: Any, **kwargs: Any) -> None: def __init__(self, *args: Any, **kwargs: Any) -> None:
"""Initialize RequestException with `request` and `response` objects.""" """Initialize RequestException with `request` and `response` objects."""
response: Response | None = kwargs.pop("response", None) response: Response | None = kwargs.pop("response", None)
self.response = response self.response: Response | None = response
self.request = kwargs.pop("request", None) self.request: Request | PreparedRequest | None = kwargs.pop("request", None)
if response is not None and not self.request and hasattr(response, "request"): if response is not None and not self.request and hasattr(response, "request"):
self.request = response.request self.request = response.request
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)

View File

@@ -308,16 +308,6 @@ class Request(RequestHooksMixin):
<PreparedRequest [GET]> <PreparedRequest [GET]>
""" """
method: str | None
url: _t.UriType | None
headers: CaseInsensitiveDict[str] | Mapping[str, str | bytes] | None
files: _t.FilesType
data: _t.DataType
json: _t.JsonType
params: _t.ParamsType
auth: _t.AuthType
cookies: RequestsCookieJar | CookieJar | dict[str, str] | None
def __init__( def __init__(
self, self,
method: str | None = None, method: str | None = None,
@@ -338,19 +328,19 @@ class Request(RequestHooksMixin):
params = {} if params is None else params params = {} if params is None else params
hooks = {} if hooks is None else hooks hooks = {} if hooks is None else hooks
self.hooks = default_hooks() self.hooks: dict[str, list[_t.HookType]] = default_hooks()
for k, v in list(hooks.items()): for k, v in list(hooks.items()):
self.register_hook(event=k, hook=v) self.register_hook(event=k, hook=v)
self.method = method self.method: str | None = method
self.url = url self.url: _t.UriType | None = url
self.headers = headers self.headers: _t.HeadersType | None = headers
self.files = files self.files: _t.FilesType = files
self.data = data self.data: _t.DataType = data
self.json = json self.json: _t.JsonType = json
self.params = params self.params: _t.ParamsType = params
self.auth = auth self.auth: _t.AuthType = auth
self.cookies = cookies self.cookies: _t.CookiesType | dict[str, str] = cookies
def __repr__(self) -> str: def __repr__(self) -> str:
return f"<Request [{self.method}]>" return f"<Request [{self.method}]>"
@@ -394,30 +384,22 @@ class PreparedRequest(RequestEncodingMixin, RequestHooksMixin):
<Response [200]> <Response [200]>
""" """
method: str | None
url: str | None
headers: CaseInsensitiveDict[str | bytes]
_cookies: RequestsCookieJar | CookieJar | None
body: _t.BodyType
hooks: dict[str, list[_t.HookType]]
_body_position: int | object | None
def __init__(self) -> None: def __init__(self) -> None:
#: HTTP verb to send to the server. #: HTTP verb to send to the server.
self.method = None self.method: str | None = None
#: HTTP URL to send the request to. #: HTTP URL to send the request to.
self.url = None self.url: str | None = None
#: dictionary of HTTP headers. #: dictionary of HTTP headers.
self.headers = None # type: ignore[assignment] self.headers: CaseInsensitiveDict[str | bytes] = None # type: ignore[assignment]
# The `CookieJar` used to create the Cookie header will be stored here # The `CookieJar` used to create the Cookie header will be stored here
# after prepare_cookies is called # after prepare_cookies is called
self._cookies = None self._cookies: _t.CookiesType = None
#: request body to send to the server. #: request body to send to the server.
self.body = None self.body: _t.BodyType = None
#: dictionary of callback hooks, for internal usage. #: dictionary of callback hooks, for internal usage.
self.hooks = default_hooks() self.hooks: dict[str, list[_t.HookType]] = default_hooks()
#: integer denoting starting position of a readable file-like body. #: integer denoting starting position of a readable file-like body.
self._body_position = None self._body_position: int | object | None = None
def prepare( def prepare(
self, self,
@@ -732,19 +714,6 @@ class Response:
server's response to an HTTP request. server's response to an HTTP request.
""" """
_content: bytes | Literal[False] | None
_content_consumed: bool
_next: PreparedRequest | None
status_code: int
headers: CaseInsensitiveDict[str]
raw: Any
url: str
encoding: str | None
history: list[Response]
reason: str | None
cookies: RequestsCookieJar
elapsed: datetime.timedelta
request: PreparedRequest
connection: HTTPAdapter connection: HTTPAdapter
__attrs__: list[str] = [ __attrs__: list[str] = [
@@ -761,39 +730,39 @@ class Response:
] ]
def __init__(self) -> None: def __init__(self) -> None:
self._content = False self._content: bytes | Literal[False] | None = False
self._content_consumed = False self._content_consumed: bool = False
self._next = None self._next: PreparedRequest | None = None
#: Integer Code of responded HTTP Status, e.g. 404 or 200. #: Integer Code of responded HTTP Status, e.g. 404 or 200.
self.status_code = None # type: ignore[assignment] self.status_code: int = None # type: ignore[assignment]
#: Case-insensitive Dictionary of Response Headers. #: Case-insensitive Dictionary of Response Headers.
#: For example, ``headers['content-encoding']`` will return the #: For example, ``headers['content-encoding']`` will return the
#: value of a ``'Content-Encoding'`` response header. #: value of a ``'Content-Encoding'`` response header.
self.headers = CaseInsensitiveDict() self.headers: CaseInsensitiveDict[str] = CaseInsensitiveDict()
#: File-like object representation of response (for advanced usage). #: File-like object representation of response (for advanced usage).
#: Use of ``raw`` requires that ``stream=True`` be set on the request. #: Use of ``raw`` requires that ``stream=True`` be set on the request.
#: This requirement does not apply for use internally to Requests. #: This requirement does not apply for use internally to Requests.
self.raw = None self.raw: Any = None
#: Final URL location of Response. #: Final URL location of Response.
self.url = None # type: ignore[assignment] self.url: str = None # type: ignore[assignment]
#: Encoding to decode with when accessing r.text. #: Encoding to decode with when accessing r.text.
self.encoding = None self.encoding: str | None = None
#: A list of :class:`Response <Response>` objects from #: A list of :class:`Response <Response>` objects from
#: the history of the Request. Any redirect responses will end #: the history of the Request. Any redirect responses will end
#: up here. The list is sorted from the oldest to the most recent request. #: up here. The list is sorted from the oldest to the most recent request.
self.history = [] self.history: list[Response] = []
#: Textual reason of responded HTTP Status, e.g. "Not Found" or "OK". #: Textual reason of responded HTTP Status, e.g. "Not Found" or "OK".
self.reason = None self.reason: str | None = None
#: A CookieJar of Cookies the server sent back. #: A CookieJar of Cookies the server sent back.
self.cookies = cookiejar_from_dict({}) self.cookies: RequestsCookieJar = cookiejar_from_dict({})
#: The amount of time elapsed between sending the request #: The amount of time elapsed between sending the request
#: and the arrival of the response (as a timedelta). #: and the arrival of the response (as a timedelta).
@@ -801,11 +770,11 @@ class Response:
#: the first byte of the request and finishing parsing the headers. It #: the first byte of the request and finishing parsing the headers. It
#: is therefore unaffected by consuming the response content or the #: is therefore unaffected by consuming the response content or the
#: value of the ``stream`` keyword argument. #: value of the ``stream`` keyword argument.
self.elapsed = datetime.timedelta(0) self.elapsed: datetime.timedelta = datetime.timedelta(0)
#: The :class:`PreparedRequest <PreparedRequest>` object to which this #: The :class:`PreparedRequest <PreparedRequest>` object to which this
#: is a response. #: is a response.
self.request = None # type: ignore[assignment] self.request: PreparedRequest = None # type: ignore[assignment]
def __enter__(self) -> Self: def __enter__(self) -> Self:
return self return self

View File

@@ -411,19 +411,6 @@ class Session(SessionRedirectMixin):
<Response [200]> <Response [200]>
""" """
headers: CaseInsensitiveDict[str]
auth: _t.AuthType
proxies: dict[str, str]
hooks: dict[str, list[_t.HookType]]
params: MutableMapping[str, Any]
stream: bool
verify: _t.VerifyType
cert: _t.CertType
max_redirects: int
trust_env: bool
cookies: RequestsCookieJar
adapters: MutableMapping[str, BaseAdapter]
__attrs__: list[str] = [ __attrs__: list[str] = [
"headers", "headers",
"cookies", "cookies",
@@ -443,27 +430,27 @@ class Session(SessionRedirectMixin):
#: A case-insensitive dictionary of headers to be sent on each #: A case-insensitive dictionary of headers to be sent on each
#: :class:`Request <Request>` sent from this #: :class:`Request <Request>` sent from this
#: :class:`Session <Session>`. #: :class:`Session <Session>`.
self.headers = default_headers() self.headers: CaseInsensitiveDict[str] = default_headers()
#: Default Authentication tuple or object to attach to #: Default Authentication tuple or object to attach to
#: :class:`Request <Request>`. #: :class:`Request <Request>`.
self.auth = None self.auth: _t.AuthType = None
#: Dictionary mapping protocol or protocol and host to the URL of the proxy #: Dictionary mapping protocol or protocol and host to the URL of the proxy
#: (e.g. {'http': 'foo.bar:3128', 'http://host.name': 'foo.bar:4012'}) to #: (e.g. {'http': 'foo.bar:3128', 'http://host.name': 'foo.bar:4012'}) to
#: be used on each :class:`Request <Request>`. #: be used on each :class:`Request <Request>`.
self.proxies = {} self.proxies: dict[str, str] = {}
#: Event-handling hooks. #: Event-handling hooks.
self.hooks = default_hooks() self.hooks: dict[str, list[_t.HookType]] = default_hooks()
#: Dictionary of querystring data to attach to each #: Dictionary of querystring data to attach to each
#: :class:`Request <Request>`. The dictionary values may be lists for #: :class:`Request <Request>`. The dictionary values may be lists for
#: representing multivalued query parameters. #: representing multivalued query parameters.
self.params = {} self.params: MutableMapping[str, Any] = {}
#: Stream response content default. #: Stream response content default.
self.stream = False self.stream: bool = False
#: SSL Verification default. #: SSL Verification default.
#: Defaults to `True`, requiring requests to verify the TLS certificate at the #: Defaults to `True`, requiring requests to verify the TLS certificate at the
@@ -475,30 +462,30 @@ class Session(SessionRedirectMixin):
#: Only set this to `False` for testing. #: Only set this to `False` for testing.
#: If verify is set to a string, it must be the path to a CA bundle file #: If verify is set to a string, it must be the path to a CA bundle file
#: that will be used to verify the TLS certificate. #: that will be used to verify the TLS certificate.
self.verify = True self.verify: _t.VerifyType = True
#: SSL client certificate default, if String, path to ssl client #: SSL client certificate default, if String, path to ssl client
#: cert file (.pem). If Tuple, ('cert', 'key') pair. #: cert file (.pem). If Tuple, ('cert', 'key') pair.
self.cert = None self.cert: _t.CertType = None
#: Maximum number of redirects allowed. If the request exceeds this #: Maximum number of redirects allowed. If the request exceeds this
#: limit, a :class:`TooManyRedirects` exception is raised. #: limit, a :class:`TooManyRedirects` exception is raised.
#: This defaults to requests.models.DEFAULT_REDIRECT_LIMIT, which is #: This defaults to requests.models.DEFAULT_REDIRECT_LIMIT, which is
#: 30. #: 30.
self.max_redirects = DEFAULT_REDIRECT_LIMIT self.max_redirects: int = DEFAULT_REDIRECT_LIMIT
#: Trust environment settings for proxy configuration, default #: Trust environment settings for proxy configuration, default
#: authentication and similar. #: authentication and similar.
self.trust_env = True self.trust_env: bool = True
#: A CookieJar containing all currently outstanding cookies set on this #: A CookieJar containing all currently outstanding cookies set on this
#: session. By default it is a #: session. By default it is a
#: :class:`RequestsCookieJar <requests.cookies.RequestsCookieJar>`, but #: :class:`RequestsCookieJar <requests.cookies.RequestsCookieJar>`, but
#: may be any other ``cookielib.CookieJar`` compatible object. #: may be any other ``cookielib.CookieJar`` compatible object.
self.cookies = cookiejar_from_dict({}) self.cookies: RequestsCookieJar = cookiejar_from_dict({})
# Default connection adapters. # Default connection adapters.
self.adapters = OrderedDict() self.adapters: MutableMapping[str, BaseAdapter] = OrderedDict()
self.mount("https://", HTTPAdapter()) self.mount("https://", HTTPAdapter())
self.mount("http://", HTTPAdapter()) self.mount("http://", HTTPAdapter())

View File

@@ -44,14 +44,12 @@ class CaseInsensitiveDict(MutableMapping[str, _VT], Generic[_VT]):
behavior is undefined. behavior is undefined.
""" """
_store: OrderedDict[str, tuple[str, _VT]]
def __init__( def __init__(
self, self,
data: Mapping[str, _VT] | Iterable[tuple[str, _VT]] | None = None, data: Mapping[str, _VT] | Iterable[tuple[str, _VT]] | None = None,
**kwargs: _VT, **kwargs: _VT,
) -> None: ) -> None:
self._store = OrderedDict() self._store: OrderedDict[str, tuple[str, _VT]] = OrderedDict()
if data is None: if data is None:
data = {} data = {}
self.update(data, **kwargs) self.update(data, **kwargs)
@@ -96,10 +94,8 @@ class CaseInsensitiveDict(MutableMapping[str, _VT], Generic[_VT]):
class LookupDict(dict[str, _VT]): class LookupDict(dict[str, _VT]):
"""Dictionary lookup object.""" """Dictionary lookup object."""
name: Any
def __init__(self, name: Any = None) -> None: def __init__(self, name: Any = None) -> None:
self.name = name self.name: bytes | str = name
super().__init__() super().__init__()
def __repr__(self) -> str: def __repr__(self) -> str: