4
4
import glob
5
5
import importlib .util
6
6
from importlib ._bootstrap_external import _get_sourcefile
7
+ from importlib .machinery import (
8
+ BuiltinImporter , ExtensionFileLoader , FrozenImporter , SourceFileLoader ,
9
+ )
7
10
import marshal
8
11
import os
9
12
import py_compile
44
47
sys .dont_write_bytecode ,
45
48
"test meaningful only when writing bytecode" )
46
49
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
+
47
93
def remove_files (name ):
48
94
for f in (name + ".py" ,
49
95
name + ".pyc" ,
@@ -1437,10 +1483,10 @@ def import_script(self, name, fd, check_override=None):
1437
1483
os.write({ fd } , text.encode('utf-8'))
1438
1484
''' )
1439
1485
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
+ ):
1444
1490
"""
1445
1491
Try importing the named module in a subinterpreter.
1446
1492
@@ -1470,27 +1516,35 @@ def run_shared(self, name, *,
1470
1516
self .assertEqual (ret , 0 )
1471
1517
return os .read (r , 100 )
1472
1518
1473
- def check_compatible_shared (self , name , * , strict = False ):
1519
+ def check_compatible_here (self , name , * , strict = False ):
1474
1520
# 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
+ )
1477
1525
self .assertEqual (out , b'okay' )
1478
1526
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 ():
1481
1529
# * verify that import fails
1482
1530
# * "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
+ )
1484
1534
self .assertEqual (
1485
1535
out .decode ('utf-8' ),
1486
1536
f'ImportError: module { name } does not support loading in subinterpreters' ,
1487
1537
)
1488
1538
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 ():
1491
1541
# * subinterpreter in a new process
1492
1542
# * module has never been imported before in that process
1493
1543
# * this tests importing the module for the first time
1544
+ kwargs = dict (
1545
+ ** self .RUN_KWARGS ,
1546
+ check_multi_interp_extensions = strict ,
1547
+ )
1494
1548
_ , out , err = script_helper .assert_python_ok ('-c' , textwrap .dedent (f'''
1495
1549
import _testcapi, sys
1496
1550
assert (
@@ -1499,25 +1553,27 @@ def check_compatible_isolated(self, name, *, strict=False):
1499
1553
), repr({ name !r} )
1500
1554
ret = _testcapi.run_in_subinterp_with_config(
1501
1555
{ self .import_script (name , "sys.stdout.fileno()" )!r} ,
1502
- **{ self .RUN_KWARGS } ,
1503
- check_multi_interp_extensions={ strict } ,
1556
+ **{ kwargs } ,
1504
1557
)
1505
1558
assert ret == 0, ret
1506
1559
''' ))
1507
1560
self .assertEqual (err , b'' )
1508
1561
self .assertEqual (out , b'okay' )
1509
1562
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 ():
1512
1565
# * verify that import fails
1513
1566
# * "strict" is always True
1567
+ kwargs = dict (
1568
+ ** self .RUN_KWARGS ,
1569
+ check_multi_interp_extensions = True ,
1570
+ )
1514
1571
_ , out , err = script_helper .assert_python_ok ('-c' , textwrap .dedent (f'''
1515
1572
import _testcapi, sys
1516
1573
assert { name !r} not in sys.modules, { name !r}
1517
1574
ret = _testcapi.run_in_subinterp_with_config(
1518
1575
{ self .import_script (name , "sys.stdout.fileno()" )!r} ,
1519
- **{ self .RUN_KWARGS } ,
1520
- check_multi_interp_extensions=True,
1576
+ **{ kwargs } ,
1521
1577
)
1522
1578
assert ret == 0, ret
1523
1579
''' ))
@@ -1528,67 +1584,73 @@ def check_incompatible_isolated(self, name):
1528
1584
)
1529
1585
1530
1586
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 )
1532
1591
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 )
1536
1595
1537
1596
@cpython_only
1538
1597
def test_frozen_compat (self ):
1539
1598
module = '_frozen_importlib'
1599
+ require_frozen (module , skip = True )
1540
1600
if __import__ (module ).__spec__ .origin != 'frozen' :
1541
1601
raise unittest .SkipTest (f'{ module } is unexpectedly not frozen' )
1542
1602
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 )
1546
1606
1547
1607
@unittest .skipIf (_testsinglephase is None , "test requires _testsinglephase module" )
1548
1608
def test_single_init_extension_compat (self ):
1549
1609
module = '_testsinglephase'
1610
+ require_extension (module )
1550
1611
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 )
1556
1617
1557
1618
@unittest .skipIf (_testmultiphase is None , "test requires _testmultiphase module" )
1558
1619
def test_multi_init_extension_compat (self ):
1559
1620
module = '_testmultiphase'
1621
+ require_extension (module )
1560
1622
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 )
1566
1628
1567
1629
def test_python_compat (self ):
1568
1630
module = 'threading'
1569
- if __import__ (module ).__spec__ .origin == 'frozen' :
1570
- raise unittest .SkipTest (f'{ module } is unexpectedly frozen' )
1631
+ require_pure_python (module )
1571
1632
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 )
1577
1638
1578
1639
@unittest .skipIf (_testsinglephase is None , "test requires _testsinglephase module" )
1579
1640
def test_singlephase_check_with_setting_and_override (self ):
1580
1641
module = '_testsinglephase'
1642
+ require_extension (module )
1581
1643
1582
1644
def check_compatible (setting , override ):
1583
- out = self .run_shared (
1645
+ out = self .run_here (
1584
1646
module ,
1585
1647
check_singlephase_setting = setting ,
1586
1648
check_singlephase_override = override ,
1587
1649
)
1588
1650
self .assertEqual (out , b'okay' )
1589
1651
1590
1652
def check_incompatible (setting , override ):
1591
- out = self .run_shared (
1653
+ out = self .run_here (
1592
1654
module ,
1593
1655
check_singlephase_setting = setting ,
1594
1656
check_singlephase_override = override ,
0 commit comments