def test_everything(): values = { 'form': { 'input': "no", }, } tree = Condition().parse( '!!3<0 || !(form.input == "0" && ("da" != "de"))' ) assert ConditionTransformer(values).transform(tree) is True tree = Condition().parse( '!!3<0 OR !(form.input == "0" AND ("da" != "de"))' ) assert ConditionTransformer(values).transform(tree) is True
def test_condition(): values = { 'first_form': { 'param1': 'value1', }, 'second_form': { 'param1': 'value1', 'param2': 'value2', }, } tree = Condition().parse('first_form.param1 == "value1"') assert ConditionTransformer(values).transform(tree) is True tree = Condition().parse('second_form.param1 == "value1"') assert ConditionTransformer(values).transform(tree) is True tree = Condition().parse('second_form.param2 == "value2"') assert ConditionTransformer(values).transform(tree) is True tree = Condition().parse('first_form.param1 != "nonsense"') assert ConditionTransformer(values).transform(tree) is True tree = Condition().parse('first_form.param1 == "nonsense"') assert ConditionTransformer(values).transform(tree) is False tree = Condition().parse('first_form.param1 == second_form.param1') assert ConditionTransformer(values).transform(tree) is True tree = Condition().parse('first_form.param1 == second_form.param2') assert ConditionTransformer(values).transform(tree) is False
def test_logic_operators(): values = { 'set': { 'A': True, 'B': False, }, } tree = Condition().parse('set.A || set.B') assert ConditionTransformer(values).transform(tree) is True tree = Condition().parse('set.A && set.B') assert ConditionTransformer(values).transform(tree) is False tree = Condition().parse('set.A AND set.B') assert ConditionTransformer(values).transform(tree) is False tree = Condition().parse('set.A OR set.B') assert ConditionTransformer(values).transform(tree) is True tree = Condition().parse('set.A AND set.B OR set.A') assert ConditionTransformer(values).transform(tree) is True tree = Condition().parse('set.B OR set.B OR set.A') assert ConditionTransformer(values).transform(tree) is True tree = Condition().parse('set.A AND set.B AND set.A') assert ConditionTransformer(values).transform(tree) is False
def test_no(): values = { 'set': { 'A': True, 'B': False, }, } tree = Condition().parse('!set.A') assert ConditionTransformer(values).transform(tree) is False tree = Condition().parse('set.A && !set.B') assert ConditionTransformer(values).transform(tree) is True tree = Condition().parse('!set.A && set.B') assert ConditionTransformer(values).transform(tree) is False tree = Condition().parse('!!0>-2') assert ConditionTransformer(values).transform(tree) is True
def test_aritmetic_operators(): values = { 'set': { 'A': -1, 'B': 1, 'C': 1.0, 'D': 1.5, }, } tree = Condition().parse('set.A < set.B') assert ConditionTransformer(values).transform(tree) is True tree = Condition().parse('set.A > set.B') assert ConditionTransformer(values).transform(tree) is False tree = Condition().parse('set.B < set.C') assert ConditionTransformer(values).transform(tree) is False tree = Condition().parse('set.B <= set.C') assert ConditionTransformer(values).transform(tree) is True tree = Condition().parse('set.C < set.D') assert ConditionTransformer(values).transform(tree) is True
def work(self, config, state, channel, mongo): tree = Condition().parse(self.condition) try: value = ConditionTransformer(state['values']).transform(tree) except ValueError as e: raise InconsistentState('Could not evaluate condition: {}'.format( str(e))) return [ Form.state_json(self.id, [{ 'name': 'condition', 'state': 'valid', 'type': 'bool', 'value': value, }]) ]
def test_list(): tree = Condition().parse('[]') assert ConditionTransformer({}).transform(tree) == [] tree = Condition().parse('["hello",]') assert ConditionTransformer({}).transform(tree) == ['hello'] tree = Condition().parse('[0]') assert ConditionTransformer({}).transform(tree) == [0] tree = Condition().parse('[1, 2, 3]') assert ConditionTransformer({}).transform(tree) == [1, 2, 3] tree = Condition().parse('3 IN [1, 2, 3]') assert ConditionTransformer({}).transform(tree) is True tree = Condition().parse('4 NOT IN [1, 2, 3]') assert ConditionTransformer({}).transform(tree) is True tree = Condition().parse('4 IN [1, 2, 3]') assert ConditionTransformer({}).transform(tree) is False tree = Condition().parse('[1, 2, 3] == [1, 2, 3,]') assert ConditionTransformer({}).transform(tree) is True
def test_constants(): tree = Condition().parse('TRUE') assert ConditionTransformer({}).transform(tree) is True tree = Condition().parse('FALSE') assert ConditionTransformer({}).transform(tree) is False
def _validate_file(filename, verbose=False): ids = [] data_form = ChainMap() passed_nodes = [] variable_re = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*$') class StreamWrapper: def __init__(self, filename): self.f = open(filename) self.lineno = 0 def read(self, b): self.lineno += 1 return self.f.readline() sw = StreamWrapper(filename) def check_id(node): id_element = node.getAttribute('id') if not id_element: raise MalformedProcess('{}:{} All nodes must have an id'.format( filename, sw.lineno)) if not variable_re.match(id_element): raise MalformedProcess( '{}:{} Id must be a valid variable name'.format( filename, sw.lineno, )) if id_element not in ids: ids.append(id_element) else: raise MalformedProcess("{}:{} Duplicated id: '{}'".format( filename, sw.lineno, id_element, )) doc = pulldom.parse(sw) for event, node in doc: if event == pulldom.START_ELEMENT and node.tagName == 'block': data_form.maps.append(dict()) if event == pulldom.END_ELEMENT and node.tagName == 'block': data_form.maps.pop() if event != pulldom.START_ELEMENT: continue if node.tagName == 'condition': doc.expandNode(node) try: tree = Condition().parse(get_text(node)) except GrammarError: raise MalformedProcess( '{}:{} Grammar error in condition'.format( filename, sw.lineno, )) except ParseError: raise MalformedProcess('{}:{} Parse error in condition'.format( filename, sw.lineno, )) except LexError: raise MalformedProcess('{}:{} Lex error in condition'.format( filename, sw.lineno)) except KeyError as e: raise MalformedProcess( '{}:{} variable does not exist: {}'.format( filename, sw.lineno, str(e), )) # validate variables used in condition for tree in tree.find_data('ref'): reference_form, field_form = list( map(lambda x: x.children[0][:], tree.children)) try: data_form[reference_form][field_form] except KeyError: raise MalformedProcess("{}:{} variable used in condition " "is not defined '{}'".format( filename, sw.lineno, reference_form + '.' + field_form, )) continue if node.tagName not in NODES: continue # Duplicate ids check_id(node) if node.tagName == 'if': continue # Expand and check this node. <if> nodes are not expanded doc.expandNode(node) # Check auth-filter params params = node.getElementsByTagName("param") for param in params: if param.getAttribute('type') != 'ref': continue ref_type, ref = get_text(param).split('#') if ref_type == 'form': reference_form, field_form = ref.split('.') try: data_form[reference_form][field_form] except KeyError: raise MalformedProcess( "{}:{} Referenced param does not exist '{}'".format( filename, sw.lineno, reference_form + '.' + field_form, )) elif ref_type == 'user': if ref not in passed_nodes: raise MalformedProcess( '{}:{} Referenced user is never created: {}'.format( filename, sw.lineno, ref, )) # Check dependencies deps = node.getElementsByTagName("dep") for dep in deps: form, field = get_text(dep).split('.') try: data_form[form][field] except KeyError: raise MalformedProcess( "{}:{} Referenced dependency does not exist '{}'".format( filename, sw.lineno, form + '.' + field, )) # fill forms for later usage forms = node.getElementsByTagName('form') for form in forms: form_id = form.getAttribute('id') if form_id and not variable_re.match(form_id): raise MalformedProcess( '{}:{} Form ids must be valid variable names'.format( filename, sw.lineno, )) form_ref = form.getAttribute('ref') if form_ref and not variable_re.match(form_ref): raise MalformedProcess( '{}:{} Form refs must be valid variable names'.format( filename, sw.lineno, )) inputs = form.getElementsByTagName("input") array_input = {} for inpt in inputs: inpt_name = inpt.getAttribute('name') if not variable_re.match(inpt_name): raise MalformedProcess( '{}:{} Field names must match [a-zA-Z0-9_]+'.format( filename, sw.lineno, )) array_input[inpt_name] = \ inpt.getAttribute('default') data_form.maps[-1][form_id] = array_input # In case of a request node, add its captured values to `data_form` # so they can be recognized as valid values captures = node.getElementsByTagName('capture') for capture in captures: capture_id = capture.getAttribute('id') if capture_id and not variable_re.match(capture_id): raise MalformedProcess( '{}:{} Capture ids must be valid variable names'.format( filename, sw.lineno, )) capture_inputs = capture.getElementsByTagName("value") array_input = {} for inpt in capture_inputs: inpt_name = inpt.getAttribute('name') if not variable_re.match(inpt_name): raise MalformedProcess( '{}:{} names must be valid variable names'.format( filename, sw.lineno, )) array_input[inpt_name] = '1' data_form.maps[-1][capture_id] = array_input # add this node to the list of revised nodes has_auth_filter = len(node.getElementsByTagName('auth-filter')) > 0 if has_auth_filter: passed_nodes.append(node.getAttribute('id')) if verbose: print('{} seems correct'.format(filename))