Skip to content

Commit cae26c0

Browse files
squash! Handle req file decode failures on locale encoding
Use `logging.warning` over `warnings`, include source details in message
1 parent 84067e1 commit cae26c0

File tree

2 files changed

+18
-16
lines changed

2 files changed

+18
-16
lines changed

src/pip/_internal/req/req_file.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import re
99
import shlex
1010
import urllib.parse
11-
import warnings
1211
from optparse import Values
1312
from typing import (
1413
TYPE_CHECKING,
@@ -558,10 +557,12 @@ def get_file_content(url: str, session: "PipSession") -> Tuple[str, str]:
558557
if exc.encoding == fallback_encoding:
559558
raise
560559

561-
warnings.warn(
562-
f"unable to decode data with {exc.encoding}, falling back to {fallback_encoding}", # noqa: E501
563-
UnicodeWarning,
564-
stacklevel=2,
560+
logging.warning(
561+
"unable to decode data from %s with encoding %s, "
562+
"falling back to encoding %s",
563+
url,
564+
exc.encoding,
565+
fallback_encoding,
565566
)
566567
content = raw_content.decode(fallback_encoding)
567568

tests/unit/test_req_file.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import logging
33
import os
44
import textwrap
5-
import warnings
65
from optparse import Values
76
from pathlib import Path
87
from typing import Any, Iterator, List, Optional, Protocol, Tuple, Union
@@ -886,7 +885,10 @@ def test_install_requirements_with_options(
886885
assert req.global_options == [global_option]
887886

888887
def test_warns_on_decode_fail_in_locale(
889-
self, tmpdir: Path, session: PipSession
888+
self,
889+
tmpdir: Path,
890+
session: PipSession,
891+
caplog: pytest.LogCaptureFixture,
890892
) -> None:
891893
# \xe3\x80\x82 encodes to 'IDEOGRAPHIC FULL STOP' in UTF-8
892894
# the lone \x82 byte is invalid in the gbk encoding
@@ -897,32 +899,31 @@ def test_warns_on_decode_fail_in_locale(
897899

898900
# it's hard to rely on a locale definitely existing for testing
899901
# so patch things out for simplicity
900-
with pytest.warns(UnicodeWarning) as records, mock.patch(
902+
with caplog.at_level(logging.WARNING, "pip._internal.req.req_file"), mock.patch(
901903
"locale.getpreferredencoding", return_value=locale_encoding
902904
):
903905
reqs = tuple(parse_reqfile(req_file.resolve(), session=session))
904906

905-
assert len(records) == 1
907+
assert len(caplog.records) == 1
906908
assert (
907-
str(records[0].message)
908-
== "unable to decode data with gbk, falling back to utf-8"
909+
caplog.records[0].msg == "unable to decode data from %s with encoding %s, "
910+
"falling back to encoding %s"
909911
)
912+
assert caplog.records[0].args == (str(req_file), locale_encoding, "utf-8")
913+
910914
assert len(reqs) == 1
911915
assert reqs[0].name == "pip"
912916
assert str(reqs[0].specifier) == "<=24.0"
913917

914-
@pytest.mark.parametrize("encoding", ("utf-8", "gbk"))
918+
@pytest.mark.parametrize("encoding", ["utf-8", "gbk"])
915919
def test_erorrs_on_non_decodable_data(
916920
self, encoding: str, tmpdir: Path, session: PipSession
917921
) -> None:
918922
data = b"\xff"
919923
req_file = tmpdir / "requirements.txt"
920924
req_file.write_bytes(data)
921925

922-
with warnings.catch_warnings(), pytest.raises(UnicodeDecodeError), mock.patch(
926+
with pytest.raises(UnicodeDecodeError), mock.patch(
923927
"locale.getpreferredencoding", return_value=encoding
924928
):
925-
warnings.simplefilter(
926-
"ignore", category=UnicodeWarning
927-
) # suppress warning not under test here
928929
next(parse_reqfile(req_file.resolve(), session=session))

0 commit comments

Comments
 (0)