@@ -470,7 +470,8 @@ def main_xoptions(self, xoptions_list):
470470 xoptions [opt ] = True
471471 return xoptions
472472
473- def _get_expected_config (self , env ):
473+ def _get_expected_config_impl (self ):
474+ env = remove_python_envvars ()
474475 code = textwrap .dedent ('''
475476 import json
476477 import sys
@@ -499,13 +500,19 @@ def _get_expected_config(self, env):
499500 except json .JSONDecodeError :
500501 self .fail (f"fail to decode stdout: { stdout !r} " )
501502
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+
502512 def get_expected_config (self , expected_preconfig , expected , env , api ,
503513 modify_path_cb = None ):
504514 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 ()
509516
510517 pre_config = configs ['pre_config' ]
511518 for key , value in expected_preconfig .items ():
@@ -553,9 +560,10 @@ def get_expected_config(self, expected_preconfig, expected, env, api,
553560 if value is self .GET_DEFAULT_CONFIG :
554561 expected [key ] = config [key ]
555562
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' ]]
559567 if modify_path_cb is not None :
560568 expected ['module_search_paths' ] = expected ['module_search_paths' ].copy ()
561569 modify_path_cb (expected ['module_search_paths' ])
@@ -604,8 +612,11 @@ def check_global_config(self, configs):
604612
605613 def check_all_configs (self , testname , expected_config = None ,
606614 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
609620
610621 if api == API_ISOLATED :
611622 default_preconfig = self .PRE_CONFIG_ISOLATED
@@ -634,7 +645,7 @@ def check_all_configs(self, testname, expected_config=None,
634645 out , err = self .run_embedded_interpreter (testname , env = env )
635646 if stderr is None and not expected_config ['verbose' ]:
636647 stderr = ""
637- if stderr is not None :
648+ if stderr is not None and not ignore_stderr :
638649 self .assertEqual (err .rstrip (), stderr )
639650 try :
640651 configs = json .loads (out )
@@ -966,6 +977,62 @@ def test_init_dont_parse_argv(self):
966977 self .check_all_configs ("test_init_dont_parse_argv" , config , pre_config ,
967978 api = API_PYTHON )
968979
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+
9691036
9701037class AuditingTests (EmbeddingTestsMixin , unittest .TestCase ):
9711038 def test_open_code_hook (self ):
0 commit comments