|
2 | 2 | import logging
|
3 | 3 | import os
|
4 | 4 | import textwrap
|
| 5 | +import warnings |
5 | 6 | from optparse import Values
|
6 | 7 | from pathlib import Path
|
7 | 8 | from typing import Any, Iterator, List, Optional, Protocol, Tuple, Union
|
@@ -883,3 +884,43 @@ def test_install_requirements_with_options(
|
883 | 884 | )
|
884 | 885 |
|
885 | 886 | assert req.global_options == [global_option]
|
| 887 | + |
| 888 | + def test_warns_on_decode_fail_in_locale( |
| 889 | + self, tmpdir: Path, session: PipSession |
| 890 | + ) -> None: |
| 891 | + # \xe3\x80\x82 encodes to 'IDEOGRAPHIC FULL STOP' in UTF-8 |
| 892 | + # the lone \x82 byte is invalid in the gbk encoding |
| 893 | + data = b"pip<=24.0 # some comment\xe3\x80\x82\n" |
| 894 | + locale_encoding = "gbk" |
| 895 | + req_file = tmpdir / "requirements.txt" |
| 896 | + req_file.write_bytes(data) |
| 897 | + |
| 898 | + # it's hard to rely on a locale definitely existing for testing |
| 899 | + # so patch things out for simplicity |
| 900 | + with pytest.warns(UnicodeWarning) as records, mock.patch( |
| 901 | + "locale.getpreferredencoding", return_value=locale_encoding |
| 902 | + ): |
| 903 | + reqs = tuple(parse_reqfile(req_file.resolve(), session=session)) |
| 904 | + |
| 905 | + assert len(records) == 1 |
| 906 | + assert ( |
| 907 | + str(records[0].message) |
| 908 | + == "unable to decode data with gbk, falling back to utf-8" |
| 909 | + ) |
| 910 | + assert len(reqs) == 1 |
| 911 | + assert reqs[0].name == "pip" |
| 912 | + assert str(reqs[0].specifier) == "<=24.0" |
| 913 | + |
| 914 | + @pytest.mark.parametrize("encoding", ("utf-8", "gbk")) |
| 915 | + def test_erorrs_on_non_decodable_data( |
| 916 | + self, encoding: str, tmpdir: Path, session: PipSession |
| 917 | + ) -> None: |
| 918 | + data = b"\xff" |
| 919 | + req_file = tmpdir / "requirements.txt" |
| 920 | + req_file.write_bytes(data) |
| 921 | + |
| 922 | + with warnings.catch_warnings(), pytest.raises(UnicodeDecodeError), mock.patch( |
| 923 | + "locale.getpreferredencoding", return_value=encoding |
| 924 | + ): |
| 925 | + warnings.simplefilter("ignore") # suppress warning not under test here |
| 926 | + next(parse_reqfile(req_file.resolve(), session=session)) |
0 commit comments