17db96d56Sopenharmony_ci# bpo-42260: Test _PyInterpreterState_GetConfigCopy()
27db96d56Sopenharmony_ci# and _PyInterpreterState_SetConfig().
37db96d56Sopenharmony_ci#
47db96d56Sopenharmony_ci# Test run in a subprocess since set_config(get_config())
57db96d56Sopenharmony_ci# does reset sys attributes to their state of the Python startup
67db96d56Sopenharmony_ci# (before the site module is run).
77db96d56Sopenharmony_ci
87db96d56Sopenharmony_ciimport _testinternalcapi
97db96d56Sopenharmony_ciimport os
107db96d56Sopenharmony_ciimport sys
117db96d56Sopenharmony_ciimport unittest
127db96d56Sopenharmony_ci
137db96d56Sopenharmony_ci
147db96d56Sopenharmony_ciMS_WINDOWS = (os.name == 'nt')
157db96d56Sopenharmony_ciMAX_HASH_SEED = 4294967295
167db96d56Sopenharmony_ci
177db96d56Sopenharmony_ciclass SetConfigTests(unittest.TestCase):
187db96d56Sopenharmony_ci    def setUp(self):
197db96d56Sopenharmony_ci        self.old_config = _testinternalcapi.get_config()
207db96d56Sopenharmony_ci        self.sys_copy = dict(sys.__dict__)
217db96d56Sopenharmony_ci
227db96d56Sopenharmony_ci    def tearDown(self):
237db96d56Sopenharmony_ci        _testinternalcapi.reset_path_config()
247db96d56Sopenharmony_ci        _testinternalcapi.set_config(self.old_config)
257db96d56Sopenharmony_ci        sys.__dict__.clear()
267db96d56Sopenharmony_ci        sys.__dict__.update(self.sys_copy)
277db96d56Sopenharmony_ci
287db96d56Sopenharmony_ci    def set_config(self, **kwargs):
297db96d56Sopenharmony_ci        _testinternalcapi.set_config(self.old_config | kwargs)
307db96d56Sopenharmony_ci
317db96d56Sopenharmony_ci    def check(self, **kwargs):
327db96d56Sopenharmony_ci        self.set_config(**kwargs)
337db96d56Sopenharmony_ci        for key, value in kwargs.items():
347db96d56Sopenharmony_ci            self.assertEqual(getattr(sys, key), value,
357db96d56Sopenharmony_ci                             (key, value))
367db96d56Sopenharmony_ci
377db96d56Sopenharmony_ci    def test_set_invalid(self):
387db96d56Sopenharmony_ci        invalid_uint = -1
397db96d56Sopenharmony_ci        NULL = None
407db96d56Sopenharmony_ci        invalid_wstr = NULL
417db96d56Sopenharmony_ci        # PyWideStringList strings must be non-NULL
427db96d56Sopenharmony_ci        invalid_wstrlist = ["abc", NULL, "def"]
437db96d56Sopenharmony_ci
447db96d56Sopenharmony_ci        type_tests = []
457db96d56Sopenharmony_ci        value_tests = [
467db96d56Sopenharmony_ci            # enum
477db96d56Sopenharmony_ci            ('_config_init', 0),
487db96d56Sopenharmony_ci            ('_config_init', 4),
497db96d56Sopenharmony_ci            # unsigned long
507db96d56Sopenharmony_ci            ("hash_seed", -1),
517db96d56Sopenharmony_ci            ("hash_seed", MAX_HASH_SEED + 1),
527db96d56Sopenharmony_ci        ]
537db96d56Sopenharmony_ci
547db96d56Sopenharmony_ci        # int (unsigned)
557db96d56Sopenharmony_ci        options = [
567db96d56Sopenharmony_ci            '_config_init',
577db96d56Sopenharmony_ci            'isolated',
587db96d56Sopenharmony_ci            'use_environment',
597db96d56Sopenharmony_ci            'dev_mode',
607db96d56Sopenharmony_ci            'install_signal_handlers',
617db96d56Sopenharmony_ci            'use_hash_seed',
627db96d56Sopenharmony_ci            'faulthandler',
637db96d56Sopenharmony_ci            'tracemalloc',
647db96d56Sopenharmony_ci            'import_time',
657db96d56Sopenharmony_ci            'code_debug_ranges',
667db96d56Sopenharmony_ci            'show_ref_count',
677db96d56Sopenharmony_ci            'dump_refs',
687db96d56Sopenharmony_ci            'malloc_stats',
697db96d56Sopenharmony_ci            'parse_argv',
707db96d56Sopenharmony_ci            'site_import',
717db96d56Sopenharmony_ci            'bytes_warning',
727db96d56Sopenharmony_ci            'inspect',
737db96d56Sopenharmony_ci            'interactive',
747db96d56Sopenharmony_ci            'optimization_level',
757db96d56Sopenharmony_ci            'parser_debug',
767db96d56Sopenharmony_ci            'write_bytecode',
777db96d56Sopenharmony_ci            'verbose',
787db96d56Sopenharmony_ci            'quiet',
797db96d56Sopenharmony_ci            'user_site_directory',
807db96d56Sopenharmony_ci            'configure_c_stdio',
817db96d56Sopenharmony_ci            'buffered_stdio',
827db96d56Sopenharmony_ci            'pathconfig_warnings',
837db96d56Sopenharmony_ci            'module_search_paths_set',
847db96d56Sopenharmony_ci            'skip_source_first_line',
857db96d56Sopenharmony_ci            '_install_importlib',
867db96d56Sopenharmony_ci            '_init_main',
877db96d56Sopenharmony_ci            '_isolated_interpreter',
887db96d56Sopenharmony_ci        ]
897db96d56Sopenharmony_ci        if MS_WINDOWS:
907db96d56Sopenharmony_ci            options.append('legacy_windows_stdio')
917db96d56Sopenharmony_ci        for key in options:
927db96d56Sopenharmony_ci            value_tests.append((key, invalid_uint))
937db96d56Sopenharmony_ci            type_tests.append((key, "abc"))
947db96d56Sopenharmony_ci            type_tests.append((key, 2.0))
957db96d56Sopenharmony_ci
967db96d56Sopenharmony_ci        # wchar_t*
977db96d56Sopenharmony_ci        for key in (
987db96d56Sopenharmony_ci            'filesystem_encoding',
997db96d56Sopenharmony_ci            'filesystem_errors',
1007db96d56Sopenharmony_ci            'stdio_encoding',
1017db96d56Sopenharmony_ci            'stdio_errors',
1027db96d56Sopenharmony_ci            'check_hash_pycs_mode',
1037db96d56Sopenharmony_ci            'program_name',
1047db96d56Sopenharmony_ci            'platlibdir',
1057db96d56Sopenharmony_ci            # optional wstr:
1067db96d56Sopenharmony_ci            # 'pythonpath_env'
1077db96d56Sopenharmony_ci            # 'home'
1087db96d56Sopenharmony_ci            # 'pycache_prefix'
1097db96d56Sopenharmony_ci            # 'run_command'
1107db96d56Sopenharmony_ci            # 'run_module'
1117db96d56Sopenharmony_ci            # 'run_filename'
1127db96d56Sopenharmony_ci            # 'executable'
1137db96d56Sopenharmony_ci            # 'prefix'
1147db96d56Sopenharmony_ci            # 'exec_prefix'
1157db96d56Sopenharmony_ci            # 'base_executable'
1167db96d56Sopenharmony_ci            # 'base_prefix'
1177db96d56Sopenharmony_ci            # 'base_exec_prefix'
1187db96d56Sopenharmony_ci        ):
1197db96d56Sopenharmony_ci            value_tests.append((key, invalid_wstr))
1207db96d56Sopenharmony_ci            type_tests.append((key, b'bytes'))
1217db96d56Sopenharmony_ci            type_tests.append((key, 123))
1227db96d56Sopenharmony_ci
1237db96d56Sopenharmony_ci        # PyWideStringList
1247db96d56Sopenharmony_ci        for key in (
1257db96d56Sopenharmony_ci            'orig_argv',
1267db96d56Sopenharmony_ci            'argv',
1277db96d56Sopenharmony_ci            'xoptions',
1287db96d56Sopenharmony_ci            'warnoptions',
1297db96d56Sopenharmony_ci            'module_search_paths',
1307db96d56Sopenharmony_ci        ):
1317db96d56Sopenharmony_ci            value_tests.append((key, invalid_wstrlist))
1327db96d56Sopenharmony_ci            type_tests.append((key, 123))
1337db96d56Sopenharmony_ci            type_tests.append((key, "abc"))
1347db96d56Sopenharmony_ci            type_tests.append((key, [123]))
1357db96d56Sopenharmony_ci            type_tests.append((key, [b"bytes"]))
1367db96d56Sopenharmony_ci
1377db96d56Sopenharmony_ci
1387db96d56Sopenharmony_ci        if MS_WINDOWS:
1397db96d56Sopenharmony_ci            value_tests.append(('legacy_windows_stdio', invalid_uint))
1407db96d56Sopenharmony_ci
1417db96d56Sopenharmony_ci        for exc_type, tests in (
1427db96d56Sopenharmony_ci            (ValueError, value_tests),
1437db96d56Sopenharmony_ci            (TypeError, type_tests),
1447db96d56Sopenharmony_ci        ):
1457db96d56Sopenharmony_ci            for key, value in tests:
1467db96d56Sopenharmony_ci                config = self.old_config | {key: value}
1477db96d56Sopenharmony_ci                with self.subTest(key=key, value=value, exc_type=exc_type):
1487db96d56Sopenharmony_ci                    with self.assertRaises(exc_type):
1497db96d56Sopenharmony_ci                        _testinternalcapi.set_config(config)
1507db96d56Sopenharmony_ci
1517db96d56Sopenharmony_ci    def test_flags(self):
1527db96d56Sopenharmony_ci        for sys_attr, key, value in (
1537db96d56Sopenharmony_ci            ("debug", "parser_debug", 1),
1547db96d56Sopenharmony_ci            ("inspect", "inspect", 2),
1557db96d56Sopenharmony_ci            ("interactive", "interactive", 3),
1567db96d56Sopenharmony_ci            ("optimize", "optimization_level", 4),
1577db96d56Sopenharmony_ci            ("verbose", "verbose", 1),
1587db96d56Sopenharmony_ci            ("bytes_warning", "bytes_warning", 10),
1597db96d56Sopenharmony_ci            ("quiet", "quiet", 11),
1607db96d56Sopenharmony_ci            ("isolated", "isolated", 12),
1617db96d56Sopenharmony_ci        ):
1627db96d56Sopenharmony_ci            with self.subTest(sys=sys_attr, key=key, value=value):
1637db96d56Sopenharmony_ci                self.set_config(**{key: value, 'parse_argv': 0})
1647db96d56Sopenharmony_ci                self.assertEqual(getattr(sys.flags, sys_attr), value)
1657db96d56Sopenharmony_ci
1667db96d56Sopenharmony_ci        self.set_config(write_bytecode=0)
1677db96d56Sopenharmony_ci        self.assertEqual(sys.flags.dont_write_bytecode, True)
1687db96d56Sopenharmony_ci        self.assertEqual(sys.dont_write_bytecode, True)
1697db96d56Sopenharmony_ci
1707db96d56Sopenharmony_ci        self.set_config(write_bytecode=1)
1717db96d56Sopenharmony_ci        self.assertEqual(sys.flags.dont_write_bytecode, False)
1727db96d56Sopenharmony_ci        self.assertEqual(sys.dont_write_bytecode, False)
1737db96d56Sopenharmony_ci
1747db96d56Sopenharmony_ci        self.set_config(user_site_directory=0, isolated=0)
1757db96d56Sopenharmony_ci        self.assertEqual(sys.flags.no_user_site, 1)
1767db96d56Sopenharmony_ci        self.set_config(user_site_directory=1, isolated=0)
1777db96d56Sopenharmony_ci        self.assertEqual(sys.flags.no_user_site, 0)
1787db96d56Sopenharmony_ci
1797db96d56Sopenharmony_ci        self.set_config(site_import=0)
1807db96d56Sopenharmony_ci        self.assertEqual(sys.flags.no_site, 1)
1817db96d56Sopenharmony_ci        self.set_config(site_import=1)
1827db96d56Sopenharmony_ci        self.assertEqual(sys.flags.no_site, 0)
1837db96d56Sopenharmony_ci
1847db96d56Sopenharmony_ci        self.set_config(dev_mode=0)
1857db96d56Sopenharmony_ci        self.assertEqual(sys.flags.dev_mode, False)
1867db96d56Sopenharmony_ci        self.set_config(dev_mode=1)
1877db96d56Sopenharmony_ci        self.assertEqual(sys.flags.dev_mode, True)
1887db96d56Sopenharmony_ci
1897db96d56Sopenharmony_ci        self.set_config(use_environment=0, isolated=0)
1907db96d56Sopenharmony_ci        self.assertEqual(sys.flags.ignore_environment, 1)
1917db96d56Sopenharmony_ci        self.set_config(use_environment=1, isolated=0)
1927db96d56Sopenharmony_ci        self.assertEqual(sys.flags.ignore_environment, 0)
1937db96d56Sopenharmony_ci
1947db96d56Sopenharmony_ci        self.set_config(use_hash_seed=1, hash_seed=0)
1957db96d56Sopenharmony_ci        self.assertEqual(sys.flags.hash_randomization, 0)
1967db96d56Sopenharmony_ci        self.set_config(use_hash_seed=0, hash_seed=0)
1977db96d56Sopenharmony_ci        self.assertEqual(sys.flags.hash_randomization, 1)
1987db96d56Sopenharmony_ci        self.set_config(use_hash_seed=1, hash_seed=123)
1997db96d56Sopenharmony_ci        self.assertEqual(sys.flags.hash_randomization, 1)
2007db96d56Sopenharmony_ci
2017db96d56Sopenharmony_ci    def test_options(self):
2027db96d56Sopenharmony_ci        self.check(warnoptions=[])
2037db96d56Sopenharmony_ci        self.check(warnoptions=["default", "ignore"])
2047db96d56Sopenharmony_ci
2057db96d56Sopenharmony_ci        self.set_config(xoptions=[])
2067db96d56Sopenharmony_ci        self.assertEqual(sys._xoptions, {})
2077db96d56Sopenharmony_ci        self.set_config(xoptions=["dev", "tracemalloc=5"])
2087db96d56Sopenharmony_ci        self.assertEqual(sys._xoptions, {"dev": True, "tracemalloc": "5"})
2097db96d56Sopenharmony_ci
2107db96d56Sopenharmony_ci    def test_pathconfig(self):
2117db96d56Sopenharmony_ci        self.check(
2127db96d56Sopenharmony_ci            executable='executable',
2137db96d56Sopenharmony_ci            prefix="prefix",
2147db96d56Sopenharmony_ci            base_prefix="base_prefix",
2157db96d56Sopenharmony_ci            exec_prefix="exec_prefix",
2167db96d56Sopenharmony_ci            base_exec_prefix="base_exec_prefix",
2177db96d56Sopenharmony_ci            platlibdir="platlibdir")
2187db96d56Sopenharmony_ci
2197db96d56Sopenharmony_ci        self.set_config(base_executable="base_executable")
2207db96d56Sopenharmony_ci        self.assertEqual(sys._base_executable, "base_executable")
2217db96d56Sopenharmony_ci
2227db96d56Sopenharmony_ci        # When base_xxx is NULL, value is copied from xxxx
2237db96d56Sopenharmony_ci        self.set_config(
2247db96d56Sopenharmony_ci            executable='executable',
2257db96d56Sopenharmony_ci            prefix="prefix",
2267db96d56Sopenharmony_ci            exec_prefix="exec_prefix",
2277db96d56Sopenharmony_ci            base_executable=None,
2287db96d56Sopenharmony_ci            base_prefix=None,
2297db96d56Sopenharmony_ci            base_exec_prefix=None)
2307db96d56Sopenharmony_ci        self.assertEqual(sys._base_executable, "executable")
2317db96d56Sopenharmony_ci        self.assertEqual(sys.base_prefix, "prefix")
2327db96d56Sopenharmony_ci        self.assertEqual(sys.base_exec_prefix, "exec_prefix")
2337db96d56Sopenharmony_ci
2347db96d56Sopenharmony_ci    def test_path(self):
2357db96d56Sopenharmony_ci        self.set_config(module_search_paths_set=1,
2367db96d56Sopenharmony_ci                        module_search_paths=['a', 'b', 'c'])
2377db96d56Sopenharmony_ci        self.assertEqual(sys.path, ['a', 'b', 'c'])
2387db96d56Sopenharmony_ci
2397db96d56Sopenharmony_ci        # sys.path is reset if module_search_paths_set=0
2407db96d56Sopenharmony_ci        self.set_config(module_search_paths_set=0,
2417db96d56Sopenharmony_ci                        module_search_paths=['new_path'])
2427db96d56Sopenharmony_ci        self.assertNotEqual(sys.path, ['a', 'b', 'c'])
2437db96d56Sopenharmony_ci        self.assertNotEqual(sys.path, ['new_path'])
2447db96d56Sopenharmony_ci
2457db96d56Sopenharmony_ci    def test_argv(self):
2467db96d56Sopenharmony_ci        self.set_config(parse_argv=0,
2477db96d56Sopenharmony_ci                        argv=['python_program', 'args'],
2487db96d56Sopenharmony_ci                        orig_argv=['orig', 'orig_args'])
2497db96d56Sopenharmony_ci        self.assertEqual(sys.argv, ['python_program', 'args'])
2507db96d56Sopenharmony_ci        self.assertEqual(sys.orig_argv, ['orig', 'orig_args'])
2517db96d56Sopenharmony_ci
2527db96d56Sopenharmony_ci        self.set_config(parse_argv=0,
2537db96d56Sopenharmony_ci                        argv=[],
2547db96d56Sopenharmony_ci                        orig_argv=[])
2557db96d56Sopenharmony_ci        self.assertEqual(sys.argv, [''])
2567db96d56Sopenharmony_ci        self.assertEqual(sys.orig_argv, [])
2577db96d56Sopenharmony_ci
2587db96d56Sopenharmony_ci    def test_pycache_prefix(self):
2597db96d56Sopenharmony_ci        self.check(pycache_prefix=None)
2607db96d56Sopenharmony_ci        self.check(pycache_prefix="pycache_prefix")
2617db96d56Sopenharmony_ci
2627db96d56Sopenharmony_ci
2637db96d56Sopenharmony_ciif __name__ == "__main__":
2647db96d56Sopenharmony_ci    unittest.main()
265