_imp_emulation.py 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. try:
  2. # this works on Python < 3.12
  3. from imp import *
  4. except ImportError:
  5. # this is a limited emulation for Python >= 3.12.
  6. # Note that this is used only for tests or for the old ffi.verify().
  7. # This is copied from the source code of Python 3.11.
  8. from _imp import (acquire_lock, release_lock,
  9. is_builtin, is_frozen)
  10. from importlib._bootstrap import _load
  11. from importlib import machinery
  12. import os
  13. import sys
  14. import tokenize
  15. SEARCH_ERROR = 0
  16. PY_SOURCE = 1
  17. PY_COMPILED = 2
  18. C_EXTENSION = 3
  19. PY_RESOURCE = 4
  20. PKG_DIRECTORY = 5
  21. C_BUILTIN = 6
  22. PY_FROZEN = 7
  23. PY_CODERESOURCE = 8
  24. IMP_HOOK = 9
  25. def get_suffixes():
  26. extensions = [(s, 'rb', C_EXTENSION)
  27. for s in machinery.EXTENSION_SUFFIXES]
  28. source = [(s, 'r', PY_SOURCE) for s in machinery.SOURCE_SUFFIXES]
  29. bytecode = [(s, 'rb', PY_COMPILED) for s in machinery.BYTECODE_SUFFIXES]
  30. return extensions + source + bytecode
  31. def find_module(name, path=None):
  32. if not isinstance(name, str):
  33. raise TypeError("'name' must be a str, not {}".format(type(name)))
  34. elif not isinstance(path, (type(None), list)):
  35. # Backwards-compatibility
  36. raise RuntimeError("'path' must be None or a list, "
  37. "not {}".format(type(path)))
  38. if path is None:
  39. if is_builtin(name):
  40. return None, None, ('', '', C_BUILTIN)
  41. elif is_frozen(name):
  42. return None, None, ('', '', PY_FROZEN)
  43. else:
  44. path = sys.path
  45. for entry in path:
  46. package_directory = os.path.join(entry, name)
  47. for suffix in ['.py', machinery.BYTECODE_SUFFIXES[0]]:
  48. package_file_name = '__init__' + suffix
  49. file_path = os.path.join(package_directory, package_file_name)
  50. if os.path.isfile(file_path):
  51. return None, package_directory, ('', '', PKG_DIRECTORY)
  52. for suffix, mode, type_ in get_suffixes():
  53. file_name = name + suffix
  54. file_path = os.path.join(entry, file_name)
  55. if os.path.isfile(file_path):
  56. break
  57. else:
  58. continue
  59. break # Break out of outer loop when breaking out of inner loop.
  60. else:
  61. raise ImportError(name, name=name)
  62. encoding = None
  63. if 'b' not in mode:
  64. with open(file_path, 'rb') as file:
  65. encoding = tokenize.detect_encoding(file.readline)[0]
  66. file = open(file_path, mode, encoding=encoding)
  67. return file, file_path, (suffix, mode, type_)
  68. def load_dynamic(name, path, file=None):
  69. loader = machinery.ExtensionFileLoader(name, path)
  70. spec = machinery.ModuleSpec(name=name, loader=loader, origin=path)
  71. return _load(spec)