@@ -92,7 +92,7 @@ def find_module(
92
92
modname : str ,
93
93
module_parts : tuple [str , ...],
94
94
processed : tuple [str , ...],
95
- submodule_path : Sequence [str ] | None ,
95
+ submodule_path : tuple [str , ... ] | None ,
96
96
) -> ModuleSpec | None :
97
97
"""Find the given module.
98
98
@@ -105,7 +105,7 @@ def find_module(
105
105
namespace.
106
106
:param processed: What parts from the module parts were processed
107
107
so far.
108
- :param submodule_path: A list of paths where the module
108
+ :param submodule_path: A tuple of paths where the module
109
109
can be looked into.
110
110
:returns: A ModuleSpec, describing how and where the module was found,
111
111
None, otherwise.
@@ -127,11 +127,12 @@ class ImportlibFinder(Finder):
127
127
)
128
128
129
129
@staticmethod
130
+ @lru_cache (maxsize = 1024 )
130
131
def find_module (
131
132
modname : str ,
132
133
module_parts : tuple [str , ...],
133
134
processed : tuple [str , ...],
134
- submodule_path : Sequence [str ] | None ,
135
+ submodule_path : tuple [str , ... ] | None ,
135
136
) -> ModuleSpec | None :
136
137
if submodule_path is not None :
137
138
search_paths = list (submodule_path )
@@ -222,11 +223,12 @@ class ExplicitNamespacePackageFinder(ImportlibFinder):
222
223
"""A finder for the explicit namespace packages."""
223
224
224
225
@staticmethod
226
+ @lru_cache (maxsize = 1024 )
225
227
def find_module (
226
228
modname : str ,
227
229
module_parts : tuple [str , ...],
228
230
processed : tuple [str , ...],
229
- submodule_path : Sequence [str ] | None ,
231
+ submodule_path : tuple [str , ... ] | None ,
230
232
) -> ModuleSpec | None :
231
233
if processed :
232
234
modname = "." .join ([* processed , modname ])
@@ -261,11 +263,12 @@ def __init__(self, path: Sequence[str]) -> None:
261
263
continue
262
264
263
265
@staticmethod
266
+ @lru_cache (maxsize = 1024 )
264
267
def find_module (
265
268
modname : str ,
266
269
module_parts : tuple [str , ...],
267
270
processed : tuple [str , ...],
268
- submodule_path : Sequence [str ] | None ,
271
+ submodule_path : tuple [str , ... ] | None ,
269
272
) -> ModuleSpec | None :
270
273
try :
271
274
file_type , filename , path = _search_zip (module_parts )
@@ -285,11 +288,12 @@ class PathSpecFinder(Finder):
285
288
"""Finder based on importlib.machinery.PathFinder."""
286
289
287
290
@staticmethod
291
+ @lru_cache (maxsize = 1024 )
288
292
def find_module (
289
293
modname : str ,
290
294
module_parts : tuple [str , ...],
291
295
processed : tuple [str , ...],
292
- submodule_path : Sequence [str ] | None ,
296
+ submodule_path : tuple [str , ... ] | None ,
293
297
) -> ModuleSpec | None :
294
298
spec = importlib .machinery .PathFinder .find_spec (modname , path = submodule_path )
295
299
if spec is not None :
@@ -373,7 +377,7 @@ def _find_spec_with_path(
373
377
modname : str ,
374
378
module_parts : tuple [str , ...],
375
379
processed : tuple [str , ...],
376
- submodule_path : Sequence [str ] | None ,
380
+ submodule_path : tuple [str , ... ] | None ,
377
381
) -> tuple [Finder | _MetaPathFinder , ModuleSpec ]:
378
382
for finder in _SPEC_FINDERS :
379
383
finder_instance = finder (search_path )
@@ -451,25 +455,30 @@ def _find_spec(
451
455
# Need a copy for not mutating the argument.
452
456
modpath = list (module_path )
453
457
454
- submodule_path = None
458
+ search_paths = None
455
459
processed : list [str ] = []
456
460
457
461
while modpath :
458
462
modname = modpath .pop (0 )
463
+
464
+ submodule_path = search_paths or path
465
+ if submodule_path is not None :
466
+ submodule_path = tuple (submodule_path )
467
+
459
468
finder , spec = _find_spec_with_path (
460
- _path , modname , module_path , tuple (processed ), submodule_path or path
469
+ _path , modname , module_path , tuple (processed ), submodule_path
461
470
)
462
471
processed .append (modname )
463
472
if modpath :
464
473
if isinstance (finder , Finder ):
465
- submodule_path = finder .contribute_to_path (spec , processed )
466
- # If modname is a package from an editable install, update submodule_path
474
+ search_paths = finder .contribute_to_path (spec , processed )
475
+ # If modname is a package from an editable install, update search_paths
467
476
# so that the next module in the path will be found inside of it using importlib.
468
477
# Existence of __name__ is guaranteed by _find_spec_with_path.
469
478
elif finder .__name__ in _EditableFinderClasses : # type: ignore[attr-defined]
470
- submodule_path = spec .submodule_search_locations
479
+ search_paths = spec .submodule_search_locations
471
480
472
481
if spec .type == ModuleType .PKG_DIRECTORY :
473
- spec = spec ._replace (submodule_search_locations = submodule_path )
482
+ spec = spec ._replace (submodule_search_locations = search_paths )
474
483
475
484
return spec
0 commit comments