Make expression parser support instrumented attrs

This commit is contained in:
Konsta Vesterinen
2014-05-07 15:19:28 +03:00
parent 5b00373f9f
commit 823ad79d9b
2 changed files with 35 additions and 31 deletions

View File

@@ -1,5 +1,11 @@
try:
from collections import OrderedDict
except ImportError:
from ordereddict import OrderedDict
import six import six
import sqlalchemy as sa import sqlalchemy as sa
from sqlalchemy.orm.attributes import InstrumentedAttribute
from sqlalchemy.sql.annotation import AnnotatedColumn from sqlalchemy.sql.annotation import AnnotatedColumn
from sqlalchemy.sql.expression import ( from sqlalchemy.sql.expression import (
BooleanClauseList, BooleanClauseList,
@@ -21,43 +27,38 @@ from sqlalchemy.sql.elements import (
class ExpressionParser(object): class ExpressionParser(object):
parsers = OrderedDict((
(BinaryExpression, 'binary_expression'),
(BooleanClauseList, 'boolean_expression'),
(UnaryExpression, 'unary_expression'),
(sa.Column, 'column'),
(AnnotatedColumn, 'column'),
(BindParameter, 'bind_parameter'),
(False_, 'false'),
(True_, 'true'),
(Grouping, 'grouping'),
(ClauseList, 'clause_list'),
(Label, 'label'),
(Cast, 'cast'),
(Case, 'case'),
(Tuple, 'tuple'),
(Null, 'null'),
(InstrumentedAttribute, 'instrumented_attribute')
))
def expression(self, expr): def expression(self, expr):
if expr is None: if expr is None:
return return
if isinstance(expr, BinaryExpression): for class_, parser in self.parsers.items():
return self.binary_expression(expr) if isinstance(expr, class_):
elif isinstance(expr, BooleanClauseList): return getattr(self, parser)(expr)
return self.boolean_expression(expr)
elif isinstance(expr, UnaryExpression):
return self.unary_expression(expr)
elif isinstance(expr, sa.Column):
return self.column(expr)
elif isinstance(expr, AnnotatedColumn):
return self.column(expr)
elif isinstance(expr, BindParameter):
return self.bind_parameter(expr)
elif isinstance(expr, False_):
return self.false(expr)
elif isinstance(expr, True_):
return self.true(expr)
elif isinstance(expr, Grouping):
return self.grouping(expr)
elif isinstance(expr, ClauseList):
return self.clause_list(expr)
elif isinstance(expr, Label):
return self.label(expr)
elif isinstance(expr, Cast):
return self.cast(expr)
elif isinstance(expr, Case):
return self.case(expr)
elif isinstance(expr, Tuple):
return self.tuple(expr)
elif isinstance(expr, Null):
return self.null(expr)
raise Exception( raise Exception(
'Unknown expression type %s' % expr.__class__.__name__ 'Unknown expression type %s' % expr.__class__.__name__
) )
def instrumented_attribute(self, expr):
return expr
def null(self, expr): def null(self, expr):
return expr return expr

View File

@@ -12,6 +12,9 @@ class MyExpressionParser(ExpressionParser):
def column(self, column): def column(self, column):
return getattr(self.parent, column.key) return getattr(self.parent, column.key)
def instrumented_attribute(self, column):
return getattr(self.parent, column.key)
class TestExpressionParser(TestCase): class TestExpressionParser(TestCase):
create_tables = False create_tables = False
@@ -82,4 +85,4 @@ class TestExpressionParser(TestCase):
def test_instrumented_attribute(self): def test_instrumented_attribute(self):
expr = self.parser(self.User.name) expr = self.parser(self.User.name)
assert str(expr) == 'category.name' assert str(expr) == 'Category.name'