用python做配置文件

受zig语言启发,图灵完备的配置文件可能是个不错的选择,只要严格限制权限就行。
用importlib
目标:

  • 禁止二次导入,去除import语句
  • 提供模块白名单、黑名单
import ast
from sys import meta_path
from importlib.abc import Loader, MetaPathFinder
from importlib.util import spec_from_loader, find_spec
from mocap_wrapper.logger import Log


class CustomLoader(Loader):
    def __init__(self, original_spec):
        self.original_spec = original_spec

    def create_module(self, spec):
        # 使用默认模块创建逻辑
        return None

    def exec_module(self, module):
        # 获取原始源代码
        source = self.original_spec.loader.get_source(module.__name__)
        if source is None:
            raise ImportError(f"Can't get module {module.__name__} source code.")

        # 解析为AST并删除所有import节点
        tree = ast.parse(source)
        transformer = ImportRemover()
        modified_tree = transformer.visit(tree)
        ast.fix_missing_locations(modified_tree)  # 修复AST节点位置

        # 编译修改后的AST
        code = compile(modified_tree, module.__spec__.origin, 'exec')

        # 注入system函数到模块的全局命名空间
        # module.system = os.system

        # 执行修改后的代码
        exec(code, module.__dict__)


class ImportRemover(ast.NodeTransformer):
    ...
    # def visit_Import(self, node):
    #     """删除所有Import节点"""
    #     return None

    # def visit_ImportFrom(self, node):
    #     """删除所有ImportFrom节点"""
    #     return None


class CustomFinder(MetaPathFinder):
    def find_spec(self, fullname, path, target=None):
        Log.debug(fullname)

        # 仅处理特定模块
        # if not fullname.startswith('mocap_wrapper.config'):
        #     return None

        # 临时移除 CustomFinder 以避免递归
        meta_path.remove(self)
        try:
            # 查找原始模块的Spec
            original_spec = find_spec(fullname)
        finally:
            # 重新添加 CustomFinder
            meta_path.insert(0, self)

        if not original_spec:
            # 未找到
            return None

        # 使用自定义Loader替换原加载器
        loader = CustomLoader(original_spec)
        return spec_from_loader(
            fullname,
            loader,
            origin=original_spec.origin
        )


class Import:
    singleton = None

    @staticmethod
    def init():
        """注册自定义Finder到meta_path"""
        if not Import.singleton:
            Import.singleton = CustomFinder()
        if Import.singleton not in meta_path:
            meta_path.insert(0, Import.singleton)
        Log.debug(meta_path)

    @staticmethod
    def reset():
        if Import.singleton in meta_path:
            meta_path.remove(Import.singleton)
            Import.singleton = None
        Log.debug(meta_path)


def test():
    Import.init()
    import mocap_wrapper.config.template as c
    Import.reset()
    Log.debug(c.Aria2.port)
    return c


if __name__ == '__main__':
    c = test()

posted @ 2025-02-16 18:57  Nolca  阅读(13)  评论(0)    收藏  举报