Coverage for aipyapp/exec/python/mod_obj.py: 31%

1 import sys

2 import types

3 import importlib.abc

4 import importlib.util

5

6 from loguru import logger

7

8 class ObjectModuleLoader(importlib.abc.Loader):

9 def __init__(self, fullname, obj):

10 self.fullname = fullname

11 self.obj = obj

12

13 def create_module(self, spec):

14 mod = types.ModuleType(self.fullname)

15 # 注入所有非魔法属性，包括方法

16 for attr in dir(self.obj):

17 if not attr.startswith("__"):

18 setattr(mod, attr, getattr(self.obj, attr))

19 return mod

20

21 def exec_module(self, module):

22 pass

23

24 class ObjectModuleFinder(importlib.abc.MetaPathFinder):

25 def __init__(self, package, object_map):

26 self.package = package

27 self.object_map = object_map

28 self.logger = logger.bind(src='ObjectModuleFinder')

29

30 def find_spec(self, fullname, path, target=None):

31 self.logger.info(f"find_spec: {fullname}, {path}, {target}")

32 if fullname == self.package:

33 spec = importlib.util.spec_from_loader(fullname, loader=None)

34 spec.submodule_search_locations = []

35 return spec

36

37 if not fullname.startswith(self.package + "."):

38 return None

39

40 subname = fullname[len(self.package) + 1:]

41 if subname in self.object_map:

42 loader = ObjectModuleLoader(fullname, self.object_map[subname])

43 return importlib.util.spec_from_loader(fullname, loader)

44 return None

45

46 class ObjectImporter:

47 def __init__(self, object_map, package='aipyapp'):

48 self.package = package

49 self.finder = ObjectModuleFinder(package, object_map)

50

51 def __enter__(self):

52 self._old_meta_path = sys.meta_path[:]

53 if self.finder not in sys.meta_path:

54 sys.meta_path.insert(0, self.finder)

55 return self

56

57 def __exit__(self, exc_type, exc_val, exc_tb):

58 sys.meta_path = self._old_meta_path

59

60 if __name__ == "__main__":

61 class Runtime:

62 def do(self):

63 print("runtime doing something")

64

65 runtime = Runtime()

66

67 obj_importer = ObjectImporter({"runtime": runtime})

68

69 code = '''

70 from aipyapp import runtime

71 runtime.do()

72'''

73

74 with obj_importer:

75 exec(code)