Created
February 13, 2016 16:43
-
-
Save dsblank/25952531bba2b796922f to your computer and use it in GitHub Desktop.
Demonstration of using Python AST to represent WHERE clause in Gramps
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from meta.asttools import Visitor | |
from meta.decompiler import _ast, decompile_func | |
class ParseFilter(Visitor): | |
def visitName(self, node): | |
return node.id | |
def visitNum(self, node): | |
return node.n | |
def visitlong(self, node): | |
return node | |
def process_expression(self, expr): | |
if isinstance(expr, str): | |
# boolean | |
return [self.process_field(expr), "=", True] | |
elif len(expr) == 3: | |
# (field, op, value) | |
return [self.process_field(expr[0]), expr[1], expr[2]] | |
else: | |
# list of exprs | |
return [self.process_expression(exp) for | |
exp in expr] | |
def process_field(self, field): | |
if field.startswith(self.parameter + "."): | |
return field[len(self.parameter) + 1:] | |
else: | |
return field | |
def visitCall(self, node): | |
""" | |
Handle LIKE() | |
""" | |
return [self.process_field(self.visit(node.args[0])), | |
self.visit(node.func), | |
self.visit(node.args[1])] | |
def visitStr(self, node): | |
return node.s | |
def visitlist(self, list): | |
return [self.visit(node) for node in list] | |
def visitCompare(self, node): | |
return [self.process_field(self.visit(node.left)), | |
" ".join(self.visit(node.ops)), | |
self.visit(node.comparators[0])] | |
def visitAttribute(self, node): | |
return "%s.%s" % (self.visit(node.value), node.attr) | |
def get_boolean_op(self, node): | |
if isinstance(node, _ast.And): | |
return "AND" | |
elif isinstance(node, _ast.Or): | |
return "AND" | |
else: | |
raise Exception("invalid boolean") | |
def visitNotEq(self, node): | |
return "NE" | |
def visitBoolOp(self, node): | |
""" | |
BoolOp: boolean operator | |
""" | |
op = self.get_boolean_op(node.op) | |
values = list(node.values) | |
return [op, self.process_expression( | |
[self.visit(value) for value in values])] | |
def visitLambda(self, node): | |
self.parameter = self.visit(node.args)[0] | |
return self.visit(node.body) | |
def visitarguments(self, node): | |
return [self.visit(arg) for arg in node.args] | |
def visitarg(self, node): | |
return node.arg | |
########## | |
# Tests: | |
test1 = lambda family: (family.private and | |
family.mother_handle.gramps_id != "I0001") | |
test2 = lambda person: LIKE(person.gramps_id, "I0001") | |
tests = [test1, test2] | |
for test in tests: | |
ast_top = decompile_func(test) | |
parser = ParseFilter() | |
print(parser.visit(ast_top)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Outputs: