diff --git a/CHANGELOG.md b/CHANGELOG.md index 66d2b080cd..4842dfff82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +## Unreleased + +### Fixed + +* Raise `ValueError` on `Response.encoding` being set after `Response.text` has been accessed. (#2852) + ## 0.25.0 (11th Sep, 2023) ### Removed diff --git a/httpx/_models.py b/httpx/_models.py index e1e45cf06b..8a6bda04bb 100644 --- a/httpx/_models.py +++ b/httpx/_models.py @@ -603,6 +603,16 @@ def encoding(self) -> typing.Optional[str]: @encoding.setter def encoding(self, value: str) -> None: + """ + Set the encoding to use for decoding the byte content into text. + + If the `text` attribute has been accessed, attempting to set the + encoding will throw a ValueError. + """ + if hasattr(self, "_text"): + raise ValueError( + "Setting encoding after `text` has been accessed is not allowed." + ) self._encoding = value @property diff --git a/tests/models/test_responses.py b/tests/models/test_responses.py index 9e65de8154..9177773a50 100644 --- a/tests/models/test_responses.py +++ b/tests/models/test_responses.py @@ -298,6 +298,23 @@ def test_response_force_encoding(): assert response.encoding == "iso-8859-1" +def test_response_force_encoding_after_text_accessed(): + response = httpx.Response( + 200, + content=b"Hello, world!", + ) + assert response.status_code == 200 + assert response.reason_phrase == "OK" + assert response.text == "Hello, world!" + assert response.encoding == "utf-8" + + with pytest.raises(ValueError): + response.encoding = "UTF8" + + with pytest.raises(ValueError): + response.encoding = "iso-8859-1" + + def test_read(): response = httpx.Response( 200,