1010import unittest
1111from test import support
1212from test .support import os_helper
13+ from test .support import force_not_colorized
1314from test .support .script_helper import (
1415 spawn_python , kill_python , assert_python_ok , assert_python_failure ,
1516 interpreter_requires_environment
@@ -38,8 +39,7 @@ def verify_valid_flag(self, cmd_line):
3839 self .assertNotIn (b'Traceback' , err )
3940 return out
4041
41- # TODO: RUSTPYTHON
42- @unittest .expectedFailure
42+ @support .cpython_only
4343 def test_help (self ):
4444 self .verify_valid_flag ('-h' )
4545 self .verify_valid_flag ('-?' )
@@ -50,20 +50,17 @@ def test_help(self):
5050 self .assertNotIn (b'-X dev' , out )
5151 self .assertLess (len (lines ), 50 )
5252
53- # TODO: RUSTPYTHON
54- @unittest .expectedFailure
53+ @support .cpython_only
5554 def test_help_env (self ):
5655 out = self .verify_valid_flag ('--help-env' )
5756 self .assertIn (b'PYTHONHOME' , out )
5857
59- # TODO: RUSTPYTHON
60- @unittest .expectedFailure
58+ @support .cpython_only
6159 def test_help_xoptions (self ):
6260 out = self .verify_valid_flag ('--help-xoptions' )
6361 self .assertIn (b'-X dev' , out )
6462
65- # TODO: RUSTPYTHON
66- @unittest .expectedFailure
63+ @support .cpython_only
6764 def test_help_all (self ):
6865 out = self .verify_valid_flag ('--help-all' )
6966 lines = out .splitlines ()
@@ -82,15 +79,16 @@ def test_optimize(self):
8279 def test_site_flag (self ):
8380 self .verify_valid_flag ('-S' )
8481
85- # NOTE: RUSTPYTHON version never starts with Python
86- @unittest .expectedFailure
82+ @support .cpython_only
8783 def test_version (self ):
8884 version = ('Python %d.%d' % sys .version_info [:2 ]).encode ("ascii" )
8985 for switch in '-V' , '--version' , '-VV' :
9086 rc , out , err = assert_python_ok (switch )
9187 self .assertFalse (err .startswith (version ))
9288 self .assertTrue (out .startswith (version ))
9389
90+ # TODO: RUSTPYTHON
91+ @unittest .expectedFailure
9492 def test_verbose (self ):
9593 # -v causes imports to write to stderr. If the write to
9694 # stderr itself causes an import to happen (for the output
@@ -149,8 +147,7 @@ def run_python(*args):
149147 else :
150148 self .assertEqual (err , b'' )
151149
152- # TODO: RUSTPYTHON
153- @unittest .expectedFailure
150+ @support .cpython_only
154151 def test_xoption_frozen_modules (self ):
155152 tests = {
156153 ('=on' , 'FrozenImporter' ),
@@ -165,6 +162,18 @@ def test_xoption_frozen_modules(self):
165162 res = assert_python_ok (* cmd )
166163 self .assertRegex (res .out .decode ('utf-8' ), expected )
167164
165+ @support .cpython_only
166+ def test_env_var_frozen_modules (self ):
167+ tests = {
168+ ('on' , 'FrozenImporter' ),
169+ ('off' , 'SourceFileLoader' ),
170+ }
171+ for raw , expected in tests :
172+ cmd = ['-c' , 'import os; print(os.__spec__.loader, end="")' ]
173+ with self .subTest (raw ):
174+ res = assert_python_ok (* cmd , PYTHON_FROZEN_MODULES = raw )
175+ self .assertRegex (res .out .decode ('utf-8' ), expected )
176+
168177 def test_run_module (self ):
169178 # Test expected operation of the '-m' switch
170179 # Switch needs an argument
@@ -226,8 +235,6 @@ def test_coding(self):
226235 # command line, but how subprocess does decode bytes to unicode. Python
227236 # doesn't decode the command line because Windows provides directly the
228237 # arguments as unicode (using wmain() instead of main()).
229- # TODO: RUSTPYTHON
230- @unittest .expectedFailure
231238 @unittest .skipIf (sys .platform == 'win32' ,
232239 'Windows has a native unicode API' )
233240 def test_undecodable_code (self ):
@@ -263,7 +270,6 @@ def test_undecodable_code(self):
263270 if not stdout .startswith (pattern ):
264271 raise AssertionError ("%a doesn't start with %a" % (stdout , pattern ))
265272
266- @unittest .skip ("TODO: RUSTPYTHON, thread 'main' panicked at 'unexpected invalid UTF-8 code point'" )
267273 @unittest .skipIf (sys .platform == 'win32' ,
268274 'Windows has a native unicode API' )
269275 def test_invalid_utf8_arg (self ):
@@ -275,20 +281,17 @@ def test_invalid_utf8_arg(self):
275281 # Test with default config, in the C locale, in the Python UTF-8 Mode.
276282 code = 'import sys, os; s=os.fsencode(sys.argv[1]); print(ascii(s))'
277283
278- # TODO: RUSTPYTHON
279284 def run_default (arg ):
280285 cmd = [sys .executable , '-c' , code , arg ]
281286 return subprocess .run (cmd , stdout = subprocess .PIPE , text = True )
282287
283- # TODO: RUSTPYTHON
284288 def run_c_locale (arg ):
285289 cmd = [sys .executable , '-c' , code , arg ]
286290 env = dict (os .environ )
287291 env ['LC_ALL' ] = 'C'
288292 return subprocess .run (cmd , stdout = subprocess .PIPE ,
289293 text = True , env = env )
290294
291- # TODO: RUSTPYTHON
292295 def run_utf8_mode (arg ):
293296 cmd = [sys .executable , '-X' , 'utf8' , '-c' , code , arg ]
294297 return subprocess .run (cmd , stdout = subprocess .PIPE , text = True )
@@ -402,8 +405,7 @@ def test_empty_PYTHONPATH_issue16309(self):
402405 path = ":".join(sys.path)
403406 path = path.encode("ascii", "backslashreplace")
404407 sys.stdout.buffer.write(path)"""
405- # TODO: RUSTPYTHON we must unset RUSTPYTHONPATH as well
406- rc1 , out1 , err1 = assert_python_ok ('-c' , code , PYTHONPATH = "" , RUSTPYTHONPATH = "" )
408+ rc1 , out1 , err1 = assert_python_ok ('-c' , code , PYTHONPATH = "" )
407409 rc2 , out2 , err2 = assert_python_ok ('-c' , code , __isolated = False )
408410 # regarding to Posix specification, outputs should be equal
409411 # for empty and unset PYTHONPATH
@@ -491,8 +493,9 @@ def test_stdout_flush_at_shutdown(self):
491493 rc , out , err = assert_python_failure ('-c' , code )
492494 self .assertEqual (b'' , out )
493495 self .assertEqual (120 , rc )
494- self .assertRegex (err .decode ('ascii' , 'ignore' ),
495- 'Exception ignored in.*\n OSError: .*' )
496+ self .assertIn (b'Exception ignored on flushing sys.stdout:\n '
497+ b'OSError: ' .replace (b'\n ' , os .linesep .encode ()),
498+ err )
496499
497500 def test_closed_stdout (self ):
498501 # Issue #13444: if stdout has been explicitly closed, we should
@@ -600,8 +603,7 @@ def test_del___main__(self):
600603 print ("del sys.modules['__main__']" , file = script )
601604 assert_python_ok (filename )
602605
603- # TODO: RUSTPYTHON
604- @unittest .expectedFailure
606+ @support .cpython_only
605607 def test_unknown_options (self ):
606608 rc , out , err = assert_python_failure ('-E' , '-z' )
607609 self .assertIn (b'Unknown option: -z' , err )
@@ -648,6 +650,8 @@ def test_isolatedmode(self):
648650 cwd = tmpdir )
649651 self .assertEqual (out .strip (), b"ok" )
650652
653+ # TODO: RUSTPYTHON
654+ @unittest .expectedFailure
651655 def test_sys_flags_set (self ):
652656 # Issue 31845: a startup refactoring broke reading flags from env vars
653657 for value , expected in (("" , 0 ), ("1" , 1 ), ("text" , 1 ), ("2" , 2 )):
@@ -657,15 +661,13 @@ def test_sys_flags_set(self):
657661 PYTHONDONTWRITEBYTECODE = value ,
658662 PYTHONVERBOSE = value ,
659663 )
660- dont_write_bytecode = int (bool (value ))
664+ expected_bool = int (bool (value ))
661665 code = (
662666 "import sys; "
663667 "sys.stderr.write(str(sys.flags)); "
664668 f"""sys.exit(not (
665- sys.flags.debug == sys.flags.optimize ==
666- sys.flags.verbose ==
667- { expected }
668- and sys.flags.dont_write_bytecode == { dont_write_bytecode }
669+ sys.flags.optimize == sys.flags.verbose == { expected }
670+ and sys.flags.debug == sys.flags.dont_write_bytecode == { expected_bool }
669671 ))"""
670672 )
671673 with self .subTest (envar_value = value ):
@@ -718,8 +720,7 @@ def run_xdev(self, *args, check_exitcode=True, xdev=True):
718720 self .assertEqual (proc .returncode , 0 , proc )
719721 return proc .stdout .rstrip ()
720722
721- # TODO: RUSTPYTHON
722- @unittest .expectedFailure
723+ @support .cpython_only
723724 def test_xdev (self ):
724725 # sys.flags.dev_mode
725726 code = "import sys; print(sys.flags.dev_mode)"
@@ -756,15 +757,17 @@ def test_xdev(self):
756757
757758 # Memory allocator debug hooks
758759 try :
759- import _testcapi
760+ import _testinternalcapi
760761 except ImportError :
761762 pass
762763 else :
763- code = "import _testcapi ; print(_testcapi .pymem_getallocatorsname())"
764+ code = "import _testinternalcapi ; print(_testinternalcapi .pymem_getallocatorsname())"
764765 with support .SuppressCrashReport ():
765766 out = self .run_xdev ("-c" , code , check_exitcode = False )
766767 if support .with_pymalloc ():
767768 alloc_name = "pymalloc_debug"
769+ elif support .Py_GIL_DISABLED :
770+ alloc_name = "mimalloc_debug"
768771 else :
769772 alloc_name = "malloc_debug"
770773 self .assertEqual (out , alloc_name )
@@ -824,7 +827,7 @@ def test_warnings_filter_precedence(self):
824827 self .assertEqual (out , expected_filters )
825828
826829 def check_pythonmalloc (self , env_var , name ):
827- code = 'import _testcapi ; print(_testcapi .pymem_getallocatorsname())'
830+ code = 'import _testinternalcapi ; print(_testinternalcapi .pymem_getallocatorsname())'
828831 env = dict (os .environ )
829832 env .pop ('PYTHONDEVMODE' , None )
830833 if env_var is not None :
@@ -840,12 +843,16 @@ def check_pythonmalloc(self, env_var, name):
840843 self .assertEqual (proc .stdout .rstrip (), name )
841844 self .assertEqual (proc .returncode , 0 )
842845
843- # TODO: RUSTPYTHON
844- @unittest .expectedFailure
846+ @support .cpython_only
845847 def test_pythonmalloc (self ):
846848 # Test the PYTHONMALLOC environment variable
849+ malloc = not support .Py_GIL_DISABLED
847850 pymalloc = support .with_pymalloc ()
848- if pymalloc :
851+ mimalloc = support .with_mimalloc ()
852+ if support .Py_GIL_DISABLED :
853+ default_name = 'mimalloc_debug' if support .Py_DEBUG else 'mimalloc'
854+ default_name_debug = 'mimalloc_debug'
855+ elif pymalloc :
849856 default_name = 'pymalloc_debug' if support .Py_DEBUG else 'pymalloc'
850857 default_name_debug = 'pymalloc_debug'
851858 else :
@@ -855,14 +862,22 @@ def test_pythonmalloc(self):
855862 tests = [
856863 (None , default_name ),
857864 ('debug' , default_name_debug ),
858- ('malloc' , 'malloc' ),
859- ('malloc_debug' , 'malloc_debug' ),
860865 ]
866+ if malloc :
867+ tests .extend ([
868+ ('malloc' , 'malloc' ),
869+ ('malloc_debug' , 'malloc_debug' ),
870+ ])
861871 if pymalloc :
862872 tests .extend ((
863873 ('pymalloc' , 'pymalloc' ),
864874 ('pymalloc_debug' , 'pymalloc_debug' ),
865875 ))
876+ if mimalloc :
877+ tests .extend ((
878+ ('mimalloc' , 'mimalloc' ),
879+ ('mimalloc_debug' , 'mimalloc_debug' ),
880+ ))
866881
867882 for env_var , name in tests :
868883 with self .subTest (env_var = env_var , name = name ):
@@ -888,6 +903,51 @@ def test_pythondevmode_env(self):
888903 self .assertEqual (proc .stdout .rstrip (), 'True' )
889904 self .assertEqual (proc .returncode , 0 , proc )
890905
906+ # TODO: RUSTPYTHON
907+ @unittest .expectedFailure
908+ def test_python_gil (self ):
909+ cases = [
910+ # (env, opt, expected, msg)
911+ ('1' , None , '1' , "PYTHON_GIL=1" ),
912+ (None , '1' , '1' , "-X gil=1" ),
913+ ]
914+
915+ if support .Py_GIL_DISABLED :
916+ cases .extend (
917+ [
918+ (None , None , 'None' , "no options set" ),
919+ ('0' , None , '0' , "PYTHON_GIL=0" ),
920+ ('1' , '0' , '0' , "-X gil=0 overrides PYTHON_GIL=1" ),
921+ (None , '0' , '0' , "-X gil=0" ),
922+ ]
923+ )
924+ else :
925+ cases .extend (
926+ [
927+ (None , None , '1' , '-X gil=0 (unsupported by this build)' ),
928+ ('1' , None , '1' , 'PYTHON_GIL=0 (unsupported by this build)' ),
929+ ]
930+ )
931+ code = "import sys; print(sys.flags.gil)"
932+ environ = dict (os .environ )
933+
934+ for env , opt , expected , msg in cases :
935+ with self .subTest (msg , env = env , opt = opt ):
936+ environ .pop ('PYTHON_GIL' , None )
937+ if env is not None :
938+ environ ['PYTHON_GIL' ] = env
939+ extra_args = []
940+ if opt is not None :
941+ extra_args = ['-X' , f'gil={ opt } ' ]
942+
943+ proc = subprocess .run ([sys .executable , * extra_args , '-c' , code ],
944+ stdout = subprocess .PIPE ,
945+ stderr = subprocess .PIPE ,
946+ text = True , env = environ )
947+ self .assertEqual (proc .returncode , 0 , proc )
948+ self .assertEqual (proc .stdout .rstrip (), expected )
949+ self .assertEqual (proc .stderr , '' )
950+
891951 @unittest .skipUnless (sys .platform == 'win32' ,
892952 'bpo-32457 only applies on Windows' )
893953 def test_argv0_normalization (self ):
@@ -900,8 +960,7 @@ def test_argv0_normalization(self):
900960 self .assertEqual (proc .returncode , 0 , proc )
901961 self .assertEqual (proc .stdout .strip (), b'0' )
902962
903- # TODO: RUSTPYTHON
904- @unittest .expectedFailure
963+ @support .cpython_only
905964 def test_parsing_error (self ):
906965 args = [sys .executable , '-I' , '--unknown-option' ]
907966 proc = subprocess .run (args ,
@@ -924,11 +983,8 @@ def test_int_max_str_digits(self):
924983 assert_python_failure ('-c' , code , PYTHONINTMAXSTRDIGITS = 'foo' )
925984 assert_python_failure ('-c' , code , PYTHONINTMAXSTRDIGITS = '100' )
926985
927- def res2int (res ):
928- out = res .out .strip ().decode ("utf-8" )
929- return tuple (int (i ) for i in out .split ())
930-
931986 res = assert_python_ok ('-c' , code )
987+ res2int = self .res2int
932988 current_max = sys .get_int_max_str_digits ()
933989 self .assertEqual (res2int (res ), (current_max , current_max ))
934990 res = assert_python_ok ('-X' , 'int_max_str_digits=0' , '-c' , code )
@@ -948,6 +1004,30 @@ def res2int(res):
9481004 )
9491005 self .assertEqual (res2int (res ), (6000 , 6000 ))
9501006
1007+ # TODO: RUSTPYTHON
1008+ @unittest .expectedFailure
1009+ def test_cpu_count (self ):
1010+ code = "import os; print(os.cpu_count(), os.process_cpu_count())"
1011+ res = assert_python_ok ('-X' , 'cpu_count=4321' , '-c' , code )
1012+ self .assertEqual (self .res2int (res ), (4321 , 4321 ))
1013+ res = assert_python_ok ('-c' , code , PYTHON_CPU_COUNT = '1234' )
1014+ self .assertEqual (self .res2int (res ), (1234 , 1234 ))
1015+
1016+ # TODO: RUSTPYTHON
1017+ @unittest .expectedFailure
1018+ def test_cpu_count_default (self ):
1019+ code = "import os; print(os.cpu_count(), os.process_cpu_count())"
1020+ res = assert_python_ok ('-X' , 'cpu_count=default' , '-c' , code )
1021+ self .assertEqual (self .res2int (res ), (os .cpu_count (), os .process_cpu_count ()))
1022+ res = assert_python_ok ('-X' , 'cpu_count=default' , '-c' , code , PYTHON_CPU_COUNT = '1234' )
1023+ self .assertEqual (self .res2int (res ), (os .cpu_count (), os .process_cpu_count ()))
1024+ es = assert_python_ok ('-c' , code , PYTHON_CPU_COUNT = 'default' )
1025+ self .assertEqual (self .res2int (res ), (os .cpu_count (), os .process_cpu_count ()))
1026+
1027+ def res2int (self , res ):
1028+ out = res .out .strip ().decode ("utf-8" )
1029+ return tuple (int (i ) for i in out .split ())
1030+
9511031
9521032@unittest .skipIf (interpreter_requires_environment (),
9531033 'Cannot run -I tests when PYTHON env vars are required.' )
@@ -990,6 +1070,7 @@ def test_sys_flags_not_set(self):
9901070
9911071
9921072class SyntaxErrorTests (unittest .TestCase ):
1073+ @force_not_colorized
9931074 def check_string (self , code ):
9941075 proc = subprocess .run ([sys .executable , "-" ], input = code ,
9951076 stdout = subprocess .PIPE , stderr = subprocess .PIPE )
0 commit comments