44import glob
55import importlib .util
66from importlib ._bootstrap_external import _get_sourcefile
7+ from importlib .machinery import (
8+ BuiltinImporter , ExtensionFileLoader , FrozenImporter , SourceFileLoader ,
9+ )
710import marshal
811import os
912import py_compile
4447 sys .dont_write_bytecode ,
4548 "test meaningful only when writing bytecode" )
4649
50+
51+ def _require_loader (module , loader , skip ):
52+ if isinstance (module , str ):
53+ module = __import__ (module )
54+
55+ MODULE_KINDS = {
56+ BuiltinImporter : 'built-in' ,
57+ ExtensionFileLoader : 'extension' ,
58+ FrozenImporter : 'frozen' ,
59+ SourceFileLoader : 'pure Python' ,
60+ }
61+
62+ expected = loader
63+ assert isinstance (expected , type ), expected
64+ expected = MODULE_KINDS [expected ]
65+
66+ actual = module .__spec__ .loader
67+ if not isinstance (actual , type ):
68+ actual = type (actual )
69+ actual = MODULE_KINDS [actual ]
70+
71+ if actual != expected :
72+ err = f'expected module to be { expected } , got { module .__spec__ } '
73+ if skip :
74+ raise unittest .SkipTest (err )
75+ raise Exception (err )
76+ return module
77+
78+ def require_builtin (module , * , skip = False ):
79+ module = _require_loader (module , BuiltinImporter , skip )
80+ assert module .__spec__ .origin == 'built-in' , module .__spec__
81+
82+ def require_extension (module , * , skip = False ):
83+ _require_loader (module , ExtensionFileLoader , skip )
84+
85+ def require_frozen (module , * , skip = True ):
86+ module = _require_loader (module , FrozenImporter , skip )
87+ assert module .__spec__ .origin == 'frozen' , module .__spec__
88+
89+ def require_pure_python (module , * , skip = False ):
90+ _require_loader (module , SourceFileLoader , skip )
91+
92+
4793def remove_files (name ):
4894 for f in (name + ".py" ,
4995 name + ".pyc" ,
@@ -1437,10 +1483,10 @@ def import_script(self, name, fd, check_override=None):
14371483 os.write({ fd } , text.encode('utf-8'))
14381484 ''' )
14391485
1440- def run_shared (self , name , * ,
1441- check_singlephase_setting = False ,
1442- check_singlephase_override = None ,
1443- ):
1486+ def run_here (self , name , * ,
1487+ check_singlephase_setting = False ,
1488+ check_singlephase_override = None ,
1489+ ):
14441490 """
14451491 Try importing the named module in a subinterpreter.
14461492
@@ -1470,27 +1516,35 @@ def run_shared(self, name, *,
14701516 self .assertEqual (ret , 0 )
14711517 return os .read (r , 100 )
14721518
1473- def check_compatible_shared (self , name , * , strict = False ):
1519+ def check_compatible_here (self , name , * , strict = False ):
14741520 # Verify that the named module may be imported in a subinterpreter.
1475- # (See run_shared() for more info.)
1476- out = self .run_shared (name , check_singlephase_setting = strict )
1521+ # (See run_here() for more info.)
1522+ out = self .run_here (name ,
1523+ check_singlephase_setting = strict ,
1524+ )
14771525 self .assertEqual (out , b'okay' )
14781526
1479- def check_incompatible_shared (self , name ):
1480- # Differences from check_compatible_shared ():
1527+ def check_incompatible_here (self , name ):
1528+ # Differences from check_compatible_here ():
14811529 # * verify that import fails
14821530 # * "strict" is always True
1483- out = self .run_shared (name , check_singlephase_setting = True )
1531+ out = self .run_here (name ,
1532+ check_singlephase_setting = True ,
1533+ )
14841534 self .assertEqual (
14851535 out .decode ('utf-8' ),
14861536 f'ImportError: module { name } does not support loading in subinterpreters' ,
14871537 )
14881538
1489- def check_compatible_isolated (self , name , * , strict = False ):
1490- # Differences from check_compatible_shared ():
1539+ def check_compatible_fresh (self , name , * , strict = False ):
1540+ # Differences from check_compatible_here ():
14911541 # * subinterpreter in a new process
14921542 # * module has never been imported before in that process
14931543 # * this tests importing the module for the first time
1544+ kwargs = dict (
1545+ ** self .RUN_KWARGS ,
1546+ check_multi_interp_extensions = strict ,
1547+ )
14941548 _ , out , err = script_helper .assert_python_ok ('-c' , textwrap .dedent (f'''
14951549 import _testcapi, sys
14961550 assert (
@@ -1499,25 +1553,27 @@ def check_compatible_isolated(self, name, *, strict=False):
14991553 ), repr({ name !r} )
15001554 ret = _testcapi.run_in_subinterp_with_config(
15011555 { self .import_script (name , "sys.stdout.fileno()" )!r} ,
1502- **{ self .RUN_KWARGS } ,
1503- check_multi_interp_extensions={ strict } ,
1556+ **{ kwargs } ,
15041557 )
15051558 assert ret == 0, ret
15061559 ''' ))
15071560 self .assertEqual (err , b'' )
15081561 self .assertEqual (out , b'okay' )
15091562
1510- def check_incompatible_isolated (self , name ):
1511- # Differences from check_compatible_isolated ():
1563+ def check_incompatible_fresh (self , name ):
1564+ # Differences from check_compatible_fresh ():
15121565 # * verify that import fails
15131566 # * "strict" is always True
1567+ kwargs = dict (
1568+ ** self .RUN_KWARGS ,
1569+ check_multi_interp_extensions = True ,
1570+ )
15141571 _ , out , err = script_helper .assert_python_ok ('-c' , textwrap .dedent (f'''
15151572 import _testcapi, sys
15161573 assert { name !r} not in sys.modules, { name !r}
15171574 ret = _testcapi.run_in_subinterp_with_config(
15181575 { self .import_script (name , "sys.stdout.fileno()" )!r} ,
1519- **{ self .RUN_KWARGS } ,
1520- check_multi_interp_extensions=True,
1576+ **{ kwargs } ,
15211577 )
15221578 assert ret == 0, ret
15231579 ''' ))
@@ -1528,67 +1584,73 @@ def check_incompatible_isolated(self, name):
15281584 )
15291585
15301586 def test_builtin_compat (self ):
1531- module = 'sys'
1587+ # For now we avoid using sys or builtins
1588+ # since they still don't implement multi-phase init.
1589+ module = '_imp'
1590+ require_builtin (module )
15321591 with self .subTest (f'{ module } : not strict' ):
1533- self .check_compatible_shared (module , strict = False )
1534- with self .subTest (f'{ module } : strict, shared ' ):
1535- self .check_compatible_shared (module , strict = True )
1592+ self .check_compatible_here (module , strict = False )
1593+ with self .subTest (f'{ module } : strict, not fresh ' ):
1594+ self .check_compatible_here (module , strict = True )
15361595
15371596 @cpython_only
15381597 def test_frozen_compat (self ):
15391598 module = '_frozen_importlib'
1599+ require_frozen (module , skip = True )
15401600 if __import__ (module ).__spec__ .origin != 'frozen' :
15411601 raise unittest .SkipTest (f'{ module } is unexpectedly not frozen' )
15421602 with self .subTest (f'{ module } : not strict' ):
1543- self .check_compatible_shared (module , strict = False )
1544- with self .subTest (f'{ module } : strict, shared ' ):
1545- self .check_compatible_shared (module , strict = True )
1603+ self .check_compatible_here (module , strict = False )
1604+ with self .subTest (f'{ module } : strict, not fresh ' ):
1605+ self .check_compatible_here (module , strict = True )
15461606
15471607 @unittest .skipIf (_testsinglephase is None , "test requires _testsinglephase module" )
15481608 def test_single_init_extension_compat (self ):
15491609 module = '_testsinglephase'
1610+ require_extension (module )
15501611 with self .subTest (f'{ module } : not strict' ):
1551- self .check_compatible_shared (module , strict = False )
1552- with self .subTest (f'{ module } : strict, shared ' ):
1553- self .check_incompatible_shared (module )
1554- with self .subTest (f'{ module } : strict, isolated ' ):
1555- self .check_incompatible_isolated (module )
1612+ self .check_compatible_here (module , strict = False )
1613+ with self .subTest (f'{ module } : strict, not fresh ' ):
1614+ self .check_incompatible_here (module )
1615+ with self .subTest (f'{ module } : strict, fresh ' ):
1616+ self .check_incompatible_fresh (module )
15561617
15571618 @unittest .skipIf (_testmultiphase is None , "test requires _testmultiphase module" )
15581619 def test_multi_init_extension_compat (self ):
15591620 module = '_testmultiphase'
1621+ require_extension (module )
15601622 with self .subTest (f'{ module } : not strict' ):
1561- self .check_compatible_shared (module , strict = False )
1562- with self .subTest (f'{ module } : strict, shared ' ):
1563- self .check_compatible_shared (module , strict = True )
1564- with self .subTest (f'{ module } : strict, isolated ' ):
1565- self .check_compatible_isolated (module , strict = True )
1623+ self .check_compatible_here (module , strict = False )
1624+ with self .subTest (f'{ module } : strict, not fresh ' ):
1625+ self .check_compatible_here (module , strict = True )
1626+ with self .subTest (f'{ module } : strict, fresh ' ):
1627+ self .check_compatible_fresh (module , strict = True )
15661628
15671629 def test_python_compat (self ):
15681630 module = 'threading'
1569- if __import__ (module ).__spec__ .origin == 'frozen' :
1570- raise unittest .SkipTest (f'{ module } is unexpectedly frozen' )
1631+ require_pure_python (module )
15711632 with self .subTest (f'{ module } : not strict' ):
1572- self .check_compatible_shared (module , strict = False )
1573- with self .subTest (f'{ module } : strict, shared ' ):
1574- self .check_compatible_shared (module , strict = True )
1575- with self .subTest (f'{ module } : strict, isolated ' ):
1576- self .check_compatible_isolated (module , strict = True )
1633+ self .check_compatible_here (module , strict = False )
1634+ with self .subTest (f'{ module } : strict, not fresh ' ):
1635+ self .check_compatible_here (module , strict = True )
1636+ with self .subTest (f'{ module } : strict, fresh ' ):
1637+ self .check_compatible_fresh (module , strict = True )
15771638
15781639 @unittest .skipIf (_testsinglephase is None , "test requires _testsinglephase module" )
15791640 def test_singlephase_check_with_setting_and_override (self ):
15801641 module = '_testsinglephase'
1642+ require_extension (module )
15811643
15821644 def check_compatible (setting , override ):
1583- out = self .run_shared (
1645+ out = self .run_here (
15841646 module ,
15851647 check_singlephase_setting = setting ,
15861648 check_singlephase_override = override ,
15871649 )
15881650 self .assertEqual (out , b'okay' )
15891651
15901652 def check_incompatible (setting , override ):
1591- out = self .run_shared (
1653+ out = self .run_here (
15921654 module ,
15931655 check_singlephase_setting = setting ,
15941656 check_singlephase_override = override ,
0 commit comments