11
11
import sys
12
12
13
13
14
+ MS_WINDOWS = (os .name == 'nt' )
15
+
16
+
14
17
class EmbeddingTestsMixin :
15
18
def setUp (self ):
16
19
here = os .path .abspath (__file__ )
17
20
basepath = os .path .dirname (os .path .dirname (os .path .dirname (here )))
18
21
exename = "_testembed"
19
- if sys . platform . startswith ( "win" ) :
22
+ if MS_WINDOWS :
20
23
ext = ("_d" if "_d" in sys .executable else "" ) + ".exe"
21
24
exename += ext
22
25
exepath = os .path .dirname (sys .executable )
@@ -38,7 +41,7 @@ def run_embedded_interpreter(self, *args, env=None):
38
41
"""Runs a test in the embedded interpreter"""
39
42
cmd = [self .test_exe ]
40
43
cmd .extend (args )
41
- if env is not None and sys . platform == 'win32' :
44
+ if env is not None and MS_WINDOWS :
42
45
# Windows requires at least the SYSTEMROOT environment variable to
43
46
# start Python.
44
47
env = env .copy ()
@@ -199,7 +202,7 @@ def test_pre_initialization_api(self):
199
202
"""
200
203
env = dict (os .environ , PYTHONPATH = os .pathsep .join (sys .path ))
201
204
out , err = self .run_embedded_interpreter ("pre_initialization_api" , env = env )
202
- if sys . platform == "win32" :
205
+ if MS_WINDOWS :
203
206
expected_path = self .test_exe
204
207
else :
205
208
expected_path = os .path .join (os .getcwd (), "spam" )
@@ -253,25 +256,14 @@ def test_initialize_pymain(self):
253
256
254
257
class InitConfigTests (EmbeddingTestsMixin , unittest .TestCase ):
255
258
maxDiff = 4096
256
- UTF8_MODE_ERRORS = ('surrogatepass' if sys . platform == 'win32'
257
- else 'surrogateescape' )
258
- # FIXME: untested core configuration variables
259
+ UTF8_MODE_ERRORS = ('surrogatepass' if MS_WINDOWS else 'surrogateescape' )
260
+
261
+ # core config
259
262
UNTESTED_CORE_CONFIG = (
260
- 'base_exec_prefix' ,
261
- 'base_prefix' ,
263
+ # FIXME: untested core configuration variables
262
264
'dll_path' ,
263
- 'exec_prefix' ,
264
265
'executable' ,
265
- 'home' ,
266
- 'legacy_windows_fs_encoding' ,
267
- 'legacy_windows_stdio' ,
268
- 'module_search_path_env' ,
269
266
'module_search_paths' ,
270
- 'prefix' ,
271
- )
272
- # FIXME: untested main configuration variables
273
- UNTESTED_MAIN_CONFIG = (
274
- 'module_search_path' ,
275
267
)
276
268
DEFAULT_CORE_CONFIG = {
277
269
'install_signal_handlers' : 1 ,
@@ -304,6 +296,13 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
304
296
'xoptions' : [],
305
297
'warnoptions' : [],
306
298
299
+ 'module_search_path_env' : None ,
300
+ '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 ,
305
+
307
306
'isolated' : 0 ,
308
307
'site_import' : 1 ,
309
308
'bytes_warning' : 0 ,
@@ -325,6 +324,63 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
325
324
'_check_hash_pycs_mode' : 'default' ,
326
325
'_frozen' : 0 ,
327
326
}
327
+ if MS_WINDOWS :
328
+ DEFAULT_CORE_CONFIG .update ({
329
+ 'legacy_windows_fs_encoding' : 0 ,
330
+ 'legacy_windows_stdio' : 0 ,
331
+ })
332
+
333
+ # main config
334
+ UNTESTED_MAIN_CONFIG = (
335
+ # FIXME: untested main configuration variables
336
+ 'module_search_path' ,
337
+ )
338
+ COPY_MAIN_CONFIG = (
339
+ # Copy core config to main config for expected values
340
+ 'argv' ,
341
+ 'base_exec_prefix' ,
342
+ 'base_prefix' ,
343
+ 'exec_prefix' ,
344
+ 'executable' ,
345
+ 'install_signal_handlers' ,
346
+ 'prefix' ,
347
+ 'pycache_prefix' ,
348
+ 'warnoptions' ,
349
+ # xoptions is created from core_config in check_main_config()
350
+ )
351
+
352
+ # global config
353
+ DEFAULT_GLOBAL_CONFIG = {
354
+ 'Py_HasFileSystemDefaultEncoding' : 0 ,
355
+ 'Py_HashRandomizationFlag' : 1 ,
356
+ '_Py_HasFileSystemDefaultEncodeErrors' : 0 ,
357
+ }
358
+ COPY_GLOBAL_CONFIG = [
359
+ # Copy core config to global config for expected values
360
+ # True means that the core config value is inverted (0 => 1 and 1 => 0)
361
+ ('Py_BytesWarningFlag' , 'bytes_warning' ),
362
+ ('Py_DebugFlag' , 'parser_debug' ),
363
+ ('Py_DontWriteBytecodeFlag' , 'write_bytecode' , True ),
364
+ ('Py_FileSystemDefaultEncodeErrors' , 'filesystem_errors' ),
365
+ ('Py_FileSystemDefaultEncoding' , 'filesystem_encoding' ),
366
+ ('Py_FrozenFlag' , '_frozen' ),
367
+ ('Py_IgnoreEnvironmentFlag' , 'use_environment' , True ),
368
+ ('Py_InspectFlag' , 'inspect' ),
369
+ ('Py_InteractiveFlag' , 'interactive' ),
370
+ ('Py_IsolatedFlag' , 'isolated' ),
371
+ ('Py_NoSiteFlag' , 'site_import' , True ),
372
+ ('Py_NoUserSiteDirectory' , 'user_site_directory' , True ),
373
+ ('Py_OptimizeFlag' , 'optimization_level' ),
374
+ ('Py_QuietFlag' , 'quiet' ),
375
+ ('Py_UTF8Mode' , 'utf8_mode' ),
376
+ ('Py_UnbufferedStdioFlag' , 'buffered_stdio' , True ),
377
+ ('Py_VerboseFlag' , 'verbose' ),
378
+ ]
379
+ if MS_WINDOWS :
380
+ COPY_GLOBAL_CONFIG .extend ((
381
+ ('Py_LegacyWindowsFSEncodingFlag' , 'legacy_windows_fs_encoding' ),
382
+ ('Py_LegacyWindowsStdioFlag' , 'legacy_windows_stdio' ),
383
+ ))
328
384
329
385
def get_stdio_encoding (self , env ):
330
386
code = 'import sys; print(sys.stdout.encoding, sys.stdout.errors)'
@@ -355,18 +411,31 @@ def get_filesystem_encoding(self, isolated, env):
355
411
out = proc .stdout .rstrip ()
356
412
return out .split ()
357
413
358
- def check_config (self , testname , expected ):
359
- expected = dict (self .DEFAULT_CORE_CONFIG , ** expected )
414
+ def main_xoptions (self , xoptions_list ):
415
+ xoptions = {}
416
+ for opt in xoptions_list :
417
+ if '=' in opt :
418
+ key , value = opt .split ('=' , 1 )
419
+ xoptions [key ] = value
420
+ else :
421
+ xoptions [opt ] = True
422
+ return xoptions
360
423
361
- env = dict (os .environ )
362
- for key in list (env ):
363
- if key .startswith ('PYTHON' ):
364
- del env [key ]
365
- # Disable C locale coercion and UTF-8 mode to not depend
366
- # on the current locale
367
- env ['PYTHONCOERCECLOCALE' ] = '0'
368
- env ['PYTHONUTF8' ] = '0'
424
+ def check_main_config (self , config ):
425
+ core_config = config ['core_config' ]
426
+ main_config = config ['main_config' ]
427
+
428
+ # main config
429
+ for key in self .UNTESTED_MAIN_CONFIG :
430
+ del main_config [key ]
369
431
432
+ expected_main = {}
433
+ for key in self .COPY_MAIN_CONFIG :
434
+ expected_main [key ] = core_config [key ]
435
+ expected_main ['xoptions' ] = self .main_xoptions (core_config ['xoptions' ])
436
+ self .assertEqual (main_config , expected_main )
437
+
438
+ def check_core_config (self , config , expected , env ):
370
439
if expected ['stdio_encoding' ] is None or expected ['stdio_errors' ] is None :
371
440
res = self .get_stdio_encoding (env )
372
441
if expected ['stdio_encoding' ] is None :
@@ -380,74 +449,45 @@ def check_config(self, testname, expected):
380
449
if expected ['filesystem_errors' ] is None :
381
450
expected ['filesystem_errors' ] = res [1 ]
382
451
383
- out , err = self .run_embedded_interpreter (testname , env = env )
384
- # Ignore err
452
+ core_config = dict (config ['core_config' ])
453
+ for key in self .UNTESTED_CORE_CONFIG :
454
+ core_config .pop (key , None )
455
+ self .assertEqual (core_config , expected )
385
456
386
- config = json . loads ( out )
457
+ def check_global_config ( self , config ):
387
458
core_config = config ['core_config' ]
388
- executable = core_config ['executable' ]
389
- main_config = config ['main_config' ]
390
459
391
- for key in self .UNTESTED_MAIN_CONFIG :
392
- del main_config [key ]
393
-
394
- expected_main = {
395
- 'install_signal_handlers' : core_config ['install_signal_handlers' ],
396
- 'argv' : [],
397
- 'prefix' : sys .prefix ,
398
- 'executable' : core_config ['executable' ],
399
- 'base_prefix' : sys .base_prefix ,
400
- 'base_exec_prefix' : sys .base_exec_prefix ,
401
- 'warnoptions' : core_config ['warnoptions' ],
402
- 'xoptions' : {},
403
- 'pycache_prefix' : core_config ['pycache_prefix' ],
404
- 'exec_prefix' : core_config ['exec_prefix' ],
405
- }
406
- self .assertEqual (main_config , expected_main )
407
-
408
-
409
- copy_global_config = [
410
- ('Py_BytesWarningFlag' , 'bytes_warning' ),
411
- ('Py_DebugFlag' , 'parser_debug' ),
412
- ('Py_DontWriteBytecodeFlag' , 'write_bytecode' , True ),
413
- ('Py_FileSystemDefaultEncodeErrors' , 'filesystem_errors' ),
414
- ('Py_FileSystemDefaultEncoding' , 'filesystem_encoding' ),
415
- ('Py_FrozenFlag' , '_frozen' ),
416
- ('Py_IgnoreEnvironmentFlag' , 'use_environment' , True ),
417
- ('Py_InspectFlag' , 'inspect' ),
418
- ('Py_InteractiveFlag' , 'interactive' ),
419
- ('Py_IsolatedFlag' , 'isolated' ),
420
- ('Py_NoSiteFlag' , 'site_import' , True ),
421
- ('Py_NoUserSiteDirectory' , 'user_site_directory' , True ),
422
- ('Py_OptimizeFlag' , 'optimization_level' ),
423
- ('Py_QuietFlag' , 'quiet' ),
424
- ('Py_UTF8Mode' , 'utf8_mode' ),
425
- ('Py_UnbufferedStdioFlag' , 'buffered_stdio' , True ),
426
- ('Py_VerboseFlag' , 'verbose' ),
427
- ]
428
- if os .name == 'nt' :
429
- copy_global_config .extend ((
430
- ('Py_LegacyWindowsFSEncodingFlag' , 'legacy_windows_fs_encoding' ),
431
- ('Py_LegacyWindowsStdioFlag' , 'legacy_windows_stdio' ),
432
- ))
433
-
434
- expected_global = {}
435
- for item in copy_global_config :
460
+ expected_global = dict (self .DEFAULT_GLOBAL_CONFIG )
461
+ for item in self .COPY_GLOBAL_CONFIG :
436
462
if len (item ) == 3 :
437
463
global_key , core_key , opposite = item
438
464
expected_global [global_key ] = 0 if core_config [core_key ] else 1
439
465
else :
440
466
global_key , core_key = item
441
467
expected_global [global_key ] = core_config [core_key ]
442
468
443
- expected_global ['Py_HasFileSystemDefaultEncoding' ] = 0
444
- expected_global ['_Py_HasFileSystemDefaultEncodeErrors' ] = 0
445
- expected_global ['Py_HashRandomizationFlag' ] = 1
446
469
self .assertEqual (config ['global_config' ], expected_global )
447
470
448
- for key in self .UNTESTED_CORE_CONFIG :
449
- core_config .pop (key , None )
450
- self .assertEqual (core_config , expected )
471
+ def check_config (self , testname , expected ):
472
+ expected = dict (self .DEFAULT_CORE_CONFIG , ** expected )
473
+
474
+ env = dict (os .environ )
475
+ # Remove PYTHON* environment variables to get deterministic environment
476
+ for key in list (env ):
477
+ if key .startswith ('PYTHON' ):
478
+ del env [key ]
479
+ # Disable C locale coercion and UTF-8 mode to not depend
480
+ # on the current locale
481
+ env ['PYTHONCOERCECLOCALE' ] = '0'
482
+ env ['PYTHONUTF8' ] = '0'
483
+
484
+ out , err = self .run_embedded_interpreter (testname , env = env )
485
+ # Ignore err
486
+ config = json .loads (out )
487
+
488
+ self .check_core_config (config , expected , env )
489
+ self .check_main_config (config )
490
+ self .check_global_config (config )
451
491
452
492
def test_init_default_config (self ):
453
493
self .check_config ("init_default_config" , {})
@@ -495,7 +535,10 @@ def test_init_from_config(self):
495
535
496
536
'pycache_prefix' : 'conf_pycache_prefix' ,
497
537
'program_name' : './conf_program_name' ,
538
+ 'argv' : ['-c' , 'pass' ],
498
539
'program' : 'conf_program' ,
540
+ 'xoptions' : ['core_xoption1=3' , 'core_xoption2=' , 'core_xoption3' ],
541
+ 'warnoptions' : ['default' , 'error::ResourceWarning' ],
499
542
500
543
'site_import' : 0 ,
501
544
'bytes_warning' : 1 ,
0 commit comments