MCPcopy Index your code
hub / github.com/cloudpipe/cloudpickle / _find_imported_submodules

Function _find_imported_submodules

cloudpickle/cloudpickle.py:338–384  ·  view source on GitHub ↗

Find currently imported submodules used by a function. Submodules used by a function need to be detected and referenced for the function to work correctly at depickling time. Because submodules can be referenced as attribute of their parent package (``package.submodule``), we need a

(code, top_level_dependencies)

Source from the content-addressed store, hash-verified

336
337
338def _find_imported_submodules(code, top_level_dependencies):
339 """Find currently imported submodules used by a function.
340
341 Submodules used by a function need to be detected and referenced for the
342 function to work correctly at depickling time. Because submodules can be
343 referenced as attribute of their parent package (``package.submodule``), we
344 need a special introspection technique that does not rely on GLOBAL-related
345 opcodes to find references of them in a code object.
346
347 Example:
348 ```
349 import concurrent.futures
350 import cloudpickle
351 def func():
352 x = concurrent.futures.ThreadPoolExecutor
353 if __name__ == '__main__':
354 cloudpickle.dumps(func)
355 ```
356 The globals extracted by cloudpickle in the function's state include the
357 concurrent package, but not its submodule (here, concurrent.futures), which
358 is the module used by func. Find_imported_submodules will detect the usage
359 of concurrent.futures. Saving this module alongside with func will ensure
360 that calling func once depickled does not fail due to concurrent.futures
361 not being imported
362 """
363
364 subimports = []
365 # check if any known dependency is an imported package
366 for x in top_level_dependencies:
367 if (
368 isinstance(x, types.ModuleType)
369 and hasattr(x, "__package__")
370 and x.__package__
371 ):
372 # check if the package has any currently loaded sub-imports
373 prefix = x.__name__ + "."
374 # A concurrent thread could mutate sys.modules,
375 # make sure we iterate over a copy to avoid exceptions
376 for name in list(sys.modules):
377 # Older versions of pytest will add a "None" module to
378 # sys.modules.
379 if name is not None and name.startswith(prefix):
380 # check whether the function can address the sub-module
381 tokens = set(name[len(prefix) :].split("."))
382 if not tokens - set(code.co_names):
383 subimports.append(sys.modules[name])
384 return subimports
385
386
387# relevant opcodes

Callers 1

_function_getstateFunction · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…