74
74
DEVELOP_DIST ,
75
75
)
76
76
import pkg_resources
77
- from ..compat import py39 , py311
77
+ from ..compat import py39 , py311 , py312
78
78
from .._path import ensure_directory
79
79
from ..extern .jaraco .text import yield_lines
80
80
@@ -588,8 +588,9 @@ def check_pth_processing(self): # noqa: C901
588
588
os .unlink (ok_file )
589
589
dirname = os .path .dirname (ok_file )
590
590
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.
593
594
except OSError :
594
595
self .cant_write_to_target ()
595
596
else :
@@ -1279,8 +1280,9 @@ def update_pth(self, dist): # noqa: C901 # is too complex (11) # FIXME
1279
1280
if os .path .islink (filename ):
1280
1281
os .unlink (filename )
1281
1282
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.
1284
1286
f .write (self .pth_file .make_relative (dist .location ) + '\n ' )
1285
1287
1286
1288
def unpack_progress (self , src , dst ):
@@ -1506,9 +1508,8 @@ def expand_paths(inputs): # noqa: C901 # is too complex (11) # FIXME
1506
1508
continue
1507
1509
1508
1510
# 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 ))
1512
1513
1513
1514
# Yield existing non-dupe, non-import directory lines from it
1514
1515
for line in lines :
@@ -1622,9 +1623,8 @@ def _load_raw(self):
1622
1623
paths = []
1623
1624
dirty = saw_import = False
1624
1625
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 ():
1628
1628
path = line .rstrip ()
1629
1629
# still keep imports and empty/commented lines for formatting
1630
1630
paths .append (path )
@@ -1643,7 +1643,6 @@ def _load_raw(self):
1643
1643
paths .pop ()
1644
1644
continue
1645
1645
seen [normalized_path ] = 1
1646
- f .close ()
1647
1646
# remove any trailing empty/blank line
1648
1647
while paths and not paths [- 1 ].strip ():
1649
1648
paths .pop ()
@@ -1694,8 +1693,9 @@ def save(self):
1694
1693
data = '\n ' .join (lines ) + '\n '
1695
1694
if os .path .islink (self .filename ):
1696
1695
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.
1699
1699
f .write (data )
1700
1700
elif os .path .exists (self .filename ):
1701
1701
log .debug ("Deleting empty %s" , self .filename )
@@ -2350,6 +2350,26 @@ def only_strs(values):
2350
2350
return filter (lambda val : isinstance (val , str ), values )
2351
2351
2352
2352
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
+
2353
2373
class EasyInstallDeprecationWarning (SetuptoolsDeprecationWarning ):
2354
2374
_SUMMARY = "easy_install command is deprecated."
2355
2375
_DETAILS = """
0 commit comments