You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

116 lines
3.8 KiB
Python

from statement import Rule, GrouperRule, AllenRule, Field, Arg
from ftreader import FtReader
import os
def flatten(l):
if isinstance(l,list):
return sum(map(flatten,l))
else:
return l
def if_exists_delete(path):
if os.path.exists(path):
if path[path.find('h5'):] == 'h5':
os.remove(path)
def iterate_subrules(rule):
for arg in rule.args:
if type(arg) in [Rule, GrouperRule, AllenRule]:
for r in iterate_subrules(arg):
yield r
yield arg
def iterate_args(rule):
for arg in rule.args:
yield arg
def iterate_rules(filter):
for rule_list in filter.rules:
for rule in rule_list:
if type(rule) not in [Rule, GrouperRule, AllenRule]:
continue
yield rule
for r in iterate_subrules(rule):
yield r
# returns the operation implementation from operators.py
# module, based on the operation contained in rule.op attribute
def find_op(rule, module='operators'):
imp = __import__(module)
op_name = rule.op
# print getattr(imp, op_name)
try:
return getattr(imp, op_name)
except AttributeError:
try:
external_imp = getattr(imp, 'external_import')
return getattr(external_imp, op_name)
except AttributeError:
raise SyntaxError('Uknown operator %s at line %s.'%(op_name,
rule.line))
def get_input_reader(parser):
# TODO: create reader somewhere else
"""Returns a reader for the parser's input"""
if not getattr(parser, "reader", None):
parser.reader = FtReader(parser.input.name)
return parser.reader
def check_rule_fields(rule, reader):
for arg in rule.args:
if type(arg) is Field:
if reader.supports_attr(arg.name):
continue
else:
if arg.name == "rec_id":
continue
msg = 'There is no such field %s, '%arg.name
msg += 'referenced at line %s'%rule.line
raise SyntaxError(msg)
def replace_bound_rules(filter):
'''
Iterate over the rules replacing evaluatable rules with their values
until there's nothing left to replace i.e. all remaining rules have
field references.
'''
def evaluate_rule(rule):
'''
Evaluates rule if possible i.e. rule contains no record field
references. If evaluation is not possible returns the original
rule.
'''
arg_types = [type(x) for x in rule.args]
if Rule in arg_types or Field in arg_types:
return rule
else:
# no references to record fields evaluate now
replace_bound_rules.count += 1
op = find_op(rule)
# hasattr() takes care of already replaced values
args = [a.value if hasattr(a, 'value') else a
for a in rule.args]
result = op(*args) if not rule.NOT else not op(*args)
return result
replace_bound_rules.count = 0
for rule in iterate_rules(filter):
newargs = [evaluate_rule(arg) if type(arg) is Rule else arg
for arg in rule.args]
rule.args = newargs
# we have to break because nasty stuff happens
# because the iterable is being changed
if replace_bound_rules.count !=0:
break
if replace_bound_rules.count != 0:
replace_bound_rules.count = 0
replace_bound_rules(filter)
def replace_with_vals(filter):
for rule in iterate_rules(filter):
for i, arg in enumerate(rule.args):
if type(arg) is Arg:
rule.args[i] = arg.value