Skip to content

Commit d243c90

Browse files
authored
Update site from CPython v3.12.3 (#5313)
* Update site from CPython v3.12.3 * mark failing test --------- Co-authored-by: CPython Developers <>
1 parent 72033ab commit d243c90

File tree

3 files changed

+95
-48
lines changed

3 files changed

+95
-48
lines changed

Lib/_sitebuiltins.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
import sys
1212

13-
1413
class Quitter(object):
1514
def __init__(self, name, eof):
1615
self.name = name
@@ -48,7 +47,7 @@ def __setup(self):
4847
data = None
4948
for filename in self.__filenames:
5049
try:
51-
with open(filename, "r") as fp:
50+
with open(filename, encoding='utf-8') as fp:
5251
data = fp.read()
5352
break
5453
except OSError:

Lib/site.py

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
import builtins
7575
import _sitebuiltins
7676
import io
77+
import stat
7778

7879
# Prefixes for site-packages; add additional prefixes like /usr/local here
7980
PREFIXES = [sys.prefix, sys.exec_prefix]
@@ -168,6 +169,14 @@ def addpackage(sitedir, name, known_paths):
168169
else:
169170
reset = False
170171
fullname = os.path.join(sitedir, name)
172+
try:
173+
st = os.lstat(fullname)
174+
except OSError:
175+
return
176+
if ((getattr(st, 'st_flags', 0) & stat.UF_HIDDEN) or
177+
(getattr(st, 'st_file_attributes', 0) & stat.FILE_ATTRIBUTE_HIDDEN)):
178+
_trace(f"Skipping hidden .pth file: {fullname!r}")
179+
return
171180
_trace(f"Processing .pth file: {fullname!r}")
172181
try:
173182
# locale encoding is not ideal especially on Windows. But we have used
@@ -190,11 +199,11 @@ def addpackage(sitedir, name, known_paths):
190199
if not dircase in known_paths and os.path.exists(dir):
191200
sys.path.append(dir)
192201
known_paths.add(dircase)
193-
except Exception:
202+
except Exception as exc:
194203
print("Error processing line {:d} of {}:\n".format(n+1, fullname),
195204
file=sys.stderr)
196205
import traceback
197-
for record in traceback.format_exception(*sys.exc_info()):
206+
for record in traceback.format_exception(exc):
198207
for line in record.splitlines():
199208
print(' '+line, file=sys.stderr)
200209
print("\nRemainder of file ignored", file=sys.stderr)
@@ -221,7 +230,8 @@ def addsitedir(sitedir, known_paths=None):
221230
names = os.listdir(sitedir)
222231
except OSError:
223232
return
224-
names = [name for name in names if name.endswith(".pth")]
233+
names = [name for name in names
234+
if name.endswith(".pth") and not name.startswith(".")]
225235
for name in sorted(names):
226236
addpackage(sitedir, name, known_paths)
227237
if reset:
@@ -406,12 +416,7 @@ def setquit():
406416
def setcopyright():
407417
"""Set 'copyright' and 'credits' in builtins"""
408418
builtins.copyright = _sitebuiltins._Printer("copyright", sys.copyright)
409-
if sys.platform[:4] == 'java':
410-
builtins.credits = _sitebuiltins._Printer(
411-
"credits",
412-
"Jython is maintained by the Jython developers (www.jython.org).")
413-
else:
414-
builtins.credits = _sitebuiltins._Printer("credits", """\
419+
builtins.credits = _sitebuiltins._Printer("credits", """\
415420
Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands
416421
for supporting Python development. See www.python.org for more information.""")
417422
files, dirs = [], []
@@ -499,20 +504,23 @@ def venv(known_paths):
499504
executable = sys._base_executable = os.environ['__PYVENV_LAUNCHER__']
500505
else:
501506
executable = sys.executable
502-
exe_dir, _ = os.path.split(os.path.abspath(executable))
507+
exe_dir = os.path.dirname(os.path.abspath(executable))
503508
site_prefix = os.path.dirname(exe_dir)
504509
sys._home = None
505510
conf_basename = 'pyvenv.cfg'
506-
candidate_confs = [
507-
conffile for conffile in (
508-
os.path.join(exe_dir, conf_basename),
509-
os.path.join(site_prefix, conf_basename)
511+
candidate_conf = next(
512+
(
513+
conffile for conffile in (
514+
os.path.join(exe_dir, conf_basename),
515+
os.path.join(site_prefix, conf_basename)
510516
)
511-
if os.path.isfile(conffile)
512-
]
517+
if os.path.isfile(conffile)
518+
),
519+
None
520+
)
513521

514-
if candidate_confs:
515-
virtual_conf = candidate_confs[0]
522+
if candidate_conf:
523+
virtual_conf = candidate_conf
516524
system_site = "true"
517525
# Issue 25185: Use UTF-8, as that's what the venv module uses when
518526
# writing the file.

Lib/test/test_site.py

Lines changed: 68 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@
1010
from test.support import os_helper
1111
from test.support import socket_helper
1212
from test.support import captured_stderr
13-
from test.support.os_helper import TESTFN, EnvironmentVarGuard, change_cwd
13+
from test.support.os_helper import TESTFN, EnvironmentVarGuard
1414
import ast
1515
import builtins
16-
import encodings
1716
import glob
1817
import io
1918
import os
2019
import re
2120
import shutil
21+
import stat
2222
import subprocess
2323
import sys
2424
import sysconfig
@@ -195,6 +195,47 @@ def test_addsitedir(self):
195195
finally:
196196
pth_file.cleanup()
197197

198+
def test_addsitedir_dotfile(self):
199+
pth_file = PthFile('.dotfile')
200+
pth_file.cleanup(prep=True)
201+
try:
202+
pth_file.create()
203+
site.addsitedir(pth_file.base_dir, set())
204+
self.assertNotIn(site.makepath(pth_file.good_dir_path)[0], sys.path)
205+
self.assertIn(pth_file.base_dir, sys.path)
206+
finally:
207+
pth_file.cleanup()
208+
209+
@unittest.skipUnless(hasattr(os, 'chflags'), 'test needs os.chflags()')
210+
def test_addsitedir_hidden_flags(self):
211+
pth_file = PthFile()
212+
pth_file.cleanup(prep=True)
213+
try:
214+
pth_file.create()
215+
st = os.stat(pth_file.file_path)
216+
os.chflags(pth_file.file_path, st.st_flags | stat.UF_HIDDEN)
217+
site.addsitedir(pth_file.base_dir, set())
218+
self.assertNotIn(site.makepath(pth_file.good_dir_path)[0], sys.path)
219+
self.assertIn(pth_file.base_dir, sys.path)
220+
finally:
221+
pth_file.cleanup()
222+
223+
# TODO: RUSTPYTHON
224+
@unittest.expectedFailure
225+
@unittest.skipUnless(sys.platform == 'win32', 'test needs Windows')
226+
@support.requires_subprocess()
227+
def test_addsitedir_hidden_file_attribute(self):
228+
pth_file = PthFile()
229+
pth_file.cleanup(prep=True)
230+
try:
231+
pth_file.create()
232+
subprocess.check_call(['attrib', '+H', pth_file.file_path])
233+
site.addsitedir(pth_file.base_dir, set())
234+
self.assertNotIn(site.makepath(pth_file.good_dir_path)[0], sys.path)
235+
self.assertIn(pth_file.base_dir, sys.path)
236+
finally:
237+
pth_file.cleanup()
238+
198239
# This tests _getuserbase, hence the double underline
199240
# to distinguish from a test for getuserbase
200241
def test__getuserbase(self):
@@ -468,10 +509,10 @@ def test_sitecustomize_executed(self):
468509
else:
469510
self.fail("sitecustomize not imported automatically")
470511

471-
@test.support.requires_resource('network')
472-
@test.support.system_must_validate_cert
473512
@unittest.skipUnless(hasattr(urllib.request, "HTTPSHandler"),
474513
'need SSL support to download license')
514+
@test.support.requires_resource('network')
515+
@test.support.system_must_validate_cert
475516
def test_license_exists_at_url(self):
476517
# This test is a bit fragile since it depends on the format of the
477518
# string displayed by license in the absence of a LICENSE file.
@@ -581,7 +622,7 @@ def _create_underpth_exe(self, lines, exe_pth=True):
581622
_pth_file = os.path.splitext(exe_file)[0] + '._pth'
582623
else:
583624
_pth_file = os.path.splitext(dll_file)[0] + '._pth'
584-
with open(_pth_file, 'w') as f:
625+
with open(_pth_file, 'w', encoding='utf8') as f:
585626
for line in lines:
586627
print(line, file=f)
587628
return exe_file
@@ -608,19 +649,33 @@ def _calc_sys_path_for_underpth_nosite(self, sys_prefix, lines):
608649
sys_path.append(abs_path)
609650
return sys_path
610651

652+
def _get_pth_lines(self, libpath: str, *, import_site: bool):
653+
pth_lines = ['fake-path-name']
654+
# include 200 lines of `libpath` in _pth lines (or fewer
655+
# if the `libpath` is long enough to get close to 32KB
656+
# see https://github.com/python/cpython/issues/113628)
657+
encoded_libpath_length = len(libpath.encode("utf-8"))
658+
repetitions = min(200, 30000 // encoded_libpath_length)
659+
if repetitions <= 2:
660+
self.skipTest(
661+
f"Python stdlib path is too long ({encoded_libpath_length:,} bytes)")
662+
pth_lines.extend(libpath for _ in range(repetitions))
663+
pth_lines.extend(['', '# comment'])
664+
if import_site:
665+
pth_lines.append('import site')
666+
return pth_lines
667+
611668
# TODO: RUSTPYTHON
612669
@unittest.expectedFailure
613670
@support.requires_subprocess()
614671
def test_underpth_basic(self):
615-
libpath = test.support.STDLIB_DIR
616-
exe_prefix = os.path.dirname(sys.executable)
617672
pth_lines = ['#.', '# ..', *sys.path, '.', '..']
618673
exe_file = self._create_underpth_exe(pth_lines)
619674
sys_path = self._calc_sys_path_for_underpth_nosite(
620675
os.path.dirname(exe_file),
621676
pth_lines)
622677

623-
output = subprocess.check_output([exe_file, '-c',
678+
output = subprocess.check_output([exe_file, '-X', 'utf8', '-c',
624679
'import sys; print("\\n".join(sys.path) if sys.flags.no_site else "")'
625680
], encoding='utf-8', errors='surrogateescape')
626681
actual_sys_path = output.rstrip().split('\n')
@@ -637,12 +692,7 @@ def test_underpth_basic(self):
637692
def test_underpth_nosite_file(self):
638693
libpath = test.support.STDLIB_DIR
639694
exe_prefix = os.path.dirname(sys.executable)
640-
pth_lines = [
641-
'fake-path-name',
642-
*[libpath for _ in range(200)],
643-
'',
644-
'# comment',
645-
]
695+
pth_lines = self._get_pth_lines(libpath, import_site=False)
646696
exe_file = self._create_underpth_exe(pth_lines)
647697
sys_path = self._calc_sys_path_for_underpth_nosite(
648698
os.path.dirname(exe_file),
@@ -668,13 +718,8 @@ def test_underpth_nosite_file(self):
668718
def test_underpth_file(self):
669719
libpath = test.support.STDLIB_DIR
670720
exe_prefix = os.path.dirname(sys.executable)
671-
exe_file = self._create_underpth_exe([
672-
'fake-path-name',
673-
*[libpath for _ in range(200)],
674-
'',
675-
'# comment',
676-
'import site'
677-
])
721+
exe_file = self._create_underpth_exe(
722+
self._get_pth_lines(libpath, import_site=True))
678723
sys_prefix = os.path.dirname(exe_file)
679724
env = os.environ.copy()
680725
env['PYTHONPATH'] = 'from-env'
@@ -695,13 +740,8 @@ def test_underpth_file(self):
695740
def test_underpth_dll_file(self):
696741
libpath = test.support.STDLIB_DIR
697742
exe_prefix = os.path.dirname(sys.executable)
698-
exe_file = self._create_underpth_exe([
699-
'fake-path-name',
700-
*[libpath for _ in range(200)],
701-
'',
702-
'# comment',
703-
'import site'
704-
], exe_pth=False)
743+
exe_file = self._create_underpth_exe(
744+
self._get_pth_lines(libpath, import_site=True), exe_pth=False)
705745
sys_prefix = os.path.dirname(exe_file)
706746
env = os.environ.copy()
707747
env['PYTHONPATH'] = 'from-env'

0 commit comments

Comments
 (0)