10
10
from test .support import os_helper
11
11
from test .support import socket_helper
12
12
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
14
14
import ast
15
15
import builtins
16
- import encodings
17
16
import glob
18
17
import io
19
18
import os
20
19
import re
21
20
import shutil
21
+ import stat
22
22
import subprocess
23
23
import sys
24
24
import sysconfig
@@ -195,6 +195,47 @@ def test_addsitedir(self):
195
195
finally :
196
196
pth_file .cleanup ()
197
197
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
+
198
239
# This tests _getuserbase, hence the double underline
199
240
# to distinguish from a test for getuserbase
200
241
def test__getuserbase (self ):
@@ -468,10 +509,10 @@ def test_sitecustomize_executed(self):
468
509
else :
469
510
self .fail ("sitecustomize not imported automatically" )
470
511
471
- @test .support .requires_resource ('network' )
472
- @test .support .system_must_validate_cert
473
512
@unittest .skipUnless (hasattr (urllib .request , "HTTPSHandler" ),
474
513
'need SSL support to download license' )
514
+ @test .support .requires_resource ('network' )
515
+ @test .support .system_must_validate_cert
475
516
def test_license_exists_at_url (self ):
476
517
# This test is a bit fragile since it depends on the format of the
477
518
# string displayed by license in the absence of a LICENSE file.
@@ -581,7 +622,7 @@ def _create_underpth_exe(self, lines, exe_pth=True):
581
622
_pth_file = os .path .splitext (exe_file )[0 ] + '._pth'
582
623
else :
583
624
_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 :
585
626
for line in lines :
586
627
print (line , file = f )
587
628
return exe_file
@@ -608,19 +649,33 @@ def _calc_sys_path_for_underpth_nosite(self, sys_prefix, lines):
608
649
sys_path .append (abs_path )
609
650
return sys_path
610
651
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
+
611
668
# TODO: RUSTPYTHON
612
669
@unittest .expectedFailure
613
670
@support .requires_subprocess ()
614
671
def test_underpth_basic (self ):
615
- libpath = test .support .STDLIB_DIR
616
- exe_prefix = os .path .dirname (sys .executable )
617
672
pth_lines = ['#.' , '# ..' , * sys .path , '.' , '..' ]
618
673
exe_file = self ._create_underpth_exe (pth_lines )
619
674
sys_path = self ._calc_sys_path_for_underpth_nosite (
620
675
os .path .dirname (exe_file ),
621
676
pth_lines )
622
677
623
- output = subprocess .check_output ([exe_file , '-c' ,
678
+ output = subprocess .check_output ([exe_file , '-X' , 'utf8' , '- c' ,
624
679
'import sys; print("\\ n".join(sys.path) if sys.flags.no_site else "")'
625
680
], encoding = 'utf-8' , errors = 'surrogateescape' )
626
681
actual_sys_path = output .rstrip ().split ('\n ' )
@@ -637,12 +692,7 @@ def test_underpth_basic(self):
637
692
def test_underpth_nosite_file (self ):
638
693
libpath = test .support .STDLIB_DIR
639
694
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 )
646
696
exe_file = self ._create_underpth_exe (pth_lines )
647
697
sys_path = self ._calc_sys_path_for_underpth_nosite (
648
698
os .path .dirname (exe_file ),
@@ -668,13 +718,8 @@ def test_underpth_nosite_file(self):
668
718
def test_underpth_file (self ):
669
719
libpath = test .support .STDLIB_DIR
670
720
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 ))
678
723
sys_prefix = os .path .dirname (exe_file )
679
724
env = os .environ .copy ()
680
725
env ['PYTHONPATH' ] = 'from-env'
@@ -695,13 +740,8 @@ def test_underpth_file(self):
695
740
def test_underpth_dll_file (self ):
696
741
libpath = test .support .STDLIB_DIR
697
742
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 )
705
745
sys_prefix = os .path .dirname (exe_file )
706
746
env = os .environ .copy ()
707
747
env ['PYTHONPATH' ] = 'from-env'
0 commit comments