Skip to content

Commit dd5d1af

Browse files
committed
Use locale.getencoding instead of getpreferredencoding
- from Python 3.11 on, this is the preferred version - fixes #957
1 parent bf39aa3 commit dd5d1af

File tree

5 files changed

+21
-15
lines changed

5 files changed

+21
-15
lines changed

.github/workflows/testsuite.yml

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ jobs:
2121
2222
tests:
2323
runs-on: ${{ matrix.os }}
24+
env:
25+
PYTHONWARNDEFAULTENCODING: true
2426
strategy:
2527
fail-fast: false
2628
matrix:

CHANGES.md

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ The released versions correspond to PyPI releases.
77
* Fixed a specific problem on reloading a pandas-related module (see [#947](../../issues/947)),
88
added possibility for unload hooks for specific modules
99
* Use this also to reload django views (see [#932](../../issues/932))
10+
* Fixed `EncodingWarning` for Python >= 3.11 (see [#957](../../issues/957))
1011

1112
## [Version 5.3.5](https://pypi.python.org/pypi/pyfakefs/5.3.5) (2024-01-30)
1213
Fixes a regression.

pyfakefs/fake_file.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
"""
1717
import errno
1818
import io
19-
import locale
2019
import os
2120
import sys
2221
from stat import (
@@ -52,6 +51,7 @@
5251
real_encoding,
5352
AnyPath,
5453
AnyString,
54+
get_locale_encoding,
5555
)
5656

5757
if TYPE_CHECKING:
@@ -190,7 +190,7 @@ def contents(self) -> Optional[str]:
190190
"""Return the contents as string with the original encoding."""
191191
if isinstance(self.byte_contents, bytes):
192192
return self.byte_contents.decode(
193-
self.encoding or locale.getpreferredencoding(False),
193+
self.encoding or get_locale_encoding(),
194194
errors=self.errors,
195195
)
196196
return None
@@ -263,7 +263,7 @@ def _encode_contents(self, contents: Union[str, bytes, None]) -> Optional[bytes]
263263
if is_unicode_string(contents):
264264
contents = bytes(
265265
cast(str, contents),
266-
self.encoding or locale.getpreferredencoding(False),
266+
self.encoding or get_locale_encoding(),
267267
self.errors,
268268
)
269269
return cast(bytes, contents)
@@ -745,7 +745,7 @@ def __init__(
745745
self._use_line_buffer = not binary and buffering == 1
746746

747747
contents = file_object.byte_contents
748-
self._encoding = encoding or locale.getpreferredencoding(False)
748+
self._encoding = encoding or get_locale_encoding()
749749
errors = errors or "strict"
750750
self._io: Union[BinaryBufferIO, TextBufferIO] = (
751751
BinaryBufferIO(contents)

pyfakefs/helpers.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,12 @@ def is_unicode_string(val: Any) -> bool:
109109
return hasattr(val, "encode")
110110

111111

112+
def get_locale_encoding():
113+
if sys.version_info >= (3, 11):
114+
return locale.getencoding()
115+
return locale.getpreferredencoding(False)
116+
117+
112118
@overload
113119
def make_string_path(dir_name: AnyStr) -> AnyStr:
114120
...
@@ -127,15 +133,15 @@ def to_string(path: Union[AnyStr, Union[str, bytes]]) -> str:
127133
"""Return the string representation of a byte string using the preferred
128134
encoding, or the string itself if path is a str."""
129135
if isinstance(path, bytes):
130-
return path.decode(locale.getpreferredencoding(False))
136+
return path.decode(get_locale_encoding())
131137
return path
132138

133139

134140
def to_bytes(path: Union[AnyStr, Union[str, bytes]]) -> bytes:
135141
"""Return the bytes representation of a string using the preferred
136142
encoding, or the byte string itself if path is a byte string."""
137143
if isinstance(path, str):
138-
return bytes(path, locale.getpreferredencoding(False))
144+
return bytes(path, get_locale_encoding())
139145
return path
140146

141147

@@ -181,7 +187,7 @@ def matching_string( # type: ignore[misc]
181187
if string is None:
182188
return string
183189
if isinstance(matched, bytes) and isinstance(string, str):
184-
return string.encode(locale.getpreferredencoding(False))
190+
return string.encode(get_locale_encoding())
185191
return string # pytype: disable=bad-return-type
186192

187193

pyfakefs/tests/fake_open_test.py

+5-8
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,14 @@
1717

1818
import errno
1919
import io
20-
import locale
2120
import os
2221
import stat
2322
import sys
2423
import time
2524
import unittest
2625

2726
from pyfakefs import fake_filesystem, helpers
28-
from pyfakefs.helpers import is_root, IS_PYPY
27+
from pyfakefs.helpers import is_root, IS_PYPY, get_locale_encoding
2928
from pyfakefs.fake_io import FakeIoModule
3029
from pyfakefs.fake_filesystem_unittest import PatchMode
3130
from pyfakefs.tests.test_utils import RealFsTestCase
@@ -119,14 +118,12 @@ def test_write_str_read_bytes(self):
119118
try:
120119
with self.open(file_path, "w") as f:
121120
f.write(str_contents)
122-
except UnicodeEncodeError:
121+
with self.open(file_path, "rb") as f:
122+
contents = f.read()
123+
self.assertEqual(str_contents, contents.decode(get_locale_encoding()))
124+
except UnicodeError:
123125
# see https://github.com/pytest-dev/pyfakefs/issues/623
124126
self.skipTest("This test does not work with an ASCII locale")
125-
with self.open(file_path, "rb") as f:
126-
contents = f.read()
127-
self.assertEqual(
128-
str_contents, contents.decode(locale.getpreferredencoding(False))
129-
)
130127

131128
def test_open_valid_file(self):
132129
contents = [

0 commit comments

Comments
 (0)