Created
April 17, 2018 21:19
-
-
Save Jinmo/5bba8f5497c5f31734a3e3ded8c74412 to your computer and use it in GitHub Desktop.
Revisions
-
Jinmo created this gist
Apr 17, 2018 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,57 @@ from ast import parse, iter_fields, AST class NotAllowedException(Exception): def __init__(self, cls): self.cls = cls pass def __str__(self): return '%r is not allowed for execution' % self.cls class Executor(object): def __init__(self, whitelist=None): self.allowed_types = set() if whitelist is not None: for c in whitelist: self.allow(c) def allow(self, source): node = parse(source) self._allow_node(node) def _allow_node(self, node): if isinstance(node, list): for x in node: self._allow_node(x) elif isinstance(node, AST): self.allowed_types.add(node.__class__) for name, field in iter_fields(node): self._allow_node(field) def check_allowed(self, node): if isinstance(node, list): for x in node: self.check_allowed(x) elif isinstance(node, AST): if node.__class__ not in self.allowed_types: raise NotAllowedException(node.__class__) for name, field in iter_fields(node): self.check_allowed(field) def __call__(self, source): # execute node = parse(source) try: self.check_allowed(node) except NotAllowedException: raise return eval(source) if __name__ == '__main__': ex = Executor(( '1 - 1', '1 + 1' )) print ex('100 + 100') print ex('1 * 1')