From 657df3377e6c9b05dfbc77b78c9199e64302151d Mon Sep 17 00:00:00 2001 From: mrbean-bremen Date: Sun, 3 Mar 2024 12:47:57 +0100 Subject: [PATCH] Use locale.getencoding instead of getpreferredencoding - from Python 3.11 on, this is the preferred version - fixes #957 --- .github/workflows/testsuite.yml | 2 ++ CHANGES.md | 1 + pyfakefs/fake_file.py | 8 ++++---- pyfakefs/helpers.py | 12 +++++++++--- pyfakefs/tests/fake_open_test.py | 13 +++++-------- 5 files changed, 21 insertions(+), 15 deletions(-) diff --git a/.github/workflows/testsuite.yml b/.github/workflows/testsuite.yml index 15d3a74f..24031dda 100644 --- a/.github/workflows/testsuite.yml +++ b/.github/workflows/testsuite.yml @@ -21,6 +21,8 @@ jobs: tests: runs-on: ${{ matrix.os }} + env: + PYTHONWARNDEFAULTENCODING: true strategy: fail-fast: false matrix: diff --git a/CHANGES.md b/CHANGES.md index 7925a1d1..144d20bc 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,7 @@ The released versions correspond to PyPI releases. * Fixed a specific problem on reloading a pandas-related module (see [#947](../../issues/947)), added possibility for unload hooks for specific modules * Use this also to reload django views (see [#932](../../issues/932)) +* Fixed `EncodingWarning` for Python >= 3.11 (see [#957](../../issues/957)) ## [Version 5.3.5](https://pypi.python.org/pypi/pyfakefs/5.3.5) (2024-01-30) Fixes a regression. diff --git a/pyfakefs/fake_file.py b/pyfakefs/fake_file.py index 44d45be3..bc37a961 100644 --- a/pyfakefs/fake_file.py +++ b/pyfakefs/fake_file.py @@ -16,7 +16,6 @@ """ import errno import io -import locale import os import sys from stat import ( @@ -52,6 +51,7 @@ real_encoding, AnyPath, AnyString, + get_locale_encoding, ) if TYPE_CHECKING: @@ -190,7 +190,7 @@ def contents(self) -> Optional[str]: """Return the contents as string with the original encoding.""" if isinstance(self.byte_contents, bytes): return self.byte_contents.decode( - self.encoding or locale.getpreferredencoding(False), + self.encoding or get_locale_encoding(), errors=self.errors, ) return None @@ -263,7 +263,7 @@ def _encode_contents(self, contents: Union[str, bytes, None]) -> Optional[bytes] if is_unicode_string(contents): contents = bytes( cast(str, contents), - self.encoding or locale.getpreferredencoding(False), + self.encoding or get_locale_encoding(), self.errors, ) return cast(bytes, contents) @@ -745,7 +745,7 @@ def __init__( self._use_line_buffer = not binary and buffering == 1 contents = file_object.byte_contents - self._encoding = encoding or locale.getpreferredencoding(False) + self._encoding = encoding or get_locale_encoding() errors = errors or "strict" self._io: Union[BinaryBufferIO, TextBufferIO] = ( BinaryBufferIO(contents) diff --git a/pyfakefs/helpers.py b/pyfakefs/helpers.py index 416be19b..a5d8d5b8 100644 --- a/pyfakefs/helpers.py +++ b/pyfakefs/helpers.py @@ -109,6 +109,12 @@ def is_unicode_string(val: Any) -> bool: return hasattr(val, "encode") +def get_locale_encoding(): + if sys.version_info >= (3, 11): + return locale.getencoding() + return locale.getpreferredencoding(False) + + @overload def make_string_path(dir_name: AnyStr) -> AnyStr: ... @@ -127,7 +133,7 @@ def to_string(path: Union[AnyStr, Union[str, bytes]]) -> str: """Return the string representation of a byte string using the preferred encoding, or the string itself if path is a str.""" if isinstance(path, bytes): - return path.decode(locale.getpreferredencoding(False)) + return path.decode(get_locale_encoding()) return path @@ -135,7 +141,7 @@ def to_bytes(path: Union[AnyStr, Union[str, bytes]]) -> bytes: """Return the bytes representation of a string using the preferred encoding, or the byte string itself if path is a byte string.""" if isinstance(path, str): - return bytes(path, locale.getpreferredencoding(False)) + return bytes(path, get_locale_encoding()) return path @@ -181,7 +187,7 @@ def matching_string( # type: ignore[misc] if string is None: return string if isinstance(matched, bytes) and isinstance(string, str): - return string.encode(locale.getpreferredencoding(False)) + return string.encode(get_locale_encoding()) return string # pytype: disable=bad-return-type diff --git a/pyfakefs/tests/fake_open_test.py b/pyfakefs/tests/fake_open_test.py index d04bb79b..db51e776 100644 --- a/pyfakefs/tests/fake_open_test.py +++ b/pyfakefs/tests/fake_open_test.py @@ -17,7 +17,6 @@ import errno import io -import locale import os import stat import sys @@ -25,7 +24,7 @@ import unittest from pyfakefs import fake_filesystem, helpers -from pyfakefs.helpers import is_root, IS_PYPY +from pyfakefs.helpers import is_root, IS_PYPY, get_locale_encoding from pyfakefs.fake_io import FakeIoModule from pyfakefs.fake_filesystem_unittest import PatchMode from pyfakefs.tests.test_utils import RealFsTestCase @@ -119,14 +118,12 @@ def test_write_str_read_bytes(self): try: with self.open(file_path, "w") as f: f.write(str_contents) - except UnicodeEncodeError: + with self.open(file_path, "rb") as f: + contents = f.read() + self.assertEqual(str_contents, contents.decode(get_locale_encoding())) + except UnicodeError: # see https://github.com/pytest-dev/pyfakefs/issues/623 self.skipTest("This test does not work with an ASCII locale") - with self.open(file_path, "rb") as f: - contents = f.read() - self.assertEqual( - str_contents, contents.decode(locale.getpreferredencoding(False)) - ) def test_open_valid_file(self): contents = [