| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -470,7 +470,8 @@ def main_xoptions(self, xoptions_list): | |||
| 470 | 470 | xoptions[opt] = True | |
| 471 | 471 | return xoptions | |
| 472 | 472 | ||
| 473 | - def _get_expected_config(self, env): | ||
| 473 | + def _get_expected_config_impl(self): | ||
| 474 | + env = remove_python_envvars() | ||
| 474 | 475 | code = textwrap.dedent(''' | |
| 475 | 476 | import json | |
| 476 | 477 | import sys | |
@@ -499,13 +500,19 @@ def _get_expected_config(self, env): | |||
| 499 | 500 | except json.JSONDecodeError: | |
| 500 | 501 | self.fail(f"fail to decode stdout: {stdout!r}") | |
| 501 | 502 | ||
| 503 | + def _get_expected_config(self): | ||
| 504 | + cls = InitConfigTests | ||
| 505 | + if cls.EXPECTED_CONFIG is None: | ||
| 506 | + cls.EXPECTED_CONFIG = self._get_expected_config_impl() | ||
| 507 | + | ||
| 508 | + # get a copy | ||
| 509 | + return {key: dict(value) | ||
| 510 | + for key, value in cls.EXPECTED_CONFIG.items()} | ||
| 511 | + | ||
| 502 | 512 | def get_expected_config(self, expected_preconfig, expected, env, api, | |
| 503 | 513 | modify_path_cb=None): | |
| 504 | 514 | cls = self.__class__ | |
| 505 | - if cls.EXPECTED_CONFIG is None: | ||
| 506 | - cls.EXPECTED_CONFIG = self._get_expected_config(env) | ||
| 507 | - configs = {key: dict(value) | ||
| 508 | - for key, value in self.EXPECTED_CONFIG.items()} | ||
| 515 | + configs = self._get_expected_config() | ||
| 509 | 516 | ||
| 510 | 517 | pre_config = configs['pre_config'] | |
| 511 | 518 | for key, value in expected_preconfig.items(): | |
@@ -553,9 +560,10 @@ def get_expected_config(self, expected_preconfig, expected, env, api, | |||
| 553 | 560 | if value is self.GET_DEFAULT_CONFIG: | |
| 554 | 561 | expected[key] = config[key] | |
| 555 | 562 | ||
| 556 | - prepend_path = expected['pythonpath_env'] | ||
| 557 | - if prepend_path is not None: | ||
| 558 | - expected['module_search_paths'] = [prepend_path, *expected['module_search_paths']] | ||
| 563 | + pythonpath_env = expected['pythonpath_env'] | ||
| 564 | + if pythonpath_env is not None: | ||
| 565 | + paths = pythonpath_env.split(os.path.pathsep) | ||
| 566 | + expected['module_search_paths'] = [*paths, *expected['module_search_paths']] | ||
| 559 | 567 | if modify_path_cb is not None: | |
| 560 | 568 | expected['module_search_paths'] = expected['module_search_paths'].copy() | |
| 561 | 569 | modify_path_cb(expected['module_search_paths']) | |
@@ -604,8 +612,11 @@ def check_global_config(self, configs): | |||
| 604 | 612 | ||
| 605 | 613 | def check_all_configs(self, testname, expected_config=None, | |
| 606 | 614 | expected_preconfig=None, modify_path_cb=None, stderr=None, | |
| 607 | - *, api): | ||
| 608 | - env = remove_python_envvars() | ||
| 615 | + *, api, env=None, ignore_stderr=False): | ||
| 616 | + new_env = remove_python_envvars() | ||
| 617 | + if env is not None: | ||
| 618 | + new_env.update(env) | ||
| 619 | + env = new_env | ||
| 609 | 620 | ||
| 610 | 621 | if api == API_ISOLATED: | |
| 611 | 622 | default_preconfig = self.PRE_CONFIG_ISOLATED | |
@@ -634,7 +645,7 @@ def check_all_configs(self, testname, expected_config=None, | |||
| 634 | 645 | out, err = self.run_embedded_interpreter(testname, env=env) | |
| 635 | 646 | if stderr is None and not expected_config['verbose']: | |
| 636 | 647 | stderr = "" | |
| 637 | - if stderr is not None: | ||
| 648 | + if stderr is not None and not ignore_stderr: | ||
| 638 | 649 | self.assertEqual(err.rstrip(), stderr) | |
| 639 | 650 | try: | |
| 640 | 651 | configs = json.loads(out) | |
@@ -966,6 +977,62 @@ def test_init_dont_parse_argv(self): | |||
| 966 | 977 | self.check_all_configs("test_init_dont_parse_argv", config, pre_config, | |
| 967 | 978 | api=API_PYTHON) | |
| 968 | 979 | ||
| 980 | + def test_init_setpath(self): | ||
| 981 | + # Test Py_SetProgramName() + Py_SetPath() | ||
| 982 | + config = self._get_expected_config() | ||
| 983 | + paths = config['config']['module_search_paths'] | ||
| 984 | + | ||
| 985 | + config = { | ||
| 986 | + 'module_search_paths': paths, | ||
| 987 | + 'prefix': '', | ||
| 988 | + 'base_prefix': '', | ||
| 989 | + 'exec_prefix': '', | ||
| 990 | + 'base_exec_prefix': '', | ||
| 991 | + } | ||
| 992 | + env = {'TESTPATH': os.path.pathsep.join(paths)} | ||
| 993 | + self.check_all_configs("test_init_setpath", config, | ||
| 994 | + api=API_COMPAT, env=env, | ||
| 995 | + ignore_stderr=True) | ||
| 996 | + | ||
| 997 | + def test_init_setpythonhome(self): | ||
| 998 | + # Test Py_SetPythonHome(home) + PYTHONPATH env var | ||
| 999 | + # + Py_SetProgramName() | ||
| 1000 | + config = self._get_expected_config() | ||
| 1001 | + paths = config['config']['module_search_paths'] | ||
| 1002 | + paths_str = os.path.pathsep.join(paths) | ||
| 1003 | + | ||
| 1004 | + for path in paths: | ||
| 1005 | + if not os.path.isdir(path): | ||
| 1006 | + continue | ||
| 1007 | + if os.path.exists(os.path.join(path, 'os.py')): | ||
| 1008 | + home = os.path.dirname(path) | ||
| 1009 | + break | ||
| 1010 | + else: | ||
| 1011 | + self.fail(f"Unable to find home in {paths!r}") | ||
| 1012 | + | ||
| 1013 | + prefix = exec_prefix = home | ||
| 1014 | + ver = sys.version_info | ||
| 1015 | + if MS_WINDOWS: | ||
| 1016 | + expected_paths = paths | ||
| 1017 | + else: | ||
| 1018 | + expected_paths = [ | ||
| 1019 | + os.path.join(prefix, 'lib', f'python{ver.major}{ver.minor}.zip'), | ||
| 1020 | + os.path.join(home, 'lib', f'python{ver.major}.{ver.minor}'), | ||
| 1021 | + os.path.join(home, 'lib', f'python{ver.major}.{ver.minor}/lib-dynload')] | ||
| 1022 | + | ||
| 1023 | + config = { | ||
| 1024 | + 'home': home, | ||
| 1025 | + 'module_search_paths': expected_paths, | ||
| 1026 | + 'prefix': prefix, | ||
| 1027 | + 'base_prefix': prefix, | ||
| 1028 | + 'exec_prefix': exec_prefix, | ||
| 1029 | + 'base_exec_prefix': exec_prefix, | ||
| 1030 | + 'pythonpath_env': paths_str, | ||
| 1031 | + } | ||
| 1032 | + env = {'TESTHOME': home, 'TESTPATH': paths_str} | ||
| 1033 | + self.check_all_configs("test_init_setpythonhome", config, | ||
| 1034 | + api=API_COMPAT, env=env) | ||
| 1035 | + | ||
| 969 | 1036 | ||
| 970 | 1037 | class AuditingTests(EmbeddingTestsMixin, unittest.TestCase): | |
| 971 | 1038 | def test_open_code_hook(self): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1012,12 +1012,12 @@ calculate_zip_path(PyCalculatePath *calculate, const wchar_t *prefix, | |||
| 1012 | 1012 | wchar_t *zip_path, size_t zip_path_len) | |
| 1013 | 1013 | { | |
| 1014 | 1014 | PyStatus status; | |
| 1015 | - if (safe_wcscpy(zip_path, prefix, zip_path_len) < 0) { | ||
| 1016 | - return PATHLEN_ERR(); | ||
| 1017 | - } | ||
| 1018 | 1015 | ||
| 1019 | 1016 | if (calculate->prefix_found > 0) { | |
| 1020 | 1017 | /* Use the reduced prefix returned by Py_GetPrefix() */ | |
| 1018 | + if (safe_wcscpy(zip_path, prefix, zip_path_len) < 0) { | ||
| 1019 | + return PATHLEN_ERR(); | ||
| 1020 | + } | ||
| 1021 | 1021 | reduce(zip_path); | |
| 1022 | 1022 | reduce(zip_path); | |
| 1023 | 1023 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -20,11 +20,12 @@ | |||
| 20 | 20 | * Executed via 'EmbeddingTests' in Lib/test/test_capi.py | |
| 21 | 21 | *********************************************************/ | |
| 22 | 22 | ||
| 23 | + /* Use path starting with "./" avoids a search along the PATH */ | ||
| 24 | + #define PROGRAM_NAME L"./_testembed" | ||
| 25 | + | ||
| 23 | 26 | static void _testembed_Py_Initialize(void) | |
| 24 | 27 | { | |
| 25 | - /* HACK: the "./" at front avoids a search along the PATH in | ||
| 26 | - Modules/getpath.c */ | ||
| 27 | - Py_SetProgramName(L"./_testembed"); | ||
| 28 | + Py_SetProgramName(PROGRAM_NAME); | ||
| 28 | 29 | Py_Initialize(); | |
| 29 | 30 | } | |
| 30 | 31 | ||
@@ -363,8 +364,7 @@ config_set_wide_string_list(PyConfig *config, PyWideStringList *list, | |||
| 363 | 364 | ||
| 364 | 365 | static void config_set_program_name(PyConfig *config) | |
| 365 | 366 | { | |
| 366 | - /* Use path starting with "./" avoids a search along the PATH */ | ||
| 367 | - const wchar_t *program_name = L"./_testembed"; | ||
| 367 | + const wchar_t *program_name = PROGRAM_NAME; | ||
| 368 | 368 | config_set_string(config, &config->program_name, program_name); | |
| 369 | 369 | } | |
| 370 | 370 | ||
@@ -1263,7 +1263,7 @@ static int _audit_hook_run(const char *eventName, PyObject *args, void *userData | |||
| 1263 | 1263 | static int test_audit_run_command(void) | |
| 1264 | 1264 | { | |
| 1265 | 1265 | AuditRunCommandTest test = {"cpython.run_command"}; | |
| 1266 | - wchar_t *argv[] = {L"./_testembed", L"-c", L"pass"}; | ||
| 1266 | + wchar_t *argv[] = {PROGRAM_NAME, L"-c", L"pass"}; | ||
| 1267 | 1267 | ||
| 1268 | 1268 | Py_IgnoreEnvironmentFlag = 0; | |
| 1269 | 1269 | PySys_AddAuditHook(_audit_hook_run, (void*)&test); | |
@@ -1274,7 +1274,7 @@ static int test_audit_run_command(void) | |||
| 1274 | 1274 | static int test_audit_run_file(void) | |
| 1275 | 1275 | { | |
| 1276 | 1276 | AuditRunCommandTest test = {"cpython.run_file"}; | |
| 1277 | - wchar_t *argv[] = {L"./_testembed", L"filename.py"}; | ||
| 1277 | + wchar_t *argv[] = {PROGRAM_NAME, L"filename.py"}; | ||
| 1278 | 1278 | ||
| 1279 | 1279 | Py_IgnoreEnvironmentFlag = 0; | |
| 1280 | 1280 | PySys_AddAuditHook(_audit_hook_run, (void*)&test); | |
@@ -1312,21 +1312,21 @@ static int run_audit_run_test(int argc, wchar_t **argv, void *test) | |||
| 1312 | 1312 | static int test_audit_run_interactivehook(void) | |
| 1313 | 1313 | { | |
| 1314 | 1314 | AuditRunCommandTest test = {"cpython.run_interactivehook", 10}; | |
| 1315 | - wchar_t *argv[] = {L"./_testembed"}; | ||
| 1315 | + wchar_t *argv[] = {PROGRAM_NAME}; | ||
| 1316 | 1316 | return run_audit_run_test(Py_ARRAY_LENGTH(argv), argv, &test); | |
| 1317 | 1317 | } | |
| 1318 | 1318 | ||
| 1319 | 1319 | static int test_audit_run_startup(void) | |
| 1320 | 1320 | { | |
| 1321 | 1321 | AuditRunCommandTest test = {"cpython.run_startup", 10}; | |
| 1322 | - wchar_t *argv[] = {L"./_testembed"}; | ||
| 1322 | + wchar_t *argv[] = {PROGRAM_NAME}; | ||
| 1323 | 1323 | return run_audit_run_test(Py_ARRAY_LENGTH(argv), argv, &test); | |
| 1324 | 1324 | } | |
| 1325 | 1325 | ||
| 1326 | 1326 | static int test_audit_run_stdin(void) | |
| 1327 | 1327 | { | |
| 1328 | 1328 | AuditRunCommandTest test = {"cpython.run_stdin"}; | |
| 1329 | - wchar_t *argv[] = {L"./_testembed"}; | ||
| 1329 | + wchar_t *argv[] = {PROGRAM_NAME}; | ||
| 1330 | 1330 | return run_audit_run_test(Py_ARRAY_LENGTH(argv), argv, &test); | |
| 1331 | 1331 | } | |
| 1332 | 1332 | ||
@@ -1423,6 +1423,88 @@ static int test_init_sys_add(void) | |||
| 1423 | 1423 | } | |
| 1424 | 1424 | ||
| 1425 | 1425 | ||
| 1426 | + static int test_init_setpath(void) | ||
| 1427 | + { | ||
| 1428 | + Py_SetProgramName(PROGRAM_NAME); | ||
| 1429 | + | ||
| 1430 | + char *env = getenv("TESTPATH"); | ||
| 1431 | + if (!env) { | ||
| 1432 | + fprintf(stderr, "missing TESTPATH env var\n"); | ||
| 1433 | + return 1; | ||
| 1434 | + } | ||
| 1435 | + wchar_t *path = Py_DecodeLocale(env, NULL); | ||
| 1436 | + if (path == NULL) { | ||
| 1437 | + fprintf(stderr, "failed to decode TESTPATH\n"); | ||
| 1438 | + return 1; | ||
| 1439 | + } | ||
| 1440 | + Py_SetPath(path); | ||
| 1441 | + PyMem_RawFree(path); | ||
| 1442 | + putenv("TESTPATH="); | ||
| 1443 | + | ||
| 1444 | + Py_Initialize(); | ||
| 1445 | + dump_config(); | ||
| 1446 | + Py_Finalize(); | ||
| 1447 | + return 0; | ||
| 1448 | + } | ||
| 1449 | + | ||
| 1450 | + | ||
| 1451 | + static int mysetenv(const char *name, const char *value) | ||
| 1452 | + { | ||
| 1453 | + size_t len = strlen(name) + 1 + strlen(value) + 1; | ||
| 1454 | + char *env = PyMem_RawMalloc(len); | ||
| 1455 | + if (env == NULL) { | ||
| 1456 | + fprintf(stderr, "out of memory\n"); | ||
| 1457 | + return -1; | ||
| 1458 | + } | ||
| 1459 | + strcpy(env, name); | ||
| 1460 | + strcat(env, "="); | ||
| 1461 | + strcat(env, value); | ||
| 1462 | + | ||
| 1463 | + putenv(env); | ||
| 1464 | + | ||
| 1465 | + /* Don't call PyMem_RawFree(env), but leak env memory block: | ||
| 1466 | + putenv() does not copy the string. */ | ||
| 1467 | + | ||
| 1468 | + return 0; | ||
| 1469 | + } | ||
| 1470 | + | ||
| 1471 | + | ||
| 1472 | + static int test_init_setpythonhome(void) | ||
| 1473 | + { | ||
| 1474 | + char *env = getenv("TESTHOME"); | ||
| 1475 | + if (!env) { | ||
| 1476 | + fprintf(stderr, "missing TESTHOME env var\n"); | ||
| 1477 | + return 1; | ||
| 1478 | + } | ||
| 1479 | + wchar_t *home = Py_DecodeLocale(env, NULL); | ||
| 1480 | + if (home == NULL) { | ||
| 1481 | + fprintf(stderr, "failed to decode TESTHOME\n"); | ||
| 1482 | + return 1; | ||
| 1483 | + } | ||
| 1484 | + Py_SetPythonHome(home); | ||
| 1485 | + PyMem_RawFree(home); | ||
| 1486 | + putenv("TESTHOME="); | ||
| 1487 | + | ||
| 1488 | + char *path = getenv("TESTPATH"); | ||
| 1489 | + if (!path) { | ||
| 1490 | + fprintf(stderr, "missing TESTPATH env var\n"); | ||
| 1491 | + return 1; | ||
| 1492 | + } | ||
| 1493 | + | ||
| 1494 | + if (mysetenv("PYTHONPATH", path) < 0) { | ||
| 1495 | + return 1; | ||
| 1496 | + } | ||
| 1497 | + putenv("TESTPATH="); | ||
| 1498 | + | ||
| 1499 | + Py_SetProgramName(PROGRAM_NAME); | ||
| 1500 | + | ||
| 1501 | + Py_Initialize(); | ||
| 1502 | + dump_config(); | ||
| 1503 | + Py_Finalize(); | ||
| 1504 | + return 0; | ||
| 1505 | + } | ||
| 1506 | + | ||
| 1507 | + | ||
| 1426 | 1508 | static void configure_init_main(PyConfig *config) | |
| 1427 | 1509 | { | |
| 1428 | 1510 | wchar_t* argv[] = { | |
@@ -1559,7 +1641,10 @@ static struct TestCase TestCases[] = { | |||
| 1559 | 1641 | {"test_init_run_main", test_init_run_main}, | |
| 1560 | 1642 | {"test_init_main", test_init_main}, | |
| 1561 | 1643 | {"test_init_sys_add", test_init_sys_add}, | |
| 1644 | + {"test_init_setpath", test_init_setpath}, | ||
| 1645 | + {"test_init_setpythonhome", test_init_setpythonhome}, | ||
| 1562 | 1646 | {"test_run_main", test_run_main}, | |
| 1647 | + | ||
| 1563 | 1648 | {"test_open_code_hook", test_open_code_hook}, | |
| 1564 | 1649 | {"test_audit", test_audit}, | |
| 1565 | 1650 | {"test_audit_subinterpreter", test_audit_subinterpreter}, | |
| Back | FazBrowse Home | New Git URL |
0 commit comments