10
10
import sys
11
11
12
12
13
+ MS_WINDOWS = (os .name == 'nt' )
14
+
15
+
13
16
class EmbeddingTestsMixin :
14
17
def setUp (self ):
15
18
here = os .path .abspath (__file__ )
16
19
basepath = os .path .dirname (os .path .dirname (os .path .dirname (here )))
17
20
exename = "_testembed"
18
- if sys . platform . startswith ( "win" ) :
21
+ if MS_WINDOWS :
19
22
ext = ("_d" if "_d" in sys .executable else "" ) + ".exe"
20
23
exename += ext
21
24
exepath = os .path .dirname (sys .executable )
@@ -37,7 +40,7 @@ def run_embedded_interpreter(self, *args, env=None):
37
40
"""Runs a test in the embedded interpreter"""
38
41
cmd = [self .test_exe ]
39
42
cmd .extend (args )
40
- if env is not None and sys . platform == 'win32' :
43
+ if env is not None and MS_WINDOWS :
41
44
# Windows requires at least the SYSTEMROOT environment variable to
42
45
# start Python.
43
46
env = env .copy ()
@@ -198,7 +201,7 @@ def test_pre_initialization_api(self):
198
201
"""
199
202
env = dict (os .environ , PYTHONPATH = os .pathsep .join (sys .path ))
200
203
out , err = self .run_embedded_interpreter ("pre_initialization_api" , env = env )
201
- if sys . platform == "win32" :
204
+ if MS_WINDOWS :
202
205
expected_path = self .test_exe
203
206
else :
204
207
expected_path = os .path .join (os .getcwd (), "spam" )
@@ -252,46 +255,15 @@ def test_initialize_pymain(self):
252
255
253
256
class InitConfigTests (EmbeddingTestsMixin , unittest .TestCase ):
254
257
maxDiff = 4096
255
- UTF8_MODE_ERRORS = ('surrogatepass' if sys . platform == 'win32'
256
- else 'surrogateescape' )
257
- # FIXME: untested core configuration variables
258
+ UTF8_MODE_ERRORS = ('surrogatepass' if MS_WINDOWS else 'surrogateescape' )
259
+
260
+ # core config
258
261
UNTESTED_CORE_CONFIG = (
259
- 'base_exec_prefix' ,
260
- 'base_prefix' ,
261
- 'exec_prefix' ,
262
+ # FIXME: untested core configuration variables
263
+ 'dll_path' ,
262
264
'executable' ,
263
- 'home' ,
264
- 'module_search_path_env' ,
265
265
'module_search_paths' ,
266
- 'prefix' ,
267
- )
268
- # FIXME: untested main configuration variables
269
- UNTESTED_MAIN_CONFIG = (
270
- 'module_search_path' ,
271
266
)
272
- DEFAULT_GLOBAL_CONFIG = {
273
- 'Py_BytesWarningFlag' : 0 ,
274
- 'Py_DebugFlag' : 0 ,
275
- 'Py_DontWriteBytecodeFlag' : 0 ,
276
- 'Py_FrozenFlag' : 0 ,
277
- 'Py_HasFileSystemDefaultEncoding' : 0 ,
278
- 'Py_HashRandomizationFlag' : 1 ,
279
- 'Py_InspectFlag' : 0 ,
280
- 'Py_InteractiveFlag' : 0 ,
281
- 'Py_IsolatedFlag' : 0 ,
282
- 'Py_NoSiteFlag' : 0 ,
283
- 'Py_NoUserSiteDirectory' : 0 ,
284
- 'Py_OptimizeFlag' : 0 ,
285
- 'Py_QuietFlag' : 0 ,
286
- 'Py_UnbufferedStdioFlag' : 0 ,
287
- 'Py_VerboseFlag' : 0 ,
288
- }
289
- if os .name == 'nt' :
290
- DEFAULT_GLOBAL_CONFIG ['Py_LegacyWindowsFSEncodingFlag' ] = 0
291
- DEFAULT_GLOBAL_CONFIG ['Py_LegacyWindowsStdioFlag' ] = 0
292
- if sys .platform in ('win32' , 'darwin' ):
293
- DEFAULT_GLOBAL_CONFIG ['Py_HasFileSystemDefaultEncoding' ] = 1
294
-
295
267
DEFAULT_CORE_CONFIG = {
296
268
'install_signal_handlers' : 1 ,
297
269
'ignore_environment' : 0 ,
@@ -318,9 +290,72 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
318
290
'xoptions' : [],
319
291
'warnoptions' : [],
320
292
293
+ 'module_search_path_env' : None ,
294
+ 'home' : None ,
295
+ 'prefix' : sys .prefix ,
296
+ 'base_prefix' : sys .base_prefix ,
297
+ 'exec_prefix' : sys .exec_prefix ,
298
+ 'base_exec_prefix' : sys .base_exec_prefix ,
299
+
321
300
'_disable_importlib' : 0 ,
322
301
}
323
302
303
+ # main config
304
+ UNTESTED_MAIN_CONFIG = (
305
+ # FIXME: untested main configuration variables
306
+ 'module_search_path' ,
307
+ )
308
+ COPY_MAIN_CONFIG = (
309
+ # Copy core config to main config for expected values
310
+ 'argv' ,
311
+ 'base_exec_prefix' ,
312
+ 'base_prefix' ,
313
+ 'exec_prefix' ,
314
+ 'executable' ,
315
+ 'install_signal_handlers' ,
316
+ 'prefix' ,
317
+ 'warnoptions' ,
318
+ # xoptions is created from core_config in check_main_config()
319
+ )
320
+
321
+ # global config
322
+ UNTESTED_GLOBAL_CONFIG = (
323
+ # Py_HasFileSystemDefaultEncoding value depends on the LC_CTYPE locale
324
+ # and the platform. It is complex to test it, and it's value doesn't
325
+ # really matter.
326
+ 'Py_HasFileSystemDefaultEncoding' ,
327
+ )
328
+ DEFAULT_GLOBAL_CONFIG = {
329
+ 'Py_BytesWarningFlag' : 0 ,
330
+ 'Py_DebugFlag' : 0 ,
331
+ 'Py_DontWriteBytecodeFlag' : 0 ,
332
+ # None means that the value is get by get_filesystem_encoding()
333
+ 'Py_FileSystemDefaultEncodeErrors' : None ,
334
+ 'Py_FileSystemDefaultEncoding' : None ,
335
+ 'Py_FrozenFlag' : 0 ,
336
+ 'Py_HashRandomizationFlag' : 1 ,
337
+ 'Py_InspectFlag' : 0 ,
338
+ 'Py_InteractiveFlag' : 0 ,
339
+ 'Py_IsolatedFlag' : 0 ,
340
+ 'Py_NoSiteFlag' : 0 ,
341
+ 'Py_NoUserSiteDirectory' : 0 ,
342
+ 'Py_OptimizeFlag' : 0 ,
343
+ 'Py_QuietFlag' : 0 ,
344
+ 'Py_UnbufferedStdioFlag' : 0 ,
345
+ 'Py_VerboseFlag' : 0 ,
346
+ }
347
+ if MS_WINDOWS :
348
+ DEFAULT_GLOBAL_CONFIG .update ({
349
+ 'Py_LegacyWindowsFSEncodingFlag' : 0 ,
350
+ 'Py_LegacyWindowsStdioFlag' : 0 ,
351
+ })
352
+ COPY_GLOBAL_CONFIG = [
353
+ # Copy core config to global config for expected values
354
+ # True means that the core config value is inverted (0 => 1 and 1 => 0)
355
+ ('Py_IgnoreEnvironmentFlag' , 'ignore_environment' ),
356
+ ('Py_UTF8Mode' , 'utf8_mode' ),
357
+ ]
358
+
324
359
def get_filesystem_encoding (self , isolated , env ):
325
360
code = ('import codecs, locale, sys; '
326
361
'print(sys.getfilesystemencoding(), '
@@ -339,10 +374,65 @@ def get_filesystem_encoding(self, isolated, env):
339
374
out = proc .stdout .rstrip ()
340
375
return out .split ()
341
376
342
- def check_config (self , testname , expected , expected_global ):
377
+ def main_xoptions (self , xoptions_list ):
378
+ xoptions = {}
379
+ for opt in xoptions_list :
380
+ if '=' in opt :
381
+ key , value = opt .split ('=' , 1 )
382
+ xoptions [key ] = value
383
+ else :
384
+ xoptions [opt ] = True
385
+ return xoptions
386
+
387
+ def check_main_config (self , config ):
388
+ core_config = config ['core_config' ]
389
+ main_config = config ['main_config' ]
390
+
391
+ # main config
392
+ for key in self .UNTESTED_MAIN_CONFIG :
393
+ del main_config [key ]
394
+
395
+ expected_main = {}
396
+ for key in self .COPY_MAIN_CONFIG :
397
+ expected_main [key ] = core_config [key ]
398
+ expected_main ['xoptions' ] = self .main_xoptions (core_config ['xoptions' ])
399
+ self .assertEqual (main_config , expected_main )
400
+
401
+ def check_core_config (self , config , expected ):
343
402
expected = dict (self .DEFAULT_CORE_CONFIG , ** expected )
403
+ core_config = dict (config ['core_config' ])
404
+ for key in self .UNTESTED_CORE_CONFIG :
405
+ core_config .pop (key , None )
406
+ self .assertEqual (core_config , expected )
344
407
408
+ def check_global_config (self , config , expected , env ):
409
+ expected = dict (self .DEFAULT_GLOBAL_CONFIG , ** expected )
410
+
411
+ if expected ['Py_FileSystemDefaultEncoding' ] is None or expected ['Py_FileSystemDefaultEncodeErrors' ] is None :
412
+ res = self .get_filesystem_encoding (expected ['Py_IsolatedFlag' ], env )
413
+ if expected ['Py_FileSystemDefaultEncoding' ] is None :
414
+ expected ['Py_FileSystemDefaultEncoding' ] = res [0 ]
415
+ if expected ['Py_FileSystemDefaultEncodeErrors' ] is None :
416
+ expected ['Py_FileSystemDefaultEncodeErrors' ] = res [1 ]
417
+
418
+ core_config = config ['core_config' ]
419
+
420
+ for item in self .COPY_GLOBAL_CONFIG :
421
+ if len (item ) == 3 :
422
+ global_key , core_key , opposite = item
423
+ expected [global_key ] = 0 if core_config [core_key ] else 1
424
+ else :
425
+ global_key , core_key = item
426
+ expected [global_key ] = core_config [core_key ]
427
+
428
+ global_config = dict (config ['global_config' ])
429
+ for key in self .UNTESTED_GLOBAL_CONFIG :
430
+ del global_config [key ]
431
+ self .assertEqual (global_config , expected )
432
+
433
+ def check_config (self , testname , expected_core , expected_global ):
345
434
env = dict (os .environ )
435
+ # Remove PYTHON* environment variables to get deterministic environment
346
436
for key in list (env ):
347
437
if key .startswith ('PYTHON' ):
348
438
del env [key ]
@@ -353,47 +443,11 @@ def check_config(self, testname, expected, expected_global):
353
443
354
444
out , err = self .run_embedded_interpreter (testname , env = env )
355
445
# Ignore err
356
-
357
446
config = json .loads (out )
358
- core_config = config ['core_config' ]
359
- executable = core_config ['executable' ]
360
- main_config = config ['main_config' ]
361
-
362
- for key in self .UNTESTED_MAIN_CONFIG :
363
- del main_config [key ]
364
-
365
- expected_main = {
366
- 'install_signal_handlers' : core_config ['install_signal_handlers' ],
367
- 'argv' : [],
368
- 'prefix' : sys .prefix ,
369
- 'executable' : core_config ['executable' ],
370
- 'base_prefix' : sys .base_prefix ,
371
- 'base_exec_prefix' : sys .base_exec_prefix ,
372
- 'warnoptions' : core_config ['warnoptions' ],
373
- 'xoptions' : {},
374
- 'exec_prefix' : core_config ['exec_prefix' ],
375
- }
376
- self .assertEqual (main_config , expected_main )
377
-
378
- expected_global = dict (self .DEFAULT_GLOBAL_CONFIG , ** expected_global )
379
-
380
- if 'Py_FileSystemDefaultEncoding' not in expected_global :
381
- isolated = expected_global ['Py_IsolatedFlag' ]
382
- fs_encoding , fs_errors = self .get_filesystem_encoding (isolated , env )
383
- expected_global ['Py_FileSystemDefaultEncodeErrors' ] = fs_errors
384
- expected_global ['Py_FileSystemDefaultEncoding' ] = fs_encoding
385
447
386
- for global_key , core_key in (
387
- ('Py_UTF8Mode' , 'utf8_mode' ),
388
- ('Py_IgnoreEnvironmentFlag' , 'ignore_environment' ),
389
- ):
390
- expected_global [global_key ] = core_config [core_key ]
391
-
392
- self .assertEqual (config ['global_config' ], expected_global )
393
-
394
- for key in self .UNTESTED_CORE_CONFIG :
395
- core_config .pop (key , None )
396
- self .assertEqual (core_config , expected )
448
+ self .check_core_config (config , expected_core )
449
+ self .check_main_config (config )
450
+ self .check_global_config (config , expected_global , env )
397
451
398
452
def test_init_default_config (self ):
399
453
self .check_config ("init_default_config" , {}, {})
@@ -406,7 +460,6 @@ def test_init_global_config(self):
406
460
global_config = {
407
461
'Py_BytesWarningFlag' : 1 ,
408
462
'Py_DontWriteBytecodeFlag' : 1 ,
409
- 'Py_HasFileSystemDefaultEncoding' : 1 ,
410
463
'Py_FileSystemDefaultEncodeErrors' : self .UTF8_MODE_ERRORS ,
411
464
'Py_FileSystemDefaultEncoding' : 'utf-8' ,
412
465
'Py_InspectFlag' : 1 ,
@@ -436,12 +489,14 @@ def test_init_from_config(self):
436
489
'utf8_mode' : 1 ,
437
490
438
491
'program_name' : './conf_program_name' ,
492
+ 'argv' : ['-c' , 'pass' ],
439
493
'program' : 'conf_program' ,
494
+ 'xoptions' : ['core_xoption1=3' , 'core_xoption2=' , 'core_xoption3' ],
495
+ 'warnoptions' : ['default' , 'error::ResourceWarning' ],
440
496
441
497
'faulthandler' : 1 ,
442
498
}
443
499
global_config = {
444
- 'Py_HasFileSystemDefaultEncoding' : 1 ,
445
500
'Py_NoUserSiteDirectory' : 0 ,
446
501
}
447
502
self .check_config ("init_from_config" , core_config , global_config )
@@ -460,7 +515,6 @@ def test_init_env(self):
460
515
}
461
516
global_config = {
462
517
'Py_DontWriteBytecodeFlag' : 1 ,
463
- 'Py_HasFileSystemDefaultEncoding' : 1 ,
464
518
'Py_InspectFlag' : 1 ,
465
519
'Py_NoUserSiteDirectory' : 1 ,
466
520
'Py_OptimizeFlag' : 2 ,
0 commit comments