17db96d56Sopenharmony_ci# Tests invocation of the interpreter with various command line arguments 27db96d56Sopenharmony_ci# Most tests are executed with environment variables ignored 37db96d56Sopenharmony_ci# See test_cmd_line_script.py for testing of script execution 47db96d56Sopenharmony_ci 57db96d56Sopenharmony_ciimport os 67db96d56Sopenharmony_ciimport subprocess 77db96d56Sopenharmony_ciimport sys 87db96d56Sopenharmony_ciimport tempfile 97db96d56Sopenharmony_ciimport textwrap 107db96d56Sopenharmony_ciimport unittest 117db96d56Sopenharmony_cifrom test import support 127db96d56Sopenharmony_cifrom test.support import os_helper 137db96d56Sopenharmony_cifrom test.support.script_helper import ( 147db96d56Sopenharmony_ci spawn_python, kill_python, assert_python_ok, assert_python_failure, 157db96d56Sopenharmony_ci interpreter_requires_environment 167db96d56Sopenharmony_ci) 177db96d56Sopenharmony_ci 187db96d56Sopenharmony_ciif not support.has_subprocess_support: 197db96d56Sopenharmony_ci raise unittest.SkipTest("test module requires subprocess") 207db96d56Sopenharmony_ci 217db96d56Sopenharmony_ci# Debug build? 227db96d56Sopenharmony_ciPy_DEBUG = hasattr(sys, "gettotalrefcount") 237db96d56Sopenharmony_ci 247db96d56Sopenharmony_ci 257db96d56Sopenharmony_ci# XXX (ncoghlan): Move to script_helper and make consistent with run_python 267db96d56Sopenharmony_cidef _kill_python_and_exit_code(p): 277db96d56Sopenharmony_ci data = kill_python(p) 287db96d56Sopenharmony_ci returncode = p.wait() 297db96d56Sopenharmony_ci return data, returncode 307db96d56Sopenharmony_ci 317db96d56Sopenharmony_ci 327db96d56Sopenharmony_ciclass CmdLineTest(unittest.TestCase): 337db96d56Sopenharmony_ci def test_directories(self): 347db96d56Sopenharmony_ci assert_python_failure('.') 357db96d56Sopenharmony_ci assert_python_failure('< .') 367db96d56Sopenharmony_ci 377db96d56Sopenharmony_ci def verify_valid_flag(self, cmd_line): 387db96d56Sopenharmony_ci rc, out, err = assert_python_ok(cmd_line) 397db96d56Sopenharmony_ci self.assertTrue(out == b'' or out.endswith(b'\n')) 407db96d56Sopenharmony_ci self.assertNotIn(b'Traceback', out) 417db96d56Sopenharmony_ci self.assertNotIn(b'Traceback', err) 427db96d56Sopenharmony_ci return out 437db96d56Sopenharmony_ci 447db96d56Sopenharmony_ci def test_help(self): 457db96d56Sopenharmony_ci self.verify_valid_flag('-h') 467db96d56Sopenharmony_ci self.verify_valid_flag('-?') 477db96d56Sopenharmony_ci out = self.verify_valid_flag('--help') 487db96d56Sopenharmony_ci lines = out.splitlines() 497db96d56Sopenharmony_ci self.assertIn(b'usage', lines[0]) 507db96d56Sopenharmony_ci self.assertNotIn(b'PYTHONHOME', out) 517db96d56Sopenharmony_ci self.assertNotIn(b'-X dev', out) 527db96d56Sopenharmony_ci self.assertLess(len(lines), 50) 537db96d56Sopenharmony_ci 547db96d56Sopenharmony_ci def test_help_env(self): 557db96d56Sopenharmony_ci out = self.verify_valid_flag('--help-env') 567db96d56Sopenharmony_ci self.assertIn(b'PYTHONHOME', out) 577db96d56Sopenharmony_ci 587db96d56Sopenharmony_ci def test_help_xoptions(self): 597db96d56Sopenharmony_ci out = self.verify_valid_flag('--help-xoptions') 607db96d56Sopenharmony_ci self.assertIn(b'-X dev', out) 617db96d56Sopenharmony_ci 627db96d56Sopenharmony_ci def test_help_all(self): 637db96d56Sopenharmony_ci out = self.verify_valid_flag('--help-all') 647db96d56Sopenharmony_ci lines = out.splitlines() 657db96d56Sopenharmony_ci self.assertIn(b'usage', lines[0]) 667db96d56Sopenharmony_ci self.assertIn(b'PYTHONHOME', out) 677db96d56Sopenharmony_ci self.assertIn(b'-X dev', out) 687db96d56Sopenharmony_ci 697db96d56Sopenharmony_ci # The first line contains the program name, 707db96d56Sopenharmony_ci # but the rest should be ASCII-only 717db96d56Sopenharmony_ci b''.join(lines[1:]).decode('ascii') 727db96d56Sopenharmony_ci 737db96d56Sopenharmony_ci def test_optimize(self): 747db96d56Sopenharmony_ci self.verify_valid_flag('-O') 757db96d56Sopenharmony_ci self.verify_valid_flag('-OO') 767db96d56Sopenharmony_ci 777db96d56Sopenharmony_ci def test_site_flag(self): 787db96d56Sopenharmony_ci self.verify_valid_flag('-S') 797db96d56Sopenharmony_ci 807db96d56Sopenharmony_ci def test_version(self): 817db96d56Sopenharmony_ci version = ('Python %d.%d' % sys.version_info[:2]).encode("ascii") 827db96d56Sopenharmony_ci for switch in '-V', '--version', '-VV': 837db96d56Sopenharmony_ci rc, out, err = assert_python_ok(switch) 847db96d56Sopenharmony_ci self.assertFalse(err.startswith(version)) 857db96d56Sopenharmony_ci self.assertTrue(out.startswith(version)) 867db96d56Sopenharmony_ci 877db96d56Sopenharmony_ci def test_verbose(self): 887db96d56Sopenharmony_ci # -v causes imports to write to stderr. If the write to 897db96d56Sopenharmony_ci # stderr itself causes an import to happen (for the output 907db96d56Sopenharmony_ci # codec), a recursion loop can occur. 917db96d56Sopenharmony_ci rc, out, err = assert_python_ok('-v') 927db96d56Sopenharmony_ci self.assertNotIn(b'stack overflow', err) 937db96d56Sopenharmony_ci rc, out, err = assert_python_ok('-vv') 947db96d56Sopenharmony_ci self.assertNotIn(b'stack overflow', err) 957db96d56Sopenharmony_ci 967db96d56Sopenharmony_ci @unittest.skipIf(interpreter_requires_environment(), 977db96d56Sopenharmony_ci 'Cannot run -E tests when PYTHON env vars are required.') 987db96d56Sopenharmony_ci def test_xoptions(self): 997db96d56Sopenharmony_ci def get_xoptions(*args): 1007db96d56Sopenharmony_ci # use subprocess module directly because test.support.script_helper adds 1017db96d56Sopenharmony_ci # "-X faulthandler" to the command line 1027db96d56Sopenharmony_ci args = (sys.executable, '-E') + args 1037db96d56Sopenharmony_ci args += ('-c', 'import sys; print(sys._xoptions)') 1047db96d56Sopenharmony_ci out = subprocess.check_output(args) 1057db96d56Sopenharmony_ci opts = eval(out.splitlines()[0]) 1067db96d56Sopenharmony_ci return opts 1077db96d56Sopenharmony_ci 1087db96d56Sopenharmony_ci opts = get_xoptions() 1097db96d56Sopenharmony_ci self.assertEqual(opts, {}) 1107db96d56Sopenharmony_ci 1117db96d56Sopenharmony_ci opts = get_xoptions('-Xa', '-Xb=c,d=e') 1127db96d56Sopenharmony_ci self.assertEqual(opts, {'a': True, 'b': 'c,d=e'}) 1137db96d56Sopenharmony_ci 1147db96d56Sopenharmony_ci def test_showrefcount(self): 1157db96d56Sopenharmony_ci def run_python(*args): 1167db96d56Sopenharmony_ci # this is similar to assert_python_ok but doesn't strip 1177db96d56Sopenharmony_ci # the refcount from stderr. It can be replaced once 1187db96d56Sopenharmony_ci # assert_python_ok stops doing that. 1197db96d56Sopenharmony_ci cmd = [sys.executable] 1207db96d56Sopenharmony_ci cmd.extend(args) 1217db96d56Sopenharmony_ci PIPE = subprocess.PIPE 1227db96d56Sopenharmony_ci p = subprocess.Popen(cmd, stdout=PIPE, stderr=PIPE) 1237db96d56Sopenharmony_ci out, err = p.communicate() 1247db96d56Sopenharmony_ci p.stdout.close() 1257db96d56Sopenharmony_ci p.stderr.close() 1267db96d56Sopenharmony_ci rc = p.returncode 1277db96d56Sopenharmony_ci self.assertEqual(rc, 0) 1287db96d56Sopenharmony_ci return rc, out, err 1297db96d56Sopenharmony_ci code = 'import sys; print(sys._xoptions)' 1307db96d56Sopenharmony_ci # normally the refcount is hidden 1317db96d56Sopenharmony_ci rc, out, err = run_python('-c', code) 1327db96d56Sopenharmony_ci self.assertEqual(out.rstrip(), b'{}') 1337db96d56Sopenharmony_ci self.assertEqual(err, b'') 1347db96d56Sopenharmony_ci # "-X showrefcount" shows the refcount, but only in debug builds 1357db96d56Sopenharmony_ci rc, out, err = run_python('-I', '-X', 'showrefcount', '-c', code) 1367db96d56Sopenharmony_ci self.assertEqual(out.rstrip(), b"{'showrefcount': True}") 1377db96d56Sopenharmony_ci if Py_DEBUG: 1387db96d56Sopenharmony_ci # bpo-46417: Tolerate negative reference count which can occur 1397db96d56Sopenharmony_ci # because of bugs in C extensions. This test is only about checking 1407db96d56Sopenharmony_ci # the showrefcount feature. 1417db96d56Sopenharmony_ci self.assertRegex(err, br'^\[-?\d+ refs, \d+ blocks\]') 1427db96d56Sopenharmony_ci else: 1437db96d56Sopenharmony_ci self.assertEqual(err, b'') 1447db96d56Sopenharmony_ci 1457db96d56Sopenharmony_ci def test_xoption_frozen_modules(self): 1467db96d56Sopenharmony_ci tests = { 1477db96d56Sopenharmony_ci ('=on', 'FrozenImporter'), 1487db96d56Sopenharmony_ci ('=off', 'SourceFileLoader'), 1497db96d56Sopenharmony_ci ('=', 'FrozenImporter'), 1507db96d56Sopenharmony_ci ('', 'FrozenImporter'), 1517db96d56Sopenharmony_ci } 1527db96d56Sopenharmony_ci for raw, expected in tests: 1537db96d56Sopenharmony_ci cmd = ['-X', f'frozen_modules{raw}', 1547db96d56Sopenharmony_ci '-c', 'import os; print(os.__spec__.loader, end="")'] 1557db96d56Sopenharmony_ci with self.subTest(raw): 1567db96d56Sopenharmony_ci res = assert_python_ok(*cmd) 1577db96d56Sopenharmony_ci self.assertRegex(res.out.decode('utf-8'), expected) 1587db96d56Sopenharmony_ci 1597db96d56Sopenharmony_ci def test_run_module(self): 1607db96d56Sopenharmony_ci # Test expected operation of the '-m' switch 1617db96d56Sopenharmony_ci # Switch needs an argument 1627db96d56Sopenharmony_ci assert_python_failure('-m') 1637db96d56Sopenharmony_ci # Check we get an error for a nonexistent module 1647db96d56Sopenharmony_ci assert_python_failure('-m', 'fnord43520xyz') 1657db96d56Sopenharmony_ci # Check the runpy module also gives an error for 1667db96d56Sopenharmony_ci # a nonexistent module 1677db96d56Sopenharmony_ci assert_python_failure('-m', 'runpy', 'fnord43520xyz') 1687db96d56Sopenharmony_ci # All good if module is located and run successfully 1697db96d56Sopenharmony_ci assert_python_ok('-m', 'timeit', '-n', '1') 1707db96d56Sopenharmony_ci 1717db96d56Sopenharmony_ci def test_run_module_bug1764407(self): 1727db96d56Sopenharmony_ci # -m and -i need to play well together 1737db96d56Sopenharmony_ci # Runs the timeit module and checks the __main__ 1747db96d56Sopenharmony_ci # namespace has been populated appropriately 1757db96d56Sopenharmony_ci p = spawn_python('-i', '-m', 'timeit', '-n', '1') 1767db96d56Sopenharmony_ci p.stdin.write(b'Timer\n') 1777db96d56Sopenharmony_ci p.stdin.write(b'exit()\n') 1787db96d56Sopenharmony_ci data = kill_python(p) 1797db96d56Sopenharmony_ci self.assertTrue(data.find(b'1 loop') != -1) 1807db96d56Sopenharmony_ci self.assertTrue(data.find(b'__main__.Timer') != -1) 1817db96d56Sopenharmony_ci 1827db96d56Sopenharmony_ci def test_relativedir_bug46421(self): 1837db96d56Sopenharmony_ci # Test `python -m unittest` with a relative directory beginning with ./ 1847db96d56Sopenharmony_ci # Note: We have to switch to the project's top module's directory, as per 1857db96d56Sopenharmony_ci # the python unittest wiki. We will switch back when we are done. 1867db96d56Sopenharmony_ci projectlibpath = os.path.dirname(__file__).removesuffix("test") 1877db96d56Sopenharmony_ci with os_helper.change_cwd(projectlibpath): 1887db96d56Sopenharmony_ci # Testing with and without ./ 1897db96d56Sopenharmony_ci assert_python_ok('-m', 'unittest', "test/test_longexp.py") 1907db96d56Sopenharmony_ci assert_python_ok('-m', 'unittest', "./test/test_longexp.py") 1917db96d56Sopenharmony_ci 1927db96d56Sopenharmony_ci def test_run_code(self): 1937db96d56Sopenharmony_ci # Test expected operation of the '-c' switch 1947db96d56Sopenharmony_ci # Switch needs an argument 1957db96d56Sopenharmony_ci assert_python_failure('-c') 1967db96d56Sopenharmony_ci # Check we get an error for an uncaught exception 1977db96d56Sopenharmony_ci assert_python_failure('-c', 'raise Exception') 1987db96d56Sopenharmony_ci # All good if execution is successful 1997db96d56Sopenharmony_ci assert_python_ok('-c', 'pass') 2007db96d56Sopenharmony_ci 2017db96d56Sopenharmony_ci @unittest.skipUnless(os_helper.FS_NONASCII, 'need os_helper.FS_NONASCII') 2027db96d56Sopenharmony_ci def test_non_ascii(self): 2037db96d56Sopenharmony_ci # Test handling of non-ascii data 2047db96d56Sopenharmony_ci command = ("assert(ord(%r) == %s)" 2057db96d56Sopenharmony_ci % (os_helper.FS_NONASCII, ord(os_helper.FS_NONASCII))) 2067db96d56Sopenharmony_ci assert_python_ok('-c', command) 2077db96d56Sopenharmony_ci 2087db96d56Sopenharmony_ci @unittest.skipUnless(os_helper.FS_NONASCII, 'need os_helper.FS_NONASCII') 2097db96d56Sopenharmony_ci def test_coding(self): 2107db96d56Sopenharmony_ci # bpo-32381: the -c command ignores the coding cookie 2117db96d56Sopenharmony_ci ch = os_helper.FS_NONASCII 2127db96d56Sopenharmony_ci cmd = f"# coding: latin1\nprint(ascii('{ch}'))" 2137db96d56Sopenharmony_ci res = assert_python_ok('-c', cmd) 2147db96d56Sopenharmony_ci self.assertEqual(res.out.rstrip(), ascii(ch).encode('ascii')) 2157db96d56Sopenharmony_ci 2167db96d56Sopenharmony_ci # On Windows, pass bytes to subprocess doesn't test how Python decodes the 2177db96d56Sopenharmony_ci # command line, but how subprocess does decode bytes to unicode. Python 2187db96d56Sopenharmony_ci # doesn't decode the command line because Windows provides directly the 2197db96d56Sopenharmony_ci # arguments as unicode (using wmain() instead of main()). 2207db96d56Sopenharmony_ci @unittest.skipIf(sys.platform == 'win32', 2217db96d56Sopenharmony_ci 'Windows has a native unicode API') 2227db96d56Sopenharmony_ci def test_undecodable_code(self): 2237db96d56Sopenharmony_ci undecodable = b"\xff" 2247db96d56Sopenharmony_ci env = os.environ.copy() 2257db96d56Sopenharmony_ci # Use C locale to get ascii for the locale encoding 2267db96d56Sopenharmony_ci env['LC_ALL'] = 'C' 2277db96d56Sopenharmony_ci env['PYTHONCOERCECLOCALE'] = '0' 2287db96d56Sopenharmony_ci code = ( 2297db96d56Sopenharmony_ci b'import locale; ' 2307db96d56Sopenharmony_ci b'print(ascii("' + undecodable + b'"), ' 2317db96d56Sopenharmony_ci b'locale.getencoding())') 2327db96d56Sopenharmony_ci p = subprocess.Popen( 2337db96d56Sopenharmony_ci [sys.executable, "-c", code], 2347db96d56Sopenharmony_ci stdout=subprocess.PIPE, stderr=subprocess.STDOUT, 2357db96d56Sopenharmony_ci env=env) 2367db96d56Sopenharmony_ci stdout, stderr = p.communicate() 2377db96d56Sopenharmony_ci if p.returncode == 1: 2387db96d56Sopenharmony_ci # _Py_char2wchar() decoded b'\xff' as '\udcff' (b'\xff' is not 2397db96d56Sopenharmony_ci # decodable from ASCII) and run_command() failed on 2407db96d56Sopenharmony_ci # PyUnicode_AsUTF8String(). This is the expected behaviour on 2417db96d56Sopenharmony_ci # Linux. 2427db96d56Sopenharmony_ci pattern = b"Unable to decode the command from the command line:" 2437db96d56Sopenharmony_ci elif p.returncode == 0: 2447db96d56Sopenharmony_ci # _Py_char2wchar() decoded b'\xff' as '\xff' even if the locale is 2457db96d56Sopenharmony_ci # C and the locale encoding is ASCII. It occurs on FreeBSD, Solaris 2467db96d56Sopenharmony_ci # and Mac OS X. 2477db96d56Sopenharmony_ci pattern = b"'\\xff' " 2487db96d56Sopenharmony_ci # The output is followed by the encoding name, an alias to ASCII. 2497db96d56Sopenharmony_ci # Examples: "US-ASCII" or "646" (ISO 646, on Solaris). 2507db96d56Sopenharmony_ci else: 2517db96d56Sopenharmony_ci raise AssertionError("Unknown exit code: %s, output=%a" % (p.returncode, stdout)) 2527db96d56Sopenharmony_ci if not stdout.startswith(pattern): 2537db96d56Sopenharmony_ci raise AssertionError("%a doesn't start with %a" % (stdout, pattern)) 2547db96d56Sopenharmony_ci 2557db96d56Sopenharmony_ci @unittest.skipIf(sys.platform == 'win32', 2567db96d56Sopenharmony_ci 'Windows has a native unicode API') 2577db96d56Sopenharmony_ci def test_invalid_utf8_arg(self): 2587db96d56Sopenharmony_ci # bpo-35883: Py_DecodeLocale() must escape b'\xfd\xbf\xbf\xbb\xba\xba' 2597db96d56Sopenharmony_ci # byte sequence with surrogateescape rather than decoding it as the 2607db96d56Sopenharmony_ci # U+7fffbeba character which is outside the [U+0000; U+10ffff] range of 2617db96d56Sopenharmony_ci # Python Unicode characters. 2627db96d56Sopenharmony_ci # 2637db96d56Sopenharmony_ci # Test with default config, in the C locale, in the Python UTF-8 Mode. 2647db96d56Sopenharmony_ci code = 'import sys, os; s=os.fsencode(sys.argv[1]); print(ascii(s))' 2657db96d56Sopenharmony_ci 2667db96d56Sopenharmony_ci def run_default(arg): 2677db96d56Sopenharmony_ci cmd = [sys.executable, '-c', code, arg] 2687db96d56Sopenharmony_ci return subprocess.run(cmd, stdout=subprocess.PIPE, text=True) 2697db96d56Sopenharmony_ci 2707db96d56Sopenharmony_ci def run_c_locale(arg): 2717db96d56Sopenharmony_ci cmd = [sys.executable, '-c', code, arg] 2727db96d56Sopenharmony_ci env = dict(os.environ) 2737db96d56Sopenharmony_ci env['LC_ALL'] = 'C' 2747db96d56Sopenharmony_ci return subprocess.run(cmd, stdout=subprocess.PIPE, 2757db96d56Sopenharmony_ci text=True, env=env) 2767db96d56Sopenharmony_ci 2777db96d56Sopenharmony_ci def run_utf8_mode(arg): 2787db96d56Sopenharmony_ci cmd = [sys.executable, '-X', 'utf8', '-c', code, arg] 2797db96d56Sopenharmony_ci return subprocess.run(cmd, stdout=subprocess.PIPE, text=True) 2807db96d56Sopenharmony_ci 2817db96d56Sopenharmony_ci valid_utf8 = 'e:\xe9, euro:\u20ac, non-bmp:\U0010ffff'.encode('utf-8') 2827db96d56Sopenharmony_ci # invalid UTF-8 byte sequences with a valid UTF-8 sequence 2837db96d56Sopenharmony_ci # in the middle. 2847db96d56Sopenharmony_ci invalid_utf8 = ( 2857db96d56Sopenharmony_ci b'\xff' # invalid byte 2867db96d56Sopenharmony_ci b'\xc3\xff' # invalid byte sequence 2877db96d56Sopenharmony_ci b'\xc3\xa9' # valid utf-8: U+00E9 character 2887db96d56Sopenharmony_ci b'\xed\xa0\x80' # lone surrogate character (invalid) 2897db96d56Sopenharmony_ci b'\xfd\xbf\xbf\xbb\xba\xba' # character outside [U+0000; U+10ffff] 2907db96d56Sopenharmony_ci ) 2917db96d56Sopenharmony_ci test_args = [valid_utf8, invalid_utf8] 2927db96d56Sopenharmony_ci 2937db96d56Sopenharmony_ci for run_cmd in (run_default, run_c_locale, run_utf8_mode): 2947db96d56Sopenharmony_ci with self.subTest(run_cmd=run_cmd): 2957db96d56Sopenharmony_ci for arg in test_args: 2967db96d56Sopenharmony_ci proc = run_cmd(arg) 2977db96d56Sopenharmony_ci self.assertEqual(proc.stdout.rstrip(), ascii(arg)) 2987db96d56Sopenharmony_ci 2997db96d56Sopenharmony_ci @unittest.skipUnless((sys.platform == 'darwin' or 3007db96d56Sopenharmony_ci support.is_android), 'test specific to Mac OS X and Android') 3017db96d56Sopenharmony_ci def test_osx_android_utf8(self): 3027db96d56Sopenharmony_ci text = 'e:\xe9, euro:\u20ac, non-bmp:\U0010ffff'.encode('utf-8') 3037db96d56Sopenharmony_ci code = "import sys; print(ascii(sys.argv[1]))" 3047db96d56Sopenharmony_ci 3057db96d56Sopenharmony_ci decoded = text.decode('utf-8', 'surrogateescape') 3067db96d56Sopenharmony_ci expected = ascii(decoded).encode('ascii') + b'\n' 3077db96d56Sopenharmony_ci 3087db96d56Sopenharmony_ci env = os.environ.copy() 3097db96d56Sopenharmony_ci # C locale gives ASCII locale encoding, but Python uses UTF-8 3107db96d56Sopenharmony_ci # to parse the command line arguments on Mac OS X and Android. 3117db96d56Sopenharmony_ci env['LC_ALL'] = 'C' 3127db96d56Sopenharmony_ci 3137db96d56Sopenharmony_ci p = subprocess.Popen( 3147db96d56Sopenharmony_ci (sys.executable, "-c", code, text), 3157db96d56Sopenharmony_ci stdout=subprocess.PIPE, 3167db96d56Sopenharmony_ci env=env) 3177db96d56Sopenharmony_ci stdout, stderr = p.communicate() 3187db96d56Sopenharmony_ci self.assertEqual(stdout, expected) 3197db96d56Sopenharmony_ci self.assertEqual(p.returncode, 0) 3207db96d56Sopenharmony_ci 3217db96d56Sopenharmony_ci def test_non_interactive_output_buffering(self): 3227db96d56Sopenharmony_ci code = textwrap.dedent(""" 3237db96d56Sopenharmony_ci import sys 3247db96d56Sopenharmony_ci out = sys.stdout 3257db96d56Sopenharmony_ci print(out.isatty(), out.write_through, out.line_buffering) 3267db96d56Sopenharmony_ci err = sys.stderr 3277db96d56Sopenharmony_ci print(err.isatty(), err.write_through, err.line_buffering) 3287db96d56Sopenharmony_ci """) 3297db96d56Sopenharmony_ci args = [sys.executable, '-c', code] 3307db96d56Sopenharmony_ci proc = subprocess.run(args, stdout=subprocess.PIPE, 3317db96d56Sopenharmony_ci stderr=subprocess.PIPE, text=True, check=True) 3327db96d56Sopenharmony_ci self.assertEqual(proc.stdout, 3337db96d56Sopenharmony_ci 'False False False\n' 3347db96d56Sopenharmony_ci 'False False True\n') 3357db96d56Sopenharmony_ci 3367db96d56Sopenharmony_ci def test_unbuffered_output(self): 3377db96d56Sopenharmony_ci # Test expected operation of the '-u' switch 3387db96d56Sopenharmony_ci for stream in ('stdout', 'stderr'): 3397db96d56Sopenharmony_ci # Binary is unbuffered 3407db96d56Sopenharmony_ci code = ("import os, sys; sys.%s.buffer.write(b'x'); os._exit(0)" 3417db96d56Sopenharmony_ci % stream) 3427db96d56Sopenharmony_ci rc, out, err = assert_python_ok('-u', '-c', code) 3437db96d56Sopenharmony_ci data = err if stream == 'stderr' else out 3447db96d56Sopenharmony_ci self.assertEqual(data, b'x', "binary %s not unbuffered" % stream) 3457db96d56Sopenharmony_ci # Text is unbuffered 3467db96d56Sopenharmony_ci code = ("import os, sys; sys.%s.write('x'); os._exit(0)" 3477db96d56Sopenharmony_ci % stream) 3487db96d56Sopenharmony_ci rc, out, err = assert_python_ok('-u', '-c', code) 3497db96d56Sopenharmony_ci data = err if stream == 'stderr' else out 3507db96d56Sopenharmony_ci self.assertEqual(data, b'x', "text %s not unbuffered" % stream) 3517db96d56Sopenharmony_ci 3527db96d56Sopenharmony_ci def test_unbuffered_input(self): 3537db96d56Sopenharmony_ci # sys.stdin still works with '-u' 3547db96d56Sopenharmony_ci code = ("import sys; sys.stdout.write(sys.stdin.read(1))") 3557db96d56Sopenharmony_ci p = spawn_python('-u', '-c', code) 3567db96d56Sopenharmony_ci p.stdin.write(b'x') 3577db96d56Sopenharmony_ci p.stdin.flush() 3587db96d56Sopenharmony_ci data, rc = _kill_python_and_exit_code(p) 3597db96d56Sopenharmony_ci self.assertEqual(rc, 0) 3607db96d56Sopenharmony_ci self.assertTrue(data.startswith(b'x'), data) 3617db96d56Sopenharmony_ci 3627db96d56Sopenharmony_ci def test_large_PYTHONPATH(self): 3637db96d56Sopenharmony_ci path1 = "ABCDE" * 100 3647db96d56Sopenharmony_ci path2 = "FGHIJ" * 100 3657db96d56Sopenharmony_ci path = path1 + os.pathsep + path2 3667db96d56Sopenharmony_ci 3677db96d56Sopenharmony_ci code = """if 1: 3687db96d56Sopenharmony_ci import sys 3697db96d56Sopenharmony_ci path = ":".join(sys.path) 3707db96d56Sopenharmony_ci path = path.encode("ascii", "backslashreplace") 3717db96d56Sopenharmony_ci sys.stdout.buffer.write(path)""" 3727db96d56Sopenharmony_ci rc, out, err = assert_python_ok('-S', '-c', code, 3737db96d56Sopenharmony_ci PYTHONPATH=path) 3747db96d56Sopenharmony_ci self.assertIn(path1.encode('ascii'), out) 3757db96d56Sopenharmony_ci self.assertIn(path2.encode('ascii'), out) 3767db96d56Sopenharmony_ci 3777db96d56Sopenharmony_ci @unittest.skipIf(sys.flags.safe_path, 3787db96d56Sopenharmony_ci 'PYTHONSAFEPATH changes default sys.path') 3797db96d56Sopenharmony_ci def test_empty_PYTHONPATH_issue16309(self): 3807db96d56Sopenharmony_ci # On Posix, it is documented that setting PATH to the 3817db96d56Sopenharmony_ci # empty string is equivalent to not setting PATH at all, 3827db96d56Sopenharmony_ci # which is an exception to the rule that in a string like 3837db96d56Sopenharmony_ci # "/bin::/usr/bin" the empty string in the middle gets 3847db96d56Sopenharmony_ci # interpreted as '.' 3857db96d56Sopenharmony_ci code = """if 1: 3867db96d56Sopenharmony_ci import sys 3877db96d56Sopenharmony_ci path = ":".join(sys.path) 3887db96d56Sopenharmony_ci path = path.encode("ascii", "backslashreplace") 3897db96d56Sopenharmony_ci sys.stdout.buffer.write(path)""" 3907db96d56Sopenharmony_ci rc1, out1, err1 = assert_python_ok('-c', code, PYTHONPATH="") 3917db96d56Sopenharmony_ci rc2, out2, err2 = assert_python_ok('-c', code, __isolated=False) 3927db96d56Sopenharmony_ci # regarding to Posix specification, outputs should be equal 3937db96d56Sopenharmony_ci # for empty and unset PYTHONPATH 3947db96d56Sopenharmony_ci self.assertEqual(out1, out2) 3957db96d56Sopenharmony_ci 3967db96d56Sopenharmony_ci def test_displayhook_unencodable(self): 3977db96d56Sopenharmony_ci for encoding in ('ascii', 'latin-1', 'utf-8'): 3987db96d56Sopenharmony_ci env = os.environ.copy() 3997db96d56Sopenharmony_ci env['PYTHONIOENCODING'] = encoding 4007db96d56Sopenharmony_ci p = subprocess.Popen( 4017db96d56Sopenharmony_ci [sys.executable, '-i'], 4027db96d56Sopenharmony_ci stdin=subprocess.PIPE, 4037db96d56Sopenharmony_ci stdout=subprocess.PIPE, 4047db96d56Sopenharmony_ci stderr=subprocess.STDOUT, 4057db96d56Sopenharmony_ci env=env) 4067db96d56Sopenharmony_ci # non-ascii, surrogate, non-BMP printable, non-BMP unprintable 4077db96d56Sopenharmony_ci text = "a=\xe9 b=\uDC80 c=\U00010000 d=\U0010FFFF" 4087db96d56Sopenharmony_ci p.stdin.write(ascii(text).encode('ascii') + b"\n") 4097db96d56Sopenharmony_ci p.stdin.write(b'exit()\n') 4107db96d56Sopenharmony_ci data = kill_python(p) 4117db96d56Sopenharmony_ci escaped = repr(text).encode(encoding, 'backslashreplace') 4127db96d56Sopenharmony_ci self.assertIn(escaped, data) 4137db96d56Sopenharmony_ci 4147db96d56Sopenharmony_ci def check_input(self, code, expected): 4157db96d56Sopenharmony_ci with tempfile.NamedTemporaryFile("wb+") as stdin: 4167db96d56Sopenharmony_ci sep = os.linesep.encode('ASCII') 4177db96d56Sopenharmony_ci stdin.write(sep.join((b'abc', b'def'))) 4187db96d56Sopenharmony_ci stdin.flush() 4197db96d56Sopenharmony_ci stdin.seek(0) 4207db96d56Sopenharmony_ci with subprocess.Popen( 4217db96d56Sopenharmony_ci (sys.executable, "-c", code), 4227db96d56Sopenharmony_ci stdin=stdin, stdout=subprocess.PIPE) as proc: 4237db96d56Sopenharmony_ci stdout, stderr = proc.communicate() 4247db96d56Sopenharmony_ci self.assertEqual(stdout.rstrip(), expected) 4257db96d56Sopenharmony_ci 4267db96d56Sopenharmony_ci def test_stdin_readline(self): 4277db96d56Sopenharmony_ci # Issue #11272: check that sys.stdin.readline() replaces '\r\n' by '\n' 4287db96d56Sopenharmony_ci # on Windows (sys.stdin is opened in binary mode) 4297db96d56Sopenharmony_ci self.check_input( 4307db96d56Sopenharmony_ci "import sys; print(repr(sys.stdin.readline()))", 4317db96d56Sopenharmony_ci b"'abc\\n'") 4327db96d56Sopenharmony_ci 4337db96d56Sopenharmony_ci def test_builtin_input(self): 4347db96d56Sopenharmony_ci # Issue #11272: check that input() strips newlines ('\n' or '\r\n') 4357db96d56Sopenharmony_ci self.check_input( 4367db96d56Sopenharmony_ci "print(repr(input()))", 4377db96d56Sopenharmony_ci b"'abc'") 4387db96d56Sopenharmony_ci 4397db96d56Sopenharmony_ci def test_output_newline(self): 4407db96d56Sopenharmony_ci # Issue 13119 Newline for print() should be \r\n on Windows. 4417db96d56Sopenharmony_ci code = """if 1: 4427db96d56Sopenharmony_ci import sys 4437db96d56Sopenharmony_ci print(1) 4447db96d56Sopenharmony_ci print(2) 4457db96d56Sopenharmony_ci print(3, file=sys.stderr) 4467db96d56Sopenharmony_ci print(4, file=sys.stderr)""" 4477db96d56Sopenharmony_ci rc, out, err = assert_python_ok('-c', code) 4487db96d56Sopenharmony_ci 4497db96d56Sopenharmony_ci if sys.platform == 'win32': 4507db96d56Sopenharmony_ci self.assertEqual(b'1\r\n2\r\n', out) 4517db96d56Sopenharmony_ci self.assertEqual(b'3\r\n4\r\n', err) 4527db96d56Sopenharmony_ci else: 4537db96d56Sopenharmony_ci self.assertEqual(b'1\n2\n', out) 4547db96d56Sopenharmony_ci self.assertEqual(b'3\n4\n', err) 4557db96d56Sopenharmony_ci 4567db96d56Sopenharmony_ci def test_unmached_quote(self): 4577db96d56Sopenharmony_ci # Issue #10206: python program starting with unmatched quote 4587db96d56Sopenharmony_ci # spewed spaces to stdout 4597db96d56Sopenharmony_ci rc, out, err = assert_python_failure('-c', "'") 4607db96d56Sopenharmony_ci self.assertRegex(err.decode('ascii', 'ignore'), 'SyntaxError') 4617db96d56Sopenharmony_ci self.assertEqual(b'', out) 4627db96d56Sopenharmony_ci 4637db96d56Sopenharmony_ci def test_stdout_flush_at_shutdown(self): 4647db96d56Sopenharmony_ci # Issue #5319: if stdout.flush() fails at shutdown, an error should 4657db96d56Sopenharmony_ci # be printed out. 4667db96d56Sopenharmony_ci code = """if 1: 4677db96d56Sopenharmony_ci import os, sys, test.support 4687db96d56Sopenharmony_ci test.support.SuppressCrashReport().__enter__() 4697db96d56Sopenharmony_ci sys.stdout.write('x') 4707db96d56Sopenharmony_ci os.close(sys.stdout.fileno())""" 4717db96d56Sopenharmony_ci rc, out, err = assert_python_failure('-c', code) 4727db96d56Sopenharmony_ci self.assertEqual(b'', out) 4737db96d56Sopenharmony_ci self.assertEqual(120, rc) 4747db96d56Sopenharmony_ci self.assertRegex(err.decode('ascii', 'ignore'), 4757db96d56Sopenharmony_ci 'Exception ignored in.*\nOSError: .*') 4767db96d56Sopenharmony_ci 4777db96d56Sopenharmony_ci def test_closed_stdout(self): 4787db96d56Sopenharmony_ci # Issue #13444: if stdout has been explicitly closed, we should 4797db96d56Sopenharmony_ci # not attempt to flush it at shutdown. 4807db96d56Sopenharmony_ci code = "import sys; sys.stdout.close()" 4817db96d56Sopenharmony_ci rc, out, err = assert_python_ok('-c', code) 4827db96d56Sopenharmony_ci self.assertEqual(b'', err) 4837db96d56Sopenharmony_ci 4847db96d56Sopenharmony_ci # Issue #7111: Python should work without standard streams 4857db96d56Sopenharmony_ci 4867db96d56Sopenharmony_ci @unittest.skipIf(os.name != 'posix', "test needs POSIX semantics") 4877db96d56Sopenharmony_ci @unittest.skipIf(sys.platform == "vxworks", 4887db96d56Sopenharmony_ci "test needs preexec support in subprocess.Popen") 4897db96d56Sopenharmony_ci def _test_no_stdio(self, streams): 4907db96d56Sopenharmony_ci code = """if 1: 4917db96d56Sopenharmony_ci import os, sys 4927db96d56Sopenharmony_ci for i, s in enumerate({streams}): 4937db96d56Sopenharmony_ci if getattr(sys, s) is not None: 4947db96d56Sopenharmony_ci os._exit(i + 1) 4957db96d56Sopenharmony_ci os._exit(42)""".format(streams=streams) 4967db96d56Sopenharmony_ci def preexec(): 4977db96d56Sopenharmony_ci if 'stdin' in streams: 4987db96d56Sopenharmony_ci os.close(0) 4997db96d56Sopenharmony_ci if 'stdout' in streams: 5007db96d56Sopenharmony_ci os.close(1) 5017db96d56Sopenharmony_ci if 'stderr' in streams: 5027db96d56Sopenharmony_ci os.close(2) 5037db96d56Sopenharmony_ci p = subprocess.Popen( 5047db96d56Sopenharmony_ci [sys.executable, "-E", "-c", code], 5057db96d56Sopenharmony_ci stdin=subprocess.PIPE, 5067db96d56Sopenharmony_ci stdout=subprocess.PIPE, 5077db96d56Sopenharmony_ci stderr=subprocess.PIPE, 5087db96d56Sopenharmony_ci preexec_fn=preexec) 5097db96d56Sopenharmony_ci out, err = p.communicate() 5107db96d56Sopenharmony_ci self.assertEqual(err, b'') 5117db96d56Sopenharmony_ci self.assertEqual(p.returncode, 42) 5127db96d56Sopenharmony_ci 5137db96d56Sopenharmony_ci def test_no_stdin(self): 5147db96d56Sopenharmony_ci self._test_no_stdio(['stdin']) 5157db96d56Sopenharmony_ci 5167db96d56Sopenharmony_ci def test_no_stdout(self): 5177db96d56Sopenharmony_ci self._test_no_stdio(['stdout']) 5187db96d56Sopenharmony_ci 5197db96d56Sopenharmony_ci def test_no_stderr(self): 5207db96d56Sopenharmony_ci self._test_no_stdio(['stderr']) 5217db96d56Sopenharmony_ci 5227db96d56Sopenharmony_ci def test_no_std_streams(self): 5237db96d56Sopenharmony_ci self._test_no_stdio(['stdin', 'stdout', 'stderr']) 5247db96d56Sopenharmony_ci 5257db96d56Sopenharmony_ci def test_hash_randomization(self): 5267db96d56Sopenharmony_ci # Verify that -R enables hash randomization: 5277db96d56Sopenharmony_ci self.verify_valid_flag('-R') 5287db96d56Sopenharmony_ci hashes = [] 5297db96d56Sopenharmony_ci if os.environ.get('PYTHONHASHSEED', 'random') != 'random': 5307db96d56Sopenharmony_ci env = dict(os.environ) # copy 5317db96d56Sopenharmony_ci # We need to test that it is enabled by default without 5327db96d56Sopenharmony_ci # the environment variable enabling it for us. 5337db96d56Sopenharmony_ci del env['PYTHONHASHSEED'] 5347db96d56Sopenharmony_ci env['__cleanenv'] = '1' # consumed by assert_python_ok() 5357db96d56Sopenharmony_ci else: 5367db96d56Sopenharmony_ci env = {} 5377db96d56Sopenharmony_ci for i in range(3): 5387db96d56Sopenharmony_ci code = 'print(hash("spam"))' 5397db96d56Sopenharmony_ci rc, out, err = assert_python_ok('-c', code, **env) 5407db96d56Sopenharmony_ci self.assertEqual(rc, 0) 5417db96d56Sopenharmony_ci hashes.append(out) 5427db96d56Sopenharmony_ci hashes = sorted(set(hashes)) # uniq 5437db96d56Sopenharmony_ci # Rare chance of failure due to 3 random seeds honestly being equal. 5447db96d56Sopenharmony_ci self.assertGreater(len(hashes), 1, 5457db96d56Sopenharmony_ci msg='3 runs produced an identical random hash ' 5467db96d56Sopenharmony_ci ' for "spam": {}'.format(hashes)) 5477db96d56Sopenharmony_ci 5487db96d56Sopenharmony_ci # Verify that sys.flags contains hash_randomization 5497db96d56Sopenharmony_ci code = 'import sys; print("random is", sys.flags.hash_randomization)' 5507db96d56Sopenharmony_ci rc, out, err = assert_python_ok('-c', code, PYTHONHASHSEED='') 5517db96d56Sopenharmony_ci self.assertIn(b'random is 1', out) 5527db96d56Sopenharmony_ci 5537db96d56Sopenharmony_ci rc, out, err = assert_python_ok('-c', code, PYTHONHASHSEED='random') 5547db96d56Sopenharmony_ci self.assertIn(b'random is 1', out) 5557db96d56Sopenharmony_ci 5567db96d56Sopenharmony_ci rc, out, err = assert_python_ok('-c', code, PYTHONHASHSEED='0') 5577db96d56Sopenharmony_ci self.assertIn(b'random is 0', out) 5587db96d56Sopenharmony_ci 5597db96d56Sopenharmony_ci rc, out, err = assert_python_ok('-R', '-c', code, PYTHONHASHSEED='0') 5607db96d56Sopenharmony_ci self.assertIn(b'random is 1', out) 5617db96d56Sopenharmony_ci 5627db96d56Sopenharmony_ci def test_del___main__(self): 5637db96d56Sopenharmony_ci # Issue #15001: PyRun_SimpleFileExFlags() did crash because it kept a 5647db96d56Sopenharmony_ci # borrowed reference to the dict of __main__ module and later modify 5657db96d56Sopenharmony_ci # the dict whereas the module was destroyed 5667db96d56Sopenharmony_ci filename = os_helper.TESTFN 5677db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, filename) 5687db96d56Sopenharmony_ci with open(filename, "w", encoding="utf-8") as script: 5697db96d56Sopenharmony_ci print("import sys", file=script) 5707db96d56Sopenharmony_ci print("del sys.modules['__main__']", file=script) 5717db96d56Sopenharmony_ci assert_python_ok(filename) 5727db96d56Sopenharmony_ci 5737db96d56Sopenharmony_ci def test_unknown_options(self): 5747db96d56Sopenharmony_ci rc, out, err = assert_python_failure('-E', '-z') 5757db96d56Sopenharmony_ci self.assertIn(b'Unknown option: -z', err) 5767db96d56Sopenharmony_ci self.assertEqual(err.splitlines().count(b'Unknown option: -z'), 1) 5777db96d56Sopenharmony_ci self.assertEqual(b'', out) 5787db96d56Sopenharmony_ci # Add "without='-E'" to prevent _assert_python to append -E 5797db96d56Sopenharmony_ci # to env_vars and change the output of stderr 5807db96d56Sopenharmony_ci rc, out, err = assert_python_failure('-z', without='-E') 5817db96d56Sopenharmony_ci self.assertIn(b'Unknown option: -z', err) 5827db96d56Sopenharmony_ci self.assertEqual(err.splitlines().count(b'Unknown option: -z'), 1) 5837db96d56Sopenharmony_ci self.assertEqual(b'', out) 5847db96d56Sopenharmony_ci rc, out, err = assert_python_failure('-a', '-z', without='-E') 5857db96d56Sopenharmony_ci self.assertIn(b'Unknown option: -a', err) 5867db96d56Sopenharmony_ci # only the first unknown option is reported 5877db96d56Sopenharmony_ci self.assertNotIn(b'Unknown option: -z', err) 5887db96d56Sopenharmony_ci self.assertEqual(err.splitlines().count(b'Unknown option: -a'), 1) 5897db96d56Sopenharmony_ci self.assertEqual(b'', out) 5907db96d56Sopenharmony_ci 5917db96d56Sopenharmony_ci @unittest.skipIf(interpreter_requires_environment(), 5927db96d56Sopenharmony_ci 'Cannot run -I tests when PYTHON env vars are required.') 5937db96d56Sopenharmony_ci def test_isolatedmode(self): 5947db96d56Sopenharmony_ci self.verify_valid_flag('-I') 5957db96d56Sopenharmony_ci self.verify_valid_flag('-IEPs') 5967db96d56Sopenharmony_ci rc, out, err = assert_python_ok('-I', '-c', 5977db96d56Sopenharmony_ci 'from sys import flags as f; ' 5987db96d56Sopenharmony_ci 'print(f.no_user_site, f.ignore_environment, f.isolated, f.safe_path)', 5997db96d56Sopenharmony_ci # dummyvar to prevent extraneous -E 6007db96d56Sopenharmony_ci dummyvar="") 6017db96d56Sopenharmony_ci self.assertEqual(out.strip(), b'1 1 1 True') 6027db96d56Sopenharmony_ci with os_helper.temp_cwd() as tmpdir: 6037db96d56Sopenharmony_ci fake = os.path.join(tmpdir, "uuid.py") 6047db96d56Sopenharmony_ci main = os.path.join(tmpdir, "main.py") 6057db96d56Sopenharmony_ci with open(fake, "w", encoding="utf-8") as f: 6067db96d56Sopenharmony_ci f.write("raise RuntimeError('isolated mode test')\n") 6077db96d56Sopenharmony_ci with open(main, "w", encoding="utf-8") as f: 6087db96d56Sopenharmony_ci f.write("import uuid\n") 6097db96d56Sopenharmony_ci f.write("print('ok')\n") 6107db96d56Sopenharmony_ci # Use -E to ignore PYTHONSAFEPATH env var 6117db96d56Sopenharmony_ci self.assertRaises(subprocess.CalledProcessError, 6127db96d56Sopenharmony_ci subprocess.check_output, 6137db96d56Sopenharmony_ci [sys.executable, '-E', main], cwd=tmpdir, 6147db96d56Sopenharmony_ci stderr=subprocess.DEVNULL) 6157db96d56Sopenharmony_ci out = subprocess.check_output([sys.executable, "-I", main], 6167db96d56Sopenharmony_ci cwd=tmpdir) 6177db96d56Sopenharmony_ci self.assertEqual(out.strip(), b"ok") 6187db96d56Sopenharmony_ci 6197db96d56Sopenharmony_ci def test_sys_flags_set(self): 6207db96d56Sopenharmony_ci # Issue 31845: a startup refactoring broke reading flags from env vars 6217db96d56Sopenharmony_ci for value, expected in (("", 0), ("1", 1), ("text", 1), ("2", 2)): 6227db96d56Sopenharmony_ci env_vars = dict( 6237db96d56Sopenharmony_ci PYTHONDEBUG=value, 6247db96d56Sopenharmony_ci PYTHONOPTIMIZE=value, 6257db96d56Sopenharmony_ci PYTHONDONTWRITEBYTECODE=value, 6267db96d56Sopenharmony_ci PYTHONVERBOSE=value, 6277db96d56Sopenharmony_ci ) 6287db96d56Sopenharmony_ci dont_write_bytecode = int(bool(value)) 6297db96d56Sopenharmony_ci code = ( 6307db96d56Sopenharmony_ci "import sys; " 6317db96d56Sopenharmony_ci "sys.stderr.write(str(sys.flags)); " 6327db96d56Sopenharmony_ci f"""sys.exit(not ( 6337db96d56Sopenharmony_ci sys.flags.debug == sys.flags.optimize == 6347db96d56Sopenharmony_ci sys.flags.verbose == 6357db96d56Sopenharmony_ci {expected} 6367db96d56Sopenharmony_ci and sys.flags.dont_write_bytecode == {dont_write_bytecode} 6377db96d56Sopenharmony_ci ))""" 6387db96d56Sopenharmony_ci ) 6397db96d56Sopenharmony_ci with self.subTest(envar_value=value): 6407db96d56Sopenharmony_ci assert_python_ok('-c', code, **env_vars) 6417db96d56Sopenharmony_ci 6427db96d56Sopenharmony_ci def test_set_pycache_prefix(self): 6437db96d56Sopenharmony_ci # sys.pycache_prefix can be set from either -X pycache_prefix or 6447db96d56Sopenharmony_ci # PYTHONPYCACHEPREFIX env var, with the former taking precedence. 6457db96d56Sopenharmony_ci NO_VALUE = object() # `-X pycache_prefix` with no `=PATH` 6467db96d56Sopenharmony_ci cases = [ 6477db96d56Sopenharmony_ci # (PYTHONPYCACHEPREFIX, -X pycache_prefix, sys.pycache_prefix) 6487db96d56Sopenharmony_ci (None, None, None), 6497db96d56Sopenharmony_ci ('foo', None, 'foo'), 6507db96d56Sopenharmony_ci (None, 'bar', 'bar'), 6517db96d56Sopenharmony_ci ('foo', 'bar', 'bar'), 6527db96d56Sopenharmony_ci ('foo', '', None), 6537db96d56Sopenharmony_ci ('foo', NO_VALUE, None), 6547db96d56Sopenharmony_ci ] 6557db96d56Sopenharmony_ci for envval, opt, expected in cases: 6567db96d56Sopenharmony_ci exp_clause = "is None" if expected is None else f'== "{expected}"' 6577db96d56Sopenharmony_ci code = f"import sys; sys.exit(not sys.pycache_prefix {exp_clause})" 6587db96d56Sopenharmony_ci args = ['-c', code] 6597db96d56Sopenharmony_ci env = {} if envval is None else {'PYTHONPYCACHEPREFIX': envval} 6607db96d56Sopenharmony_ci if opt is NO_VALUE: 6617db96d56Sopenharmony_ci args[:0] = ['-X', 'pycache_prefix'] 6627db96d56Sopenharmony_ci elif opt is not None: 6637db96d56Sopenharmony_ci args[:0] = ['-X', f'pycache_prefix={opt}'] 6647db96d56Sopenharmony_ci with self.subTest(envval=envval, opt=opt): 6657db96d56Sopenharmony_ci with os_helper.temp_cwd(): 6667db96d56Sopenharmony_ci assert_python_ok(*args, **env) 6677db96d56Sopenharmony_ci 6687db96d56Sopenharmony_ci def run_xdev(self, *args, check_exitcode=True, xdev=True): 6697db96d56Sopenharmony_ci env = dict(os.environ) 6707db96d56Sopenharmony_ci env.pop('PYTHONWARNINGS', None) 6717db96d56Sopenharmony_ci env.pop('PYTHONDEVMODE', None) 6727db96d56Sopenharmony_ci env.pop('PYTHONMALLOC', None) 6737db96d56Sopenharmony_ci 6747db96d56Sopenharmony_ci if xdev: 6757db96d56Sopenharmony_ci args = (sys.executable, '-X', 'dev', *args) 6767db96d56Sopenharmony_ci else: 6777db96d56Sopenharmony_ci args = (sys.executable, *args) 6787db96d56Sopenharmony_ci proc = subprocess.run(args, 6797db96d56Sopenharmony_ci stdout=subprocess.PIPE, 6807db96d56Sopenharmony_ci stderr=subprocess.STDOUT, 6817db96d56Sopenharmony_ci universal_newlines=True, 6827db96d56Sopenharmony_ci env=env) 6837db96d56Sopenharmony_ci if check_exitcode: 6847db96d56Sopenharmony_ci self.assertEqual(proc.returncode, 0, proc) 6857db96d56Sopenharmony_ci return proc.stdout.rstrip() 6867db96d56Sopenharmony_ci 6877db96d56Sopenharmony_ci def test_xdev(self): 6887db96d56Sopenharmony_ci # sys.flags.dev_mode 6897db96d56Sopenharmony_ci code = "import sys; print(sys.flags.dev_mode)" 6907db96d56Sopenharmony_ci out = self.run_xdev("-c", code, xdev=False) 6917db96d56Sopenharmony_ci self.assertEqual(out, "False") 6927db96d56Sopenharmony_ci out = self.run_xdev("-c", code) 6937db96d56Sopenharmony_ci self.assertEqual(out, "True") 6947db96d56Sopenharmony_ci 6957db96d56Sopenharmony_ci # Warnings 6967db96d56Sopenharmony_ci code = ("import warnings; " 6977db96d56Sopenharmony_ci "print(' '.join('%s::%s' % (f[0], f[2].__name__) " 6987db96d56Sopenharmony_ci "for f in warnings.filters))") 6997db96d56Sopenharmony_ci if Py_DEBUG: 7007db96d56Sopenharmony_ci expected_filters = "default::Warning" 7017db96d56Sopenharmony_ci else: 7027db96d56Sopenharmony_ci expected_filters = ("default::Warning " 7037db96d56Sopenharmony_ci "default::DeprecationWarning " 7047db96d56Sopenharmony_ci "ignore::DeprecationWarning " 7057db96d56Sopenharmony_ci "ignore::PendingDeprecationWarning " 7067db96d56Sopenharmony_ci "ignore::ImportWarning " 7077db96d56Sopenharmony_ci "ignore::ResourceWarning") 7087db96d56Sopenharmony_ci 7097db96d56Sopenharmony_ci out = self.run_xdev("-c", code) 7107db96d56Sopenharmony_ci self.assertEqual(out, expected_filters) 7117db96d56Sopenharmony_ci 7127db96d56Sopenharmony_ci out = self.run_xdev("-b", "-c", code) 7137db96d56Sopenharmony_ci self.assertEqual(out, f"default::BytesWarning {expected_filters}") 7147db96d56Sopenharmony_ci 7157db96d56Sopenharmony_ci out = self.run_xdev("-bb", "-c", code) 7167db96d56Sopenharmony_ci self.assertEqual(out, f"error::BytesWarning {expected_filters}") 7177db96d56Sopenharmony_ci 7187db96d56Sopenharmony_ci out = self.run_xdev("-Werror", "-c", code) 7197db96d56Sopenharmony_ci self.assertEqual(out, f"error::Warning {expected_filters}") 7207db96d56Sopenharmony_ci 7217db96d56Sopenharmony_ci # Memory allocator debug hooks 7227db96d56Sopenharmony_ci try: 7237db96d56Sopenharmony_ci import _testcapi 7247db96d56Sopenharmony_ci except ImportError: 7257db96d56Sopenharmony_ci pass 7267db96d56Sopenharmony_ci else: 7277db96d56Sopenharmony_ci code = "import _testcapi; print(_testcapi.pymem_getallocatorsname())" 7287db96d56Sopenharmony_ci with support.SuppressCrashReport(): 7297db96d56Sopenharmony_ci out = self.run_xdev("-c", code, check_exitcode=False) 7307db96d56Sopenharmony_ci if support.with_pymalloc(): 7317db96d56Sopenharmony_ci alloc_name = "pymalloc_debug" 7327db96d56Sopenharmony_ci else: 7337db96d56Sopenharmony_ci alloc_name = "malloc_debug" 7347db96d56Sopenharmony_ci self.assertEqual(out, alloc_name) 7357db96d56Sopenharmony_ci 7367db96d56Sopenharmony_ci # Faulthandler 7377db96d56Sopenharmony_ci try: 7387db96d56Sopenharmony_ci import faulthandler 7397db96d56Sopenharmony_ci except ImportError: 7407db96d56Sopenharmony_ci pass 7417db96d56Sopenharmony_ci else: 7427db96d56Sopenharmony_ci code = "import faulthandler; print(faulthandler.is_enabled())" 7437db96d56Sopenharmony_ci out = self.run_xdev("-c", code) 7447db96d56Sopenharmony_ci self.assertEqual(out, "True") 7457db96d56Sopenharmony_ci 7467db96d56Sopenharmony_ci def check_warnings_filters(self, cmdline_option, envvar, use_pywarning=False): 7477db96d56Sopenharmony_ci if use_pywarning: 7487db96d56Sopenharmony_ci code = ("import sys; from test.support.import_helper import " 7497db96d56Sopenharmony_ci "import_fresh_module; " 7507db96d56Sopenharmony_ci "warnings = import_fresh_module('warnings', blocked=['_warnings']); ") 7517db96d56Sopenharmony_ci else: 7527db96d56Sopenharmony_ci code = "import sys, warnings; " 7537db96d56Sopenharmony_ci code += ("print(' '.join('%s::%s' % (f[0], f[2].__name__) " 7547db96d56Sopenharmony_ci "for f in warnings.filters))") 7557db96d56Sopenharmony_ci args = (sys.executable, '-W', cmdline_option, '-bb', '-c', code) 7567db96d56Sopenharmony_ci env = dict(os.environ) 7577db96d56Sopenharmony_ci env.pop('PYTHONDEVMODE', None) 7587db96d56Sopenharmony_ci env["PYTHONWARNINGS"] = envvar 7597db96d56Sopenharmony_ci proc = subprocess.run(args, 7607db96d56Sopenharmony_ci stdout=subprocess.PIPE, 7617db96d56Sopenharmony_ci stderr=subprocess.STDOUT, 7627db96d56Sopenharmony_ci universal_newlines=True, 7637db96d56Sopenharmony_ci env=env) 7647db96d56Sopenharmony_ci self.assertEqual(proc.returncode, 0, proc) 7657db96d56Sopenharmony_ci return proc.stdout.rstrip() 7667db96d56Sopenharmony_ci 7677db96d56Sopenharmony_ci def test_warnings_filter_precedence(self): 7687db96d56Sopenharmony_ci expected_filters = ("error::BytesWarning " 7697db96d56Sopenharmony_ci "once::UserWarning " 7707db96d56Sopenharmony_ci "always::UserWarning") 7717db96d56Sopenharmony_ci if not Py_DEBUG: 7727db96d56Sopenharmony_ci expected_filters += (" " 7737db96d56Sopenharmony_ci "default::DeprecationWarning " 7747db96d56Sopenharmony_ci "ignore::DeprecationWarning " 7757db96d56Sopenharmony_ci "ignore::PendingDeprecationWarning " 7767db96d56Sopenharmony_ci "ignore::ImportWarning " 7777db96d56Sopenharmony_ci "ignore::ResourceWarning") 7787db96d56Sopenharmony_ci 7797db96d56Sopenharmony_ci out = self.check_warnings_filters("once::UserWarning", 7807db96d56Sopenharmony_ci "always::UserWarning") 7817db96d56Sopenharmony_ci self.assertEqual(out, expected_filters) 7827db96d56Sopenharmony_ci 7837db96d56Sopenharmony_ci out = self.check_warnings_filters("once::UserWarning", 7847db96d56Sopenharmony_ci "always::UserWarning", 7857db96d56Sopenharmony_ci use_pywarning=True) 7867db96d56Sopenharmony_ci self.assertEqual(out, expected_filters) 7877db96d56Sopenharmony_ci 7887db96d56Sopenharmony_ci def check_pythonmalloc(self, env_var, name): 7897db96d56Sopenharmony_ci code = 'import _testcapi; print(_testcapi.pymem_getallocatorsname())' 7907db96d56Sopenharmony_ci env = dict(os.environ) 7917db96d56Sopenharmony_ci env.pop('PYTHONDEVMODE', None) 7927db96d56Sopenharmony_ci if env_var is not None: 7937db96d56Sopenharmony_ci env['PYTHONMALLOC'] = env_var 7947db96d56Sopenharmony_ci else: 7957db96d56Sopenharmony_ci env.pop('PYTHONMALLOC', None) 7967db96d56Sopenharmony_ci args = (sys.executable, '-c', code) 7977db96d56Sopenharmony_ci proc = subprocess.run(args, 7987db96d56Sopenharmony_ci stdout=subprocess.PIPE, 7997db96d56Sopenharmony_ci stderr=subprocess.STDOUT, 8007db96d56Sopenharmony_ci universal_newlines=True, 8017db96d56Sopenharmony_ci env=env) 8027db96d56Sopenharmony_ci self.assertEqual(proc.stdout.rstrip(), name) 8037db96d56Sopenharmony_ci self.assertEqual(proc.returncode, 0) 8047db96d56Sopenharmony_ci 8057db96d56Sopenharmony_ci def test_pythonmalloc(self): 8067db96d56Sopenharmony_ci # Test the PYTHONMALLOC environment variable 8077db96d56Sopenharmony_ci pymalloc = support.with_pymalloc() 8087db96d56Sopenharmony_ci if pymalloc: 8097db96d56Sopenharmony_ci default_name = 'pymalloc_debug' if Py_DEBUG else 'pymalloc' 8107db96d56Sopenharmony_ci default_name_debug = 'pymalloc_debug' 8117db96d56Sopenharmony_ci else: 8127db96d56Sopenharmony_ci default_name = 'malloc_debug' if Py_DEBUG else 'malloc' 8137db96d56Sopenharmony_ci default_name_debug = 'malloc_debug' 8147db96d56Sopenharmony_ci 8157db96d56Sopenharmony_ci tests = [ 8167db96d56Sopenharmony_ci (None, default_name), 8177db96d56Sopenharmony_ci ('debug', default_name_debug), 8187db96d56Sopenharmony_ci ('malloc', 'malloc'), 8197db96d56Sopenharmony_ci ('malloc_debug', 'malloc_debug'), 8207db96d56Sopenharmony_ci ] 8217db96d56Sopenharmony_ci if pymalloc: 8227db96d56Sopenharmony_ci tests.extend(( 8237db96d56Sopenharmony_ci ('pymalloc', 'pymalloc'), 8247db96d56Sopenharmony_ci ('pymalloc_debug', 'pymalloc_debug'), 8257db96d56Sopenharmony_ci )) 8267db96d56Sopenharmony_ci 8277db96d56Sopenharmony_ci for env_var, name in tests: 8287db96d56Sopenharmony_ci with self.subTest(env_var=env_var, name=name): 8297db96d56Sopenharmony_ci self.check_pythonmalloc(env_var, name) 8307db96d56Sopenharmony_ci 8317db96d56Sopenharmony_ci def test_pythondevmode_env(self): 8327db96d56Sopenharmony_ci # Test the PYTHONDEVMODE environment variable 8337db96d56Sopenharmony_ci code = "import sys; print(sys.flags.dev_mode)" 8347db96d56Sopenharmony_ci env = dict(os.environ) 8357db96d56Sopenharmony_ci env.pop('PYTHONDEVMODE', None) 8367db96d56Sopenharmony_ci args = (sys.executable, '-c', code) 8377db96d56Sopenharmony_ci 8387db96d56Sopenharmony_ci proc = subprocess.run(args, stdout=subprocess.PIPE, 8397db96d56Sopenharmony_ci universal_newlines=True, env=env) 8407db96d56Sopenharmony_ci self.assertEqual(proc.stdout.rstrip(), 'False') 8417db96d56Sopenharmony_ci self.assertEqual(proc.returncode, 0, proc) 8427db96d56Sopenharmony_ci 8437db96d56Sopenharmony_ci env['PYTHONDEVMODE'] = '1' 8447db96d56Sopenharmony_ci proc = subprocess.run(args, stdout=subprocess.PIPE, 8457db96d56Sopenharmony_ci universal_newlines=True, env=env) 8467db96d56Sopenharmony_ci self.assertEqual(proc.stdout.rstrip(), 'True') 8477db96d56Sopenharmony_ci self.assertEqual(proc.returncode, 0, proc) 8487db96d56Sopenharmony_ci 8497db96d56Sopenharmony_ci @unittest.skipUnless(sys.platform == 'win32', 8507db96d56Sopenharmony_ci 'bpo-32457 only applies on Windows') 8517db96d56Sopenharmony_ci def test_argv0_normalization(self): 8527db96d56Sopenharmony_ci args = sys.executable, '-c', 'print(0)' 8537db96d56Sopenharmony_ci prefix, exe = os.path.split(sys.executable) 8547db96d56Sopenharmony_ci executable = prefix + '\\.\\.\\.\\' + exe 8557db96d56Sopenharmony_ci 8567db96d56Sopenharmony_ci proc = subprocess.run(args, stdout=subprocess.PIPE, 8577db96d56Sopenharmony_ci executable=executable) 8587db96d56Sopenharmony_ci self.assertEqual(proc.returncode, 0, proc) 8597db96d56Sopenharmony_ci self.assertEqual(proc.stdout.strip(), b'0') 8607db96d56Sopenharmony_ci 8617db96d56Sopenharmony_ci def test_parsing_error(self): 8627db96d56Sopenharmony_ci args = [sys.executable, '-I', '--unknown-option'] 8637db96d56Sopenharmony_ci proc = subprocess.run(args, 8647db96d56Sopenharmony_ci stdout=subprocess.PIPE, 8657db96d56Sopenharmony_ci stderr=subprocess.PIPE, 8667db96d56Sopenharmony_ci text=True) 8677db96d56Sopenharmony_ci err_msg = "unknown option --unknown-option\nusage: " 8687db96d56Sopenharmony_ci self.assertTrue(proc.stderr.startswith(err_msg), proc.stderr) 8697db96d56Sopenharmony_ci self.assertNotEqual(proc.returncode, 0) 8707db96d56Sopenharmony_ci 8717db96d56Sopenharmony_ci def test_int_max_str_digits(self): 8727db96d56Sopenharmony_ci code = "import sys; print(sys.flags.int_max_str_digits, sys.get_int_max_str_digits())" 8737db96d56Sopenharmony_ci 8747db96d56Sopenharmony_ci assert_python_failure('-X', 'int_max_str_digits', '-c', code) 8757db96d56Sopenharmony_ci assert_python_failure('-X', 'int_max_str_digits=foo', '-c', code) 8767db96d56Sopenharmony_ci assert_python_failure('-X', 'int_max_str_digits=100', '-c', code) 8777db96d56Sopenharmony_ci assert_python_failure('-X', 'int_max_str_digits', '-c', code, 8787db96d56Sopenharmony_ci PYTHONINTMAXSTRDIGITS='4000') 8797db96d56Sopenharmony_ci 8807db96d56Sopenharmony_ci assert_python_failure('-c', code, PYTHONINTMAXSTRDIGITS='foo') 8817db96d56Sopenharmony_ci assert_python_failure('-c', code, PYTHONINTMAXSTRDIGITS='100') 8827db96d56Sopenharmony_ci 8837db96d56Sopenharmony_ci def res2int(res): 8847db96d56Sopenharmony_ci out = res.out.strip().decode("utf-8") 8857db96d56Sopenharmony_ci return tuple(int(i) for i in out.split()) 8867db96d56Sopenharmony_ci 8877db96d56Sopenharmony_ci res = assert_python_ok('-c', code) 8887db96d56Sopenharmony_ci self.assertEqual(res2int(res), (-1, sys.get_int_max_str_digits())) 8897db96d56Sopenharmony_ci res = assert_python_ok('-X', 'int_max_str_digits=0', '-c', code) 8907db96d56Sopenharmony_ci self.assertEqual(res2int(res), (0, 0)) 8917db96d56Sopenharmony_ci res = assert_python_ok('-X', 'int_max_str_digits=4000', '-c', code) 8927db96d56Sopenharmony_ci self.assertEqual(res2int(res), (4000, 4000)) 8937db96d56Sopenharmony_ci res = assert_python_ok('-X', 'int_max_str_digits=100000', '-c', code) 8947db96d56Sopenharmony_ci self.assertEqual(res2int(res), (100000, 100000)) 8957db96d56Sopenharmony_ci 8967db96d56Sopenharmony_ci res = assert_python_ok('-c', code, PYTHONINTMAXSTRDIGITS='0') 8977db96d56Sopenharmony_ci self.assertEqual(res2int(res), (0, 0)) 8987db96d56Sopenharmony_ci res = assert_python_ok('-c', code, PYTHONINTMAXSTRDIGITS='4000') 8997db96d56Sopenharmony_ci self.assertEqual(res2int(res), (4000, 4000)) 9007db96d56Sopenharmony_ci res = assert_python_ok( 9017db96d56Sopenharmony_ci '-X', 'int_max_str_digits=6000', '-c', code, 9027db96d56Sopenharmony_ci PYTHONINTMAXSTRDIGITS='4000' 9037db96d56Sopenharmony_ci ) 9047db96d56Sopenharmony_ci self.assertEqual(res2int(res), (6000, 6000)) 9057db96d56Sopenharmony_ci 9067db96d56Sopenharmony_ci 9077db96d56Sopenharmony_ci@unittest.skipIf(interpreter_requires_environment(), 9087db96d56Sopenharmony_ci 'Cannot run -I tests when PYTHON env vars are required.') 9097db96d56Sopenharmony_ciclass IgnoreEnvironmentTest(unittest.TestCase): 9107db96d56Sopenharmony_ci 9117db96d56Sopenharmony_ci def run_ignoring_vars(self, predicate, **env_vars): 9127db96d56Sopenharmony_ci # Runs a subprocess with -E set, even though we're passing 9137db96d56Sopenharmony_ci # specific environment variables 9147db96d56Sopenharmony_ci # Logical inversion to match predicate check to a zero return 9157db96d56Sopenharmony_ci # code indicating success 9167db96d56Sopenharmony_ci code = "import sys; sys.stderr.write(str(sys.flags)); sys.exit(not ({}))".format(predicate) 9177db96d56Sopenharmony_ci return assert_python_ok('-E', '-c', code, **env_vars) 9187db96d56Sopenharmony_ci 9197db96d56Sopenharmony_ci def test_ignore_PYTHONPATH(self): 9207db96d56Sopenharmony_ci path = "should_be_ignored" 9217db96d56Sopenharmony_ci self.run_ignoring_vars("'{}' not in sys.path".format(path), 9227db96d56Sopenharmony_ci PYTHONPATH=path) 9237db96d56Sopenharmony_ci 9247db96d56Sopenharmony_ci def test_ignore_PYTHONHASHSEED(self): 9257db96d56Sopenharmony_ci self.run_ignoring_vars("sys.flags.hash_randomization == 1", 9267db96d56Sopenharmony_ci PYTHONHASHSEED="0") 9277db96d56Sopenharmony_ci 9287db96d56Sopenharmony_ci def test_sys_flags_not_set(self): 9297db96d56Sopenharmony_ci # Issue 31845: a startup refactoring broke reading flags from env vars 9307db96d56Sopenharmony_ci expected_outcome = """ 9317db96d56Sopenharmony_ci (sys.flags.debug == sys.flags.optimize == 9327db96d56Sopenharmony_ci sys.flags.dont_write_bytecode == 9337db96d56Sopenharmony_ci sys.flags.verbose == sys.flags.safe_path == 0) 9347db96d56Sopenharmony_ci """ 9357db96d56Sopenharmony_ci self.run_ignoring_vars( 9367db96d56Sopenharmony_ci expected_outcome, 9377db96d56Sopenharmony_ci PYTHONDEBUG="1", 9387db96d56Sopenharmony_ci PYTHONOPTIMIZE="1", 9397db96d56Sopenharmony_ci PYTHONDONTWRITEBYTECODE="1", 9407db96d56Sopenharmony_ci PYTHONVERBOSE="1", 9417db96d56Sopenharmony_ci PYTHONSAFEPATH="1", 9427db96d56Sopenharmony_ci ) 9437db96d56Sopenharmony_ci 9447db96d56Sopenharmony_ci 9457db96d56Sopenharmony_ciclass SyntaxErrorTests(unittest.TestCase): 9467db96d56Sopenharmony_ci def check_string(self, code): 9477db96d56Sopenharmony_ci proc = subprocess.run([sys.executable, "-"], input=code, 9487db96d56Sopenharmony_ci stdout=subprocess.PIPE, stderr=subprocess.PIPE) 9497db96d56Sopenharmony_ci self.assertNotEqual(proc.returncode, 0) 9507db96d56Sopenharmony_ci self.assertNotEqual(proc.stderr, None) 9517db96d56Sopenharmony_ci self.assertIn(b"\nSyntaxError", proc.stderr) 9527db96d56Sopenharmony_ci 9537db96d56Sopenharmony_ci def test_tokenizer_error_with_stdin(self): 9547db96d56Sopenharmony_ci self.check_string(b"(1+2+3") 9557db96d56Sopenharmony_ci 9567db96d56Sopenharmony_ci def test_decoding_error_at_the_end_of_the_line(self): 9577db96d56Sopenharmony_ci self.check_string(br"'\u1f'") 9587db96d56Sopenharmony_ci 9597db96d56Sopenharmony_ci 9607db96d56Sopenharmony_cidef tearDownModule(): 9617db96d56Sopenharmony_ci support.reap_children() 9627db96d56Sopenharmony_ci 9637db96d56Sopenharmony_ci 9647db96d56Sopenharmony_ciif __name__ == "__main__": 9657db96d56Sopenharmony_ci unittest.main() 966