Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

module_loading.py 1.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. """
  2. Module loading utilities similar to Django's module_loading.
  3. Reference implementation from Django:
  4. https://github.com/django/django/blob/main/django/utils/module_loading.py
  5. """
  6. import sys
  7. from importlib import import_module
  8. def cached_import(module_path: str, class_name: str):
  9. """
  10. Import a module and return the named attribute/class from it, with caching.
  11. Args:
  12. module_path: The module path to import from
  13. class_name: The attribute/class name to retrieve
  14. Returns:
  15. The imported attribute/class
  16. """
  17. if not (
  18. (module := sys.modules.get(module_path))
  19. and (spec := getattr(module, "__spec__", None))
  20. and getattr(spec, "_initializing", False) is False
  21. ):
  22. module = import_module(module_path)
  23. return getattr(module, class_name)
  24. def import_string(dotted_path: str):
  25. """
  26. Import a dotted module path and return the attribute/class designated by
  27. the last name in the path. Raise ImportError if the import failed.
  28. Args:
  29. dotted_path: Full module path to the class (e.g., 'module.submodule.ClassName')
  30. Returns:
  31. The imported class or attribute
  32. Raises:
  33. ImportError: If the module or attribute cannot be imported
  34. """
  35. try:
  36. module_path, class_name = dotted_path.rsplit(".", 1)
  37. except ValueError as err:
  38. raise ImportError(f"{dotted_path} doesn't look like a module path") from err
  39. try:
  40. return cached_import(module_path, class_name)
  41. except AttributeError as err:
  42. raise ImportError(f'Module "{module_path}" does not define a "{class_name}" attribute/class') from err