def parse(s, globals=None, conditional_context=None, expression=True, autovariables=False): if not isinstance(s, basestring): return s # this prevents any function named something ending in "if" str_to_parse = s.replace('if(', 'where(') str_to_parse = and_re.sub(r'\1&\2', str_to_parse) str_to_parse = or_re.sub(r'\1|\2', str_to_parse) str_to_parse = not_re.sub(r'\1~', str_to_parse) mode = 'eval' if expression else 'exec' try: c = compile(str_to_parse, '<expr>', mode) except SyntaxError: # SyntaxError are clearer if left unmodified since they already contain # the faulty string # Instances of this class have attributes filename, lineno, offset and # text for easier access to the details. str() of the exception # instance returns only the message. raise except Exception, e: raise add_context(e, s)
# field/link actually exist in the context it is used. # the Token class above was my first naive try at doing that, however, # it's not as easy as I first thought because functions need to be # delayed too. if conditional_context is not None: for var in c.co_names: if var in conditional_context: context.update(conditional_context[var]) context.update(functions) if globals is not None: context.update(globals) context['__builtins__'] = None if expression: try: return eval(c, context) #IOError and such. Those are clearer when left unmodified. except EnvironmentError: raise except Exception, e: raise add_context(e, s) else: exec c in context # cleanup result del context['__builtins__'] for funcname in functions.keys(): del context[funcname] return context