9
9
import re
10
10
import subprocess
11
11
import sys
12
+ import textwrap
12
13
13
14
14
15
MS_WINDOWS = (os .name == 'nt' )
@@ -265,6 +266,8 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
265
266
'executable' ,
266
267
'module_search_paths' ,
267
268
)
269
+ # Mark config which should be get by get_default_config()
270
+ GET_DEFAULT_CONFIG = object ()
268
271
DEFAULT_CORE_CONFIG = {
269
272
'install_signal_handlers' : 1 ,
270
273
'use_environment' : 1 ,
@@ -280,9 +283,8 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
280
283
'dump_refs' : 0 ,
281
284
'malloc_stats' : 0 ,
282
285
283
- # None means that the value is get by get_locale_encoding()
284
- 'filesystem_encoding' : None ,
285
- 'filesystem_errors' : None ,
286
+ 'filesystem_encoding' : GET_DEFAULT_CONFIG ,
287
+ 'filesystem_errors' : GET_DEFAULT_CONFIG ,
286
288
287
289
'utf8_mode' : 0 ,
288
290
'coerce_c_locale' : 0 ,
@@ -298,10 +300,11 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
298
300
299
301
'module_search_path_env' : None ,
300
302
'home' : None ,
301
- 'prefix' : sys .prefix ,
302
- 'base_prefix' : sys .base_prefix ,
303
- 'exec_prefix' : sys .exec_prefix ,
304
- 'base_exec_prefix' : sys .base_exec_prefix ,
303
+
304
+ 'prefix' : GET_DEFAULT_CONFIG ,
305
+ 'base_prefix' : GET_DEFAULT_CONFIG ,
306
+ 'exec_prefix' : GET_DEFAULT_CONFIG ,
307
+ 'base_exec_prefix' : GET_DEFAULT_CONFIG ,
305
308
306
309
'isolated' : 0 ,
307
310
'site_import' : 1 ,
@@ -316,9 +319,8 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
316
319
'user_site_directory' : 1 ,
317
320
'buffered_stdio' : 1 ,
318
321
319
- # None means that the value is get by get_stdio_encoding()
320
- 'stdio_encoding' : None ,
321
- 'stdio_errors' : None ,
322
+ 'stdio_encoding' : GET_DEFAULT_CONFIG ,
323
+ 'stdio_errors' : GET_DEFAULT_CONFIG ,
322
324
323
325
'_install_importlib' : 1 ,
324
326
'_check_hash_pycs_mode' : 'default' ,
@@ -379,35 +381,6 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
379
381
('Py_LegacyWindowsStdioFlag' , 'legacy_windows_stdio' ),
380
382
))
381
383
382
- def get_stdio_encoding (self , env ):
383
- code = 'import sys; print(sys.stdout.encoding, sys.stdout.errors)'
384
- args = (sys .executable , '-c' , code )
385
- proc = subprocess .run (args , env = env , text = True ,
386
- stdout = subprocess .PIPE ,
387
- stderr = subprocess .STDOUT )
388
- if proc .returncode :
389
- raise Exception (f"failed to get the stdio encoding: stdout={ proc .stdout !r} " )
390
- out = proc .stdout .rstrip ()
391
- return out .split ()
392
-
393
- def get_filesystem_encoding (self , isolated , env ):
394
- code = ('import codecs, locale, sys; '
395
- 'print(sys.getfilesystemencoding(), '
396
- 'sys.getfilesystemencodeerrors())' )
397
- args = (sys .executable , '-c' , code )
398
- env = dict (env )
399
- if not isolated :
400
- env ['PYTHONCOERCECLOCALE' ] = '0'
401
- env ['PYTHONUTF8' ] = '0'
402
- proc = subprocess .run (args , text = True , env = env ,
403
- stdout = subprocess .PIPE ,
404
- stderr = subprocess .PIPE )
405
- if proc .returncode :
406
- raise Exception (f"failed to get the locale encoding: "
407
- f"stdout={ proc .stdout !r} stderr={ proc .stderr !r} " )
408
- out = proc .stdout .rstrip ()
409
- return out .split ()
410
-
411
384
def main_xoptions (self , xoptions_list ):
412
385
xoptions = {}
413
386
for opt in xoptions_list :
@@ -423,27 +396,61 @@ def check_main_config(self, config):
423
396
main_config = config ['main_config' ]
424
397
425
398
# main config
426
- expected_main = {}
399
+ expected = {}
427
400
for key in self .COPY_MAIN_CONFIG :
428
- expected_main [key ] = core_config [key ]
429
- expected_main ['module_search_path' ] = core_config ['module_search_paths' ]
430
- expected_main ['xoptions' ] = self .main_xoptions (core_config ['xoptions' ])
431
- self .assertEqual (main_config , expected_main )
401
+ expected [key ] = core_config [key ]
402
+ expected ['module_search_path' ] = core_config ['module_search_paths' ]
403
+ expected ['xoptions' ] = self .main_xoptions (core_config ['xoptions' ])
404
+ self .assertEqual (main_config , expected )
432
405
433
- def check_core_config (self , config , expected , env ):
434
- if expected ['stdio_encoding' ] is None or expected ['stdio_errors' ] is None :
435
- res = self .get_stdio_encoding (env )
436
- if expected ['stdio_encoding' ] is None :
437
- expected ['stdio_encoding' ] = res [0 ]
438
- if expected ['stdio_errors' ] is None :
439
- expected ['stdio_errors' ] = res [1 ]
440
- if expected ['filesystem_encoding' ] is None or expected ['filesystem_errors' ] is None :
441
- res = self .get_filesystem_encoding (expected ['isolated' ], env )
442
- if expected ['filesystem_encoding' ] is None :
443
- expected ['filesystem_encoding' ] = res [0 ]
444
- if expected ['filesystem_errors' ] is None :
445
- expected ['filesystem_errors' ] = res [1 ]
406
+ def get_expected_config (self , expected , env ):
407
+ expected = dict (self .DEFAULT_CORE_CONFIG , ** expected )
446
408
409
+ code = textwrap .dedent ('''
410
+ import json
411
+ import locale
412
+ import sys
413
+
414
+ data = {
415
+ 'stdio_encoding': sys.stdout.encoding,
416
+ 'stdio_errors': sys.stdout.errors,
417
+ 'prefix': sys.prefix,
418
+ 'base_prefix': sys.base_prefix,
419
+ 'exec_prefix': sys.exec_prefix,
420
+ 'base_exec_prefix': sys.base_exec_prefix,
421
+ 'filesystem_encoding': sys.getfilesystemencoding(),
422
+ 'filesystem_errors': sys.getfilesystemencodeerrors(),
423
+ }
424
+
425
+ data = json.dumps(data)
426
+ data = data.encode('utf-8')
427
+ sys.stdout.buffer.write(data)
428
+ sys.stdout.buffer.flush()
429
+ ''' )
430
+
431
+ # Use -S to not import the site module: get the proper configuration
432
+ # when test_embed is run from a venv (bpo-35313)
433
+ args = (sys .executable , '-S' , '-c' , code )
434
+ env = dict (env )
435
+ if not expected ['isolated' ]:
436
+ env ['PYTHONCOERCECLOCALE' ] = '0'
437
+ env ['PYTHONUTF8' ] = '0'
438
+ proc = subprocess .run (args , env = env ,
439
+ stdout = subprocess .PIPE ,
440
+ stderr = subprocess .STDOUT )
441
+ if proc .returncode :
442
+ raise Exception (f"failed to get the default config: "
443
+ f"stdout={ proc .stdout !r} stderr={ proc .stderr !r} " )
444
+ stdout = proc .stdout .decode ('utf-8' )
445
+ config = json .loads (stdout )
446
+
447
+ for key , value in expected .items ():
448
+ if value is self .GET_DEFAULT_CONFIG :
449
+ expected [key ] = config [key ]
450
+ return expected
451
+
452
+ def check_core_config (self , config , expected , env ):
453
+ expected = self .get_expected_config (expected , env )
447
454
core_config = dict (config ['core_config' ])
448
455
for key in self .UNTESTED_CORE_CONFIG :
449
456
core_config .pop (key , None )
@@ -452,20 +459,18 @@ def check_core_config(self, config, expected, env):
452
459
def check_global_config (self , config ):
453
460
core_config = config ['core_config' ]
454
461
455
- expected_global = dict (self .DEFAULT_GLOBAL_CONFIG )
462
+ expected = dict (self .DEFAULT_GLOBAL_CONFIG )
456
463
for item in self .COPY_GLOBAL_CONFIG :
457
464
if len (item ) == 3 :
458
465
global_key , core_key , opposite = item
459
- expected_global [global_key ] = 0 if core_config [core_key ] else 1
466
+ expected [global_key ] = 0 if core_config [core_key ] else 1
460
467
else :
461
468
global_key , core_key = item
462
- expected_global [global_key ] = core_config [core_key ]
469
+ expected [global_key ] = core_config [core_key ]
463
470
464
- self .assertEqual (config ['global_config' ], expected_global )
471
+ self .assertEqual (config ['global_config' ], expected )
465
472
466
473
def check_config (self , testname , expected ):
467
- expected = dict (self .DEFAULT_CORE_CONFIG , ** expected )
468
-
469
474
env = dict (os .environ )
470
475
# Remove PYTHON* environment variables to get deterministic environment
471
476
for key in list (env ):
0 commit comments