Compare commits

..

7 Commits

Author SHA1 Message Date
Nate Prewitt
6e83187b8f v2.34.2
Some checks failed
Publish to PyPI / Build dists (push) Has been cancelled
Publish to PyPI / Publish (push) Has been cancelled
Publish to PyPI / Publish to Test PyPI (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.14t) (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.14t) (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.14t) (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
2026-05-14 12:21:52 -07:00
Nate Prewitt
84d10f0be8 Move Request.headers back to Mapping (#7441) 2026-05-14 09:16:25 -07:00
Nate Prewitt
b7b549b545 v2.34.1
Some checks failed
Publish to PyPI / Build dists (push) Has been cancelled
Publish to PyPI / Publish (push) Has been cancelled
Publish to PyPI / Publish to Test PyPI (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.14t) (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.14t) (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.14t) (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
2026-05-13 12:17:24 -07:00
Nate Prewitt
e511bc7277 Fix mutability issues with headers input types (#7431) 2026-05-13 12:16:50 -07:00
Nate Prewitt
5691f59613 Update JsonType containers to read-based collections (#7436) 2026-05-13 08:43:16 -06:00
Nate Prewitt
2144213c30 Constrain Response.reason to str (#7437) 2026-05-13 08:42:42 -06:00
Kaeun Kim
6404f345e5 Fix prepare_body stream detection for __getattr__-based file wrappers (#7433)
---------

Co-authored-by: Nate Prewitt <nate.prewitt@gmail.com>
2026-05-12 10:51:01 -07:00
6 changed files with 57 additions and 15 deletions

View File

@@ -6,6 +6,28 @@ dev
- \[Short description of non-trivial change.\]
2.34.2 (2026-05-14)
-------------------
- Moved `headers` input type back to `Mapping` to avoid invariance issues
with `MutableMapping` and inferred dict types. Users calling
`Request.headers.update()` may need to narrow typing in their code. (#7441)
2.34.1 (2026-05-13)
-------------------
**Bugfixes**
- Widened `json` input type from `dict` and `list` to `Mapping`
and `Sequence`. (#7436)
- Changed `headers` input type to MutableMapping and removed `None` from
`Request.headers` typing to improve handling for users. (#7431)
- `Response.reason` moved from `str | None` to `str` to improve handling
for users. (#7437)
- Fixed a bug where some bodies with custom `__getattr__` implementations
weren't being properly detected as Iterables. (#7433)
2.34.0 (2026-05-11)
-------------------

View File

@@ -5,8 +5,8 @@
__title__ = "requests"
__description__ = "Python HTTP for Humans."
__url__ = "https://requests.readthedocs.io"
__version__ = "2.34.0"
__build__ = 0x023400
__version__ = "2.34.2"
__build__ = 0x023402
__author__ = "Kenneth Reitz"
__author_email__ = "me@kennethreitz.org"
__license__ = "Apache-2.0"

View File

@@ -9,7 +9,7 @@ by external code.
from __future__ import annotations
from collections.abc import Callable, Iterable, Mapping, MutableMapping
from collections.abc import Callable, Iterable, Mapping, MutableMapping, Sequence
from typing import (
TYPE_CHECKING,
Any,
@@ -109,8 +109,7 @@ if TYPE_CHECKING:
bytes | str | Iterable[bytes | str] | SupportsRead[bytes | str] | None
)
HeadersType: TypeAlias = CaseInsensitiveDict[str] | Mapping[str, str | bytes]
HeadersUpdateType: TypeAlias = Mapping[str, str | bytes | None]
HeadersType: TypeAlias = Mapping[str, str | bytes] | None
CookiesType: TypeAlias = RequestsCookieJar | Mapping[str, str]
@@ -139,13 +138,19 @@ if TYPE_CHECKING:
VerifyType: TypeAlias = bool | str
CertType: TypeAlias = str | tuple[str, str] | None
JsonType: TypeAlias = (
None | bool | int | float | str | list["JsonType"] | dict[str, "JsonType"]
None
| bool
| int
| float
| str
| Sequence["JsonType"]
| Mapping[str, "JsonType"]
)
# TypedDicts for Unpack kwargs (PEP 692)
class BaseRequestKwargs(TypedDict, total=False):
headers: Mapping[str, str | bytes] | None
headers: HeadersType
cookies: RequestsCookieJar | CookieJar | dict[str, str] | None
files: FilesType
auth: AuthType

View File

@@ -310,7 +310,7 @@ class Request(RequestHooksMixin):
method: str | None
url: _t.UriType | None
headers: CaseInsensitiveDict[str] | Mapping[str, str | bytes] | None
headers: Mapping[str, str | bytes]
files: _t.FilesType
data: _t.DataType
json: _t.JsonType
@@ -322,7 +322,7 @@ class Request(RequestHooksMixin):
self,
method: str | None = None,
url: _t.UriType | None = None,
headers: Mapping[str, str | bytes] | None = None,
headers: _t.HeadersType = None,
files: _t.FilesType = None,
data: _t.DataType = None,
params: _t.ParamsType = None,
@@ -596,9 +596,9 @@ class PreparedRequest(RequestEncodingMixin, RequestHooksMixin):
if not isinstance(body, bytes):
body = body.encode("utf-8")
if isinstance(data, Iterable) and not isinstance(
data, (str, bytes, list, tuple, Mapping)
):
# data that proxies attributes to underlying objects needs hasattr
is_iterable = isinstance(data, Iterable) or hasattr(data, "__iter__")
if is_iterable and not isinstance(data, (str, bytes, list, tuple, Mapping)):
try:
length = super_len(data)
except (TypeError, AttributeError, UnsupportedOperation):
@@ -741,7 +741,7 @@ class Response:
url: str
encoding: str | None
history: list[Response]
reason: str | None
reason: str
cookies: RequestsCookieJar
elapsed: datetime.timedelta
request: PreparedRequest
@@ -790,7 +790,7 @@ class Response:
self.history = []
#: Textual reason of responded HTTP Status, e.g. "Not Found" or "OK".
self.reason = None
self.reason = None # type: ignore[assignment]
#: A CookieJar of Cookies the server sent back.
self.cookies = cookiejar_from_dict({})

View File

@@ -560,7 +560,7 @@ class Session(SessionRedirectMixin):
url: _t.UriType,
params: _t.ParamsType = None,
data: _t.DataType = None,
headers: Mapping[str, str | bytes] | None = None,
headers: _t.HeadersType = None,
cookies: RequestsCookieJar | CookieJar | dict[str, str] | None = None,
files: _t.FilesType = None,
auth: _t.AuthType = None,

View File

@@ -2073,6 +2073,21 @@ class TestRequests:
assert "Unable to rewind request body" in str(e)
def test_getattr_proxy_stream_follows_redirect(self, httpbin):
"""Ensure stream wrappers that don't implement __iter__ directly are still detected."""
class AttrProxy:
def __init__(self):
self._file = io.BytesIO(b"data")
def __getattr__(self, name):
return getattr(self._file, name)
r = requests.post(
httpbin("redirect-to?url=/post&status_code=307"), data=AttrProxy()
)
assert r.json()["data"] == "data"
def _patch_adapter_gzipped_redirect(self, session, url):
adapter = session.get_adapter(url=url)
org_build_response = adapter.build_response