class CharacterWrapper(object):
def __init__(self, character):
self._character = character
def make_deferer(method_name):
def deferer(obj, *args, **kwargs):
return getattr(obj, method_name)(obj, *args, **kwargs)
return deferer
for method_name in ['get_hp', 'get_mana', 'do_damage', …]:
setattr(CharacterWrapper, method_name, make_deferer(method_name))
## The following keywords are not permitted within scripts. Expand as needed.
_RESTRICTED = [
'Exception', '__builtin__', '__class__', '__debug__', '__dict__',
'__init__', '__local__', '__subclasses__', 'as', 'assert', 'break',
'class', 'compile', 'continue', 'def', 'del', 'delattr', 'dict',
'dir', 'eval', 'except', 'exec', 'execfile', 'exit', 'file', 'finally',
'for', 'from', 'getattr', 'global', 'import', 'input', 'lambda', 'locals',
'object', 'open', 'property', 'raise', 'raw_input', 'reload', 'return',
'setattr', 'staticmethod', 'try', 'while', 'with', 'yield',
]
Googling on the subject has led me to believe that eval() is potentially unsafe, but that an alternative might be to use ASTs and walking - unfortunately the Python documentation on this is incomplete, so I don't really understand it.
I was considering maybe writing a lexer/parser to convert a custom, Python-esque scripting language into Python. Would that be overkill? More importantly, would it be safe? Am I right in thinking that that would give me total control over what sort of functions/builtins are permitted? It seems that the AST method is sort of similar to this approach - is the former preferable?
I realise that there's no completely safe way to execute untrusted scripts, I'm really just looking for a way that's safe enough, while still being versatile.