gh-77102: site: try utf-8 and locale encoding when reading .pth file (GH-117802)

(cherry picked from commit 6dc661bc9f)
This commit is contained in:
Inada Naoki 2024-04-16 18:51:06 +09:00 committed by GitHub
parent 44eab29cbd
commit 2a58923687
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 38 additions and 26 deletions

View file

@ -179,35 +179,44 @@ def addpackage(sitedir, name, known_paths):
return return
_trace(f"Processing .pth file: {fullname!r}") _trace(f"Processing .pth file: {fullname!r}")
try: try:
# locale encoding is not ideal especially on Windows. But we have used with io.open_code(fullname) as f:
# it for a long time. setuptools uses the locale encoding too. pth_content = f.read()
f = io.TextIOWrapper(io.open_code(fullname), encoding="locale")
except OSError: except OSError:
return return
with f:
for n, line in enumerate(f): try:
if line.startswith("#"): pth_content = pth_content.decode()
except UnicodeDecodeError:
# Fallback to locale encoding for backward compatibility.
# We will deprecate this fallback in the future.
import locale
pth_content = pth_content.decode(locale.getencoding())
_trace(f"Cannot read {fullname!r} as UTF-8. "
f"Using fallback encoding {locale.getencoding()!r}")
for n, line in enumerate(pth_content.splitlines(), 1):
if line.startswith("#"):
continue
if line.strip() == "":
continue
try:
if line.startswith(("import ", "import\t")):
exec(line)
continue continue
if line.strip() == "": line = line.rstrip()
continue dir, dircase = makepath(sitedir, line)
try: if dircase not in known_paths and os.path.exists(dir):
if line.startswith(("import ", "import\t")): sys.path.append(dir)
exec(line) known_paths.add(dircase)
continue except Exception as exc:
line = line.rstrip() print(f"Error processing line {n:d} of {fullname}:\n",
dir, dircase = makepath(sitedir, line) file=sys.stderr)
if not dircase in known_paths and os.path.exists(dir): import traceback
sys.path.append(dir) for record in traceback.format_exception(exc):
known_paths.add(dircase) for line in record.splitlines():
except Exception as exc: print(' '+line, file=sys.stderr)
print("Error processing line {:d} of {}:\n".format(n+1, fullname), print("\nRemainder of file ignored", file=sys.stderr)
file=sys.stderr) break
import traceback
for record in traceback.format_exception(exc):
for line in record.splitlines():
print(' '+line, file=sys.stderr)
print("\nRemainder of file ignored", file=sys.stderr)
break
if reset: if reset:
known_paths = None known_paths = None
return known_paths return known_paths

View file

@ -0,0 +1,3 @@
:mod:`site` module now parses ``.pth`` file with UTF-8 first, and
:term:`locale encoding` if ``UnicodeDecodeError`` happened. It supported
only locale encoding before.