Skip to content

Commit 33279e4

Browse files
committed
Use compat.py312.PTH_ENCODING instead of locale
1 parent f8f96a2 commit 33279e4

File tree

3 files changed

+44
-20
lines changed

3 files changed

+44
-20
lines changed

setuptools/command/easy_install.py

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
DEVELOP_DIST,
7575
)
7676
import pkg_resources
77-
from ..compat import py39, py311
77+
from ..compat import py39, py311, py312
7878
from .._path import ensure_directory
7979
from ..extern.jaraco.text import yield_lines
8080

@@ -588,8 +588,9 @@ def check_pth_processing(self): # noqa: C901
588588
os.unlink(ok_file)
589589
dirname = os.path.dirname(ok_file)
590590
os.makedirs(dirname, exist_ok=True)
591-
f = open(pth_file, 'w', encoding=py39.LOCALE_ENCODING)
592-
# ^-- Requires encoding="locale" instead of "utf-8" (python/cpython#77102).
591+
f = open(pth_file, 'w', encoding=py312.PTH_ENCODING)
592+
# ^-- Python<3.13 require encoding="locale" instead of "utf-8",
593+
# see python/cpython#77102.
593594
except OSError:
594595
self.cant_write_to_target()
595596
else:
@@ -1279,8 +1280,9 @@ def update_pth(self, dist): # noqa: C901 # is too complex (11) # FIXME
12791280
if os.path.islink(filename):
12801281
os.unlink(filename)
12811282

1282-
with open(filename, 'wt', encoding=py39.LOCALE_ENCODING) as f:
1283-
# Requires encoding="locale" instead of "utf-8" (python/cpython#77102).
1283+
with open(filename, 'wt', encoding=py312.PTH_ENCODING) as f:
1284+
# ^-- Python<3.13 require encoding="locale" instead of "utf-8",
1285+
# see python/cpython#77102.
12841286
f.write(self.pth_file.make_relative(dist.location) + '\n')
12851287

12861288
def unpack_progress(self, src, dst):
@@ -1506,9 +1508,8 @@ def expand_paths(inputs): # noqa: C901 # is too complex (11) # FIXME
15061508
continue
15071509

15081510
# Read the .pth file
1509-
with open(os.path.join(dirname, name), encoding=py39.LOCALE_ENCODING) as f:
1510-
# Requires encoding="locale" instead of "utf-8" (python/cpython#77102).
1511-
lines = list(yield_lines(f))
1511+
content = _read_pth(os.path.join(dirname, name))
1512+
lines = list(yield_lines(content))
15121513

15131514
# Yield existing non-dupe, non-import directory lines from it
15141515
for line in lines:
@@ -1622,9 +1623,8 @@ def _load_raw(self):
16221623
paths = []
16231624
dirty = saw_import = False
16241625
seen = dict.fromkeys(self.sitedirs)
1625-
f = open(self.filename, 'rt', encoding=py39.LOCALE_ENCODING)
1626-
# ^-- Requires encoding="locale" instead of "utf-8" (python/cpython#77102).
1627-
for line in f:
1626+
content = _read_pth(self.filename)
1627+
for line in content.splitlines():
16281628
path = line.rstrip()
16291629
# still keep imports and empty/commented lines for formatting
16301630
paths.append(path)
@@ -1643,7 +1643,6 @@ def _load_raw(self):
16431643
paths.pop()
16441644
continue
16451645
seen[normalized_path] = 1
1646-
f.close()
16471646
# remove any trailing empty/blank line
16481647
while paths and not paths[-1].strip():
16491648
paths.pop()
@@ -1694,8 +1693,9 @@ def save(self):
16941693
data = '\n'.join(lines) + '\n'
16951694
if os.path.islink(self.filename):
16961695
os.unlink(self.filename)
1697-
with open(self.filename, 'wt', encoding=py39.LOCALE_ENCODING) as f:
1698-
# Requires encoding="locale" instead of "utf-8" (python/cpython#77102).
1696+
with open(self.filename, 'wt', encoding=py312.PTH_ENCODING) as f:
1697+
# ^-- Python<3.13 require encoding="locale" instead of "utf-8",
1698+
# see python/cpython#77102.
16991699
f.write(data)
17001700
elif os.path.exists(self.filename):
17011701
log.debug("Deleting empty %s", self.filename)
@@ -2350,6 +2350,26 @@ def only_strs(values):
23502350
return filter(lambda val: isinstance(val, str), values)
23512351

