Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Raise ValueError on Response.encoding being set after Response.text has been accessed #2852

Merged
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions httpx/_models.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import codecs
import datetime
import email.message
import json as jsonlib
@@ -603,6 +604,27 @@ 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, the encoding is not
allowed to be changed and will raise a ValueError if doing so.
"""

if hasattr(self, "_text"):
encoding = self.encoding or "utf-8"
if (
is_known_encoding(value)
and is_known_encoding(encoding)
and codecs.lookup(value) == codecs.lookup(encoding)
):
self._encoding = value
return
else:
raise ValueError(
f"Attempt to set encoding to '{value}' is not allowed,"
f"because the content has been decoded with encoding '{self.encoding}'"
)
self._encoding = value

@property
16 changes: 16 additions & 0 deletions tests/models/test_responses.py
Original file line number Diff line number Diff line change
@@ -298,6 +298,22 @@ 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"

response.encoding = "UTF8"

with pytest.raises(ValueError):
response.encoding = "iso-8859-1"


def test_read():
response = httpx.Response(
200,