Coverage for aipyapp/exec/python/mod_obj.py: 31%
55 statements
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-11 12:02 +0200
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-11 12:02 +0200
1import sys
2import types
3import importlib.abc
4import importlib.util
6from loguru import logger
8class ObjectModuleLoader(importlib.abc.Loader):
9 def __init__(self, fullname, obj):
10 self.fullname = fullname
11 self.obj = obj
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
21 def exec_module(self, module):
22 pass
24class 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')
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
37 if not fullname.startswith(self.package + "."):
38 return None
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
46class ObjectImporter:
47 def __init__(self, object_map, package='aipyapp'):
48 self.package = package
49 self.finder = ObjectModuleFinder(package, object_map)
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
57 def __exit__(self, exc_type, exc_val, exc_tb):
58 sys.meta_path = self._old_meta_path
60if __name__ == "__main__":
61 class Runtime:
62 def do(self):
63 print("runtime doing something")
65 runtime = Runtime()
67 obj_importer = ObjectImporter({"runtime": runtime})
69 code = '''
70from aipyapp import runtime
71runtime.do()
72'''
74 with obj_importer:
75 exec(code)