module_paths.py 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. """Utility functions for finding modules
  2. Utility functions for finding modules on sys.path.
  3. """
  4. from __future__ import annotations
  5. #-----------------------------------------------------------------------------
  6. # Copyright (c) 2011, the IPython Development Team.
  7. #
  8. # Distributed under the terms of the Modified BSD License.
  9. #
  10. # The full license is in the file COPYING.txt, distributed with this software.
  11. #-----------------------------------------------------------------------------
  12. #-----------------------------------------------------------------------------
  13. # Imports
  14. #-----------------------------------------------------------------------------
  15. # Stdlib imports
  16. import importlib
  17. import importlib.abc
  18. import importlib.util
  19. import sys
  20. # Third-party imports
  21. # Our own imports
  22. #-----------------------------------------------------------------------------
  23. # Globals and constants
  24. #-----------------------------------------------------------------------------
  25. #-----------------------------------------------------------------------------
  26. # Local utilities
  27. #-----------------------------------------------------------------------------
  28. #-----------------------------------------------------------------------------
  29. # Classes and functions
  30. #-----------------------------------------------------------------------------
  31. def find_mod(module_name: str) -> str | None | importlib.abc.Loader:
  32. """
  33. Find module `module_name` on sys.path, and return the path to module `module_name`.
  34. * If `module_name` refers to a module directory, then return path to `__init__` file.
  35. * If `module_name` is a directory without an __init__file, return None.
  36. * If module is missing or does not have a `.py` or `.pyw` extension, return None.
  37. * Note that we are not interested in running bytecode.
  38. * Otherwise, return the fill path of the module.
  39. Parameters
  40. ----------
  41. module_name : str
  42. Returns
  43. -------
  44. module_path : str
  45. Path to module `module_name`, its __init__.py, or None,
  46. depending on above conditions.
  47. """
  48. spec = importlib.util.find_spec(module_name)
  49. if spec is None:
  50. return None
  51. module_path = spec.origin
  52. if module_path is None:
  53. if spec.loader is not None and spec.loader in sys.meta_path:
  54. return spec.loader
  55. return None
  56. else:
  57. split_path = module_path.split(".")
  58. if split_path[-1] in ["py", "pyw"]:
  59. return module_path
  60. else:
  61. return None