cleanup accept and leave method on various visitable object (closes #89659) stable
authorPierre-Yves David <pierre-yves.david@logilab.fr>
Fri, 16 Mar 2012 16:47:20 +0100
branchstable
changeset 687 2a532f897388
parent 686 9a61c1d4c3db
child 688 6b15ab059caa
cleanup accept and leave method on various visitable object (closes #89659) The old code did: * forge a string * eval it as a lamba * monkey patch classes with the result We may just drop the logic looping on multiple class by computing class name dynamically. But this have a different behavior for subclass.
base.py
nodes.py
stmts.py
utils.py
--- a/base.py	Mon Feb 20 11:07:39 2012 +0100
+++ b/base.py	Fri Mar 16 16:47:20 2012 +0100
@@ -22,8 +22,10 @@
 
 __docformat__ = "restructuredtext en"
 
+from rql.utils import VisitableMixIn
 
-class BaseNode(object):
+
+class BaseNode(VisitableMixIn):
     __slots__ = ('parent',)
 
     def __str__(self):
--- a/nodes.py	Mon Feb 20 11:07:39 2012 +0100
+++ b/nodes.py	Fri Mar 16 16:47:20 2012 +0100
@@ -32,8 +32,8 @@
 
 from rql import CoercionError, RQLException
 from rql.base import BaseNode, Node, BinaryNode, LeafNode
-from rql.utils import (function_description, quote, uquote, build_visitor_stub,
-                       common_parent)
+from rql.utils import (function_description, quote, uquote, common_parent,
+                       VisitableMixIn)
 
 CONSTANT_TYPES = frozenset((None, 'Date', 'Datetime', 'Boolean', 'Float', 'Int',
                             'String', 'Substitute', 'etype'))
@@ -901,7 +901,7 @@
 
 ###############################################################################
 
-class Referenceable(object):
+class Referenceable(VisitableMixIn):
     __slots__ = ('name', 'stinfo', 'stmt')
 
     def __init__(self, name):
@@ -1133,6 +1133,3 @@
         return len(stinfo['selected']) + len(stinfo['relations'])
 
 
-build_visitor_stub((SubQuery, And, Or, Not, Exists, Relation,
-                    Comparison, MathExpression, UnaryExpression, Function,
-                    Constant, VariableRef, SortTerm, ColumnAlias, Variable))
--- a/stmts.py	Mon Feb 20 11:07:39 2012 +0100
+++ b/stmts.py	Fri Mar 16 16:47:20 2012 +0100
@@ -31,7 +31,7 @@
 
 from rql import BadRQLQuery, CoercionError, nodes
 from rql.base import BaseNode, Node
-from rql.utils import rqlvar_maker, build_visitor_stub
+from rql.utils import rqlvar_maker
 
 _MARKER = object()
 
@@ -1113,4 +1113,3 @@
         return new
 
 
-build_visitor_stub((Union, Select, Insert, Delete, Set))
--- a/utils.py	Mon Feb 20 11:07:39 2012 +0100
+++ b/utils.py	Fri Mar 16 16:47:20 2012 +0100
@@ -156,14 +156,19 @@
     res.append(u'"')
     return u''.join(res)
 
-# Visitor #####################################################################
+
+
+class VisitableMixIn(object):
 
-_accept = 'lambda self, visitor, *args, **kwargs: visitor.visit_%s(self, *args, **kwargs)'
-_leave = 'lambda self, visitor, *args, **kwargs: visitor.leave_%s(self, *args, **kwargs)'
-def build_visitor_stub(classes):
-    for cls in classes:
-        cls.accept = eval(_accept % (cls.__name__.lower()))
-        cls.leave = eval(_leave % (cls.__name__.lower()))
+    def accept(self, visitor, *args, **kwargs):
+        visit_id = self.__class__.__name__.lower()
+        visit_method = getattr(visitor, 'visit_%s' % visit_id)
+        return visit_method(self, *args, **kwargs)
+
+    def leave(self, visitor, *args, **kwargs):
+        visit_id = self.__class__.__name__.lower()
+        visit_method = getattr(visitor, 'leave_%s' % visit_id)
+        return visit_method(self, *args, **kwargs)
 
 class RQLVisitorHandler(object):
     """Handler providing a dummy implementation of all callbacks necessary