def visit(self, node, *args):
     "Recursively validate node and all of its children."
     fn = getattr(self, 'visit' + Helpers.classname(node))
     if Helpers.DEBUG(): self.trace(node)
     fn(node, *args)
     for child in node.getChildNodes():
         self.visit(child, *args)
 def trace(self, node):
     "Debugging utility for tracing the validation of AST nodes."
     print Helpers.classname(node)
     for attr in dir(node):
         if attr[:2] != '__':
             print ' ' * 4, "%-15.15s" % attr, getattr(node, attr)
 def fail(self, node, *args):
     "Default callback for unallowed AST nodes."
     lineno = Helpers.get_node_lineno(node)
     self.errors.append(SafeEvalASTNodeError( \
         "execution of '%s' statements is denied" % Helpers.classname(node),
         lineno))