@@ -162,17 +162,32 @@ def load_module(self, fullname):
162162 module = self .loader .load_module (fullname )
163163
164164 # Call the import hooks on the module being handled.
165-
166165 _notify_import_hooks (fullname , module )
167166
168167 return module
169168
169+ def create_module (self , spec ):
170+ return self .loader .create_module (spec )
171+
172+ def exec_module (self , module ):
173+ self .loader .exec_module (module )
174+
175+ # Call the import hooks on the module being handled.
176+ _notify_import_hooks (module .__name__ , module )
177+
170178
171179class ImportHookFinder :
172180 def __init__ (self ):
173181 self ._skip = {}
174182
175183 def find_module (self , fullname , path = None ):
184+ """
185+ Find spec and patch import hooks into loader before returning.
186+
187+ Required for Python 2.
188+
189+ https://docs.python.org/3/library/importlib.html#importlib.abc.MetaPathFinder.find_module
190+ """
176191
177192 # If not something we are interested in we can return.
178193
@@ -200,7 +215,7 @@ def find_module(self, fullname, path=None):
200215 spec = find_spec (fullname )
201216 loader = getattr (spec , "loader" , None )
202217
203- if loader :
218+ if loader and not isinstance ( loader , ( _ImportHookChainedLoader , _ImportHookLoader )) :
204219 return _ImportHookChainedLoader (loader )
205220
206221 else :
@@ -216,6 +231,54 @@ def find_module(self, fullname, path=None):
216231 finally :
217232 del self ._skip [fullname ]
218233
234+ def find_spec (self , fullname , path = None , target = None ):
235+ """
236+ Find spec and patch import hooks into loader before returning.
237+
238+ Required for Python 3.10+ to avoid warnings.
239+
240+ https://docs.python.org/3/library/importlib.html#importlib.abc.MetaPathFinder.find_spec
241+ """
242+ # raise ValueError((name, path, target))
243+
244+ # If not something we are interested in we can return.
245+
246+ if fullname not in _import_hooks :
247+ return None
248+
249+ # Check whether this is being called on the second time
250+ # through and return.
251+
252+ if fullname in self ._skip :
253+ return None
254+
255+ # We are now going to call back into import. We set a
256+ # flag to see we are handling the module so that check
257+ # above drops out on subsequent pass and we don't go
258+ # into an infinite loop.
259+
260+ self ._skip [fullname ] = True
261+
262+ try :
263+ # For Python 3 we need to use find_spec() from the importlib
264+ # module.
265+
266+ if find_spec :
267+ spec = find_spec (fullname )
268+ loader = getattr (spec , "loader" , None )
269+
270+ if loader and not isinstance (loader , (_ImportHookChainedLoader , _ImportHookLoader )):
271+ spec .loader = _ImportHookChainedLoader (loader )
272+
273+ return spec
274+
275+ else :
276+ # Not possible, Python 3 defines find_spec and Python 2 does not have find_spec on Finders
277+ return None
278+
279+ finally :
280+ del self ._skip [fullname ]
281+
219282
220283def import_hook (name ):
221284 def decorator (wrapped ):
0 commit comments