1313from test .support .script_helper import assert_python_failure
1414
1515
16- class LoaderTests ( abc . LoaderTests ) :
16+ class LoaderTests :
1717
18- """Test load_module() for extension modules ."""
18+ """Test ExtensionFileLoader ."""
1919
2020 def setUp (self ):
2121 if not self .machinery .EXTENSION_SUFFIXES :
@@ -32,15 +32,6 @@ def load_module(self, fullname):
3232 warnings .simplefilter ("ignore" , DeprecationWarning )
3333 return self .loader .load_module (fullname )
3434
35- def test_load_module_API (self ):
36- # Test the default argument for load_module().
37- with warnings .catch_warnings ():
38- warnings .simplefilter ("ignore" , DeprecationWarning )
39- self .loader .load_module ()
40- self .loader .load_module (None )
41- with self .assertRaises (ImportError ):
42- self .load_module ('XXX' )
43-
4435 def test_equality (self ):
4536 other = self .machinery .ExtensionFileLoader (util .EXTENSIONS .name ,
4637 util .EXTENSIONS .file_path )
@@ -51,6 +42,15 @@ def test_inequality(self):
5142 util .EXTENSIONS .file_path )
5243 self .assertNotEqual (self .loader , other )
5344
45+ def test_load_module_API (self ):
46+ # Test the default argument for load_module().
47+ with warnings .catch_warnings ():
48+ warnings .simplefilter ("ignore" , DeprecationWarning )
49+ self .loader .load_module ()
50+ self .loader .load_module (None )
51+ with self .assertRaises (ImportError ):
52+ self .load_module ('XXX' )
53+
5454 def test_module (self ):
5555 with util .uncache (util .EXTENSIONS .name ):
5656 module = self .load_module (util .EXTENSIONS .name )
@@ -68,12 +68,6 @@ def test_module(self):
6868 # No extension module in a package available for testing.
6969 test_lacking_parent = None
7070
71- def test_module_reuse (self ):
72- with util .uncache (util .EXTENSIONS .name ):
73- module1 = self .load_module (util .EXTENSIONS .name )
74- module2 = self .load_module (util .EXTENSIONS .name )
75- self .assertIs (module1 , module2 )
76-
7771 # No easy way to trigger a failure after a successful import.
7872 test_state_after_failure = None
7973
@@ -83,17 +77,106 @@ def test_unloadable(self):
8377 self .load_module (name )
8478 self .assertEqual (cm .exception .name , name )
8579
80+ def test_module_reuse (self ):
81+ with util .uncache (util .EXTENSIONS .name ):
82+ module1 = self .load_module (util .EXTENSIONS .name )
83+ module2 = self .load_module (util .EXTENSIONS .name )
84+ self .assertIs (module1 , module2 )
85+
8686 def test_is_package (self ):
8787 self .assertFalse (self .loader .is_package (util .EXTENSIONS .name ))
8888 for suffix in self .machinery .EXTENSION_SUFFIXES :
8989 path = os .path .join ('some' , 'path' , 'pkg' , '__init__' + suffix )
9090 loader = self .machinery .ExtensionFileLoader ('pkg' , path )
9191 self .assertTrue (loader .is_package ('pkg' ))
9292
93+
9394(Frozen_LoaderTests ,
9495 Source_LoaderTests
9596 ) = util .test_both (LoaderTests , machinery = machinery )
9697
98+
99+ class SinglePhaseExtensionModuleTests (abc .LoaderTests ):
100+ # Test loading extension modules without multi-phase initialization.
101+
102+ def setUp (self ):
103+ if not self .machinery .EXTENSION_SUFFIXES :
104+ raise unittest .SkipTest ("Requires dynamic loading support." )
105+ self .name = '_testsinglephase'
106+ if self .name in sys .builtin_module_names :
107+ raise unittest .SkipTest (
108+ f"{ self .name } is a builtin module"
109+ )
110+ finder = self .machinery .FileFinder (None )
111+ self .spec = importlib .util .find_spec (self .name )
112+ assert self .spec
113+ self .loader = self .machinery .ExtensionFileLoader (
114+ self .name , self .spec .origin )
115+
116+ def load_module (self ):
117+ with warnings .catch_warnings ():
118+ warnings .simplefilter ("ignore" , DeprecationWarning )
119+ return self .loader .load_module (self .name )
120+
121+ def load_module_by_name (self , fullname ):
122+ # Load a module from the test extension by name.
123+ origin = self .spec .origin
124+ loader = self .machinery .ExtensionFileLoader (fullname , origin )
125+ spec = importlib .util .spec_from_loader (fullname , loader )
126+ module = importlib .util .module_from_spec (spec )
127+ loader .exec_module (module )
128+ return module
129+
130+ def test_module (self ):
131+ # Test loading an extension module.
132+ with util .uncache (self .name ):
133+ module = self .load_module ()
134+ for attr , value in [('__name__' , self .name ),
135+ ('__file__' , self .spec .origin ),
136+ ('__package__' , '' )]:
137+ self .assertEqual (getattr (module , attr ), value )
138+ with self .assertRaises (AttributeError ):
139+ module .__path__
140+ self .assertIs (module , sys .modules [self .name ])
141+ self .assertIsInstance (module .__loader__ ,
142+ self .machinery .ExtensionFileLoader )
143+
144+ # No extension module as __init__ available for testing.
145+ test_package = None
146+
147+ # No extension module in a package available for testing.
148+ test_lacking_parent = None
149+
150+ # No easy way to trigger a failure after a successful import.
151+ test_state_after_failure = None
152+
153+ def test_unloadable (self ):
154+ name = 'asdfjkl;'
155+ with self .assertRaises (ImportError ) as cm :
156+ self .load_module_by_name (name )
157+ self .assertEqual (cm .exception .name , name )
158+
159+ def test_unloadable_nonascii (self ):
160+ # Test behavior with nonexistent module with non-ASCII name.
161+ name = 'fo\xf3 '
162+ with self .assertRaises (ImportError ) as cm :
163+ self .load_module_by_name (name )
164+ self .assertEqual (cm .exception .name , name )
165+
166+ # It may make sense to add the equivalent to
167+ # the following MultiPhaseExtensionModuleTests tests:
168+ #
169+ # * test_nonmodule
170+ # * test_nonmodule_with_methods
171+ # * test_bad_modules
172+ # * test_nonascii
173+
174+
175+ (Frozen_SinglePhaseExtensionModuleTests ,
176+ Source_SinglePhaseExtensionModuleTests
177+ ) = util .test_both (SinglePhaseExtensionModuleTests , machinery = machinery )
178+
179+
97180class MultiPhaseExtensionModuleTests (abc .LoaderTests ):
98181 # Test loading extension modules with multi-phase initialization (PEP 489).
99182
0 commit comments