23522352

2353+
def _read_pth(fullname: str) -> str:
2354+
# Python<3.13 require encoding="locale" instead of "utf-8", see python/cpython#77102
2355+
# In the case old versions of setuptools are producing `pth` files with
2356+
# different encodings that might be problematic... So we fallback to "locale".
2357+
2358+
try:
2359+
with open(fullname, encoding=py312.PTH_ENCODING) as f:
2360+
return f.read()
2361+
except UnicodeDecodeError: # pragma: no cover
2362+
# This error may only happen for Python >= 3.13
2363+
# TODO: Possible deprecation warnings to be added in the future:
2364+
# ``.pth file {fullname!r} is not UTF-8.``
2365+
# Your environment contain {fullname!r} that cannot be read as UTF-8.
2366+
# This is likely to have been produced with an old version of setuptools.
2367+
# Please be mindful that this is deprecated and in the future, non-utf8
2368+
# .pth files may cause setuptools to fail.
2369+
with open(fullname, encoding=py39.LOCALE_ENCODING) as f:
2370+
return f.read()
2371+
2372+
23532373
class EasyInstallDeprecationWarning(SetuptoolsDeprecationWarning):
23542374
_SUMMARY = "easy_install command is deprecated."
23552375
_DETAILS = """

setuptools/command/editable_wheel.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
namespaces,
4444
)
4545
from .._path import StrPath
46-
from ..compat import py39
46+
from ..compat import py312
4747
from ..discovery import find_package_path
4848
from ..dist import Distribution
4949
from ..warnings import (
@@ -550,7 +550,9 @@ def __exit__(self, _exc_type, _exc_value, _traceback):
550550

551551

552552
def _encode_pth(content: str) -> bytes:
553-
""".pth files are always read with 'locale' encoding, the recommendation
553+
"""
554+
Prior to Python 3.13 (see https://github.com/python/cpython/issues/77102),
555+
.pth files are always read with 'locale' encoding, the recommendation
554556
from the cpython core developers is to write them as ``open(path, "w")``
555557
and ignore warnings (see python/cpython#77102, pypa/setuptools#3937).
556558
This function tries to simulate this behaviour without having to create an
@@ -559,7 +561,8 @@ def _encode_pth(content: str) -> bytes:
559561
``encoding=None``, not all of them use ``locale.getpreferredencoding(False)``).
560562
"""
561563
with io.BytesIO() as buffer:
562-
wrapper = io.TextIOWrapper(buffer, encoding=py39.LOCALE_ENCODING)
564+
wrapper = io.TextIOWrapper(buffer, encoding=py312.PTH_ENCODING)
565+
# TODO: Python 3.13 replace the whole function with `bytes(content, "utf-8")`
563566
wrapper.write(content)
564567
wrapper.flush()
565568
buffer.seek(0)

setuptools/namespaces.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from distutils import log
33
import itertools
44

5-
from .compat import py39
5+
from .compat import py312
66

77

88
flatten = itertools.chain.from_iterable
@@ -25,8 +25,9 @@ def install_namespaces(self):
2525
list(lines)
2626
return
2727

28-
with open(filename, 'wt', encoding=py39.LOCALE_ENCODING) as f:
29-
# Requires encoding="locale" instead of "utf-8" (python/cpython#77102).
28+
with open(filename, 'wt', encoding=py312.PTH_ENCODING) as f:
29+
# Python<3.13 requires encoding="locale" instead of "utf-8"
30+
# See: python/cpython#77102
3031
f.writelines(lines)
3132

3233
def uninstall_namespaces(self):

0 commit comments

Comments
 (0)