def test_traverse_match_tree(self): match_tree = { 'and': [ {'or': [ {'match': {'source': 'domain', 'function': 'exact', 'input': 'example.com'}} ]}, {'and': [ {'not': {'or': [ {'match': {'source': 'path', 'function': 'regex', 'input': 'foo'}} ]}} ]}, {'not': {'not': { 'match': {'source': 'path', 'function': 'ends_with', 'input': 'yeah'} }}} ] } exp_data_out = ('and[' 'or[domain:exact(example.com)],' 'and[!or[path:regex(foo)]],' 'path:ends_with(yeah)' ']') data_out = parser.traverse_match_tree(self.traverse_functions, match_tree) self.assertEqual(data_out, exp_data_out)
def get_match_path_fsm(match_tree, worker_pool=None): if worker_pool is None: worker_pool = concurrent.futures.ProcessPoolExecutor(max_workers=1) alphabet = set(string.printable) def handle_condition_list(data_list_in, op, negate): def divide_and_conquer(fsm_list, op): num_items = len(fsm_list) fsm_future1 = None fsm_future2 = None if num_items == 1: return fsm_list[0] elif num_items == 2: fsm_future1 = fsm_list[0] fsm_future2 = fsm_list[1] else: half = num_items // 2 fsm_future1 = divide_and_conquer(fsm_list[:half], op) fsm_future2 = divide_and_conquer(fsm_list[half:], op) if fsm_future1 is None and fsm_future2 is None: return None if fsm_future1 is None: return fsm_future2 if fsm_future2 is None: return fsm_future1 fsm_result1 = fsm_future1.result() fsm_result2 = fsm_future2.result() future = worker_pool.submit(fsm_action_task, op, fsm_result1, fsm_result2) return future fsm_future = divide_and_conquer(data_list_in, op) if fsm_future is not None and negate: fsm_result = fsm_future.result() fsm_future = worker_pool.submit(fsm_negate_task, fsm_result) return fsm_future def handle_match(src, fun, inp, negate): if not src == "path": return None value = inp["value"] lego_regex = value if fun == "regex" else lego_re_escape(value) if inp.get("ignore_case", False): lego_regex = lego_ignore_case(lego_regex) if fun == "begins_with": regex = lego_regex + r".*" elif fun == "ends_with": regex = r".*" + lego_regex elif fun == "contains": regex = r".*" + lego_regex + r".*" elif fun in ("exact", "regex"): regex = lego_regex else: raise ValidateRuleConstraintsException("Handling of " "match function " + str(fun) + " not implemented.") future = worker_pool.submit(fsm_parse_regex_task, regex, negate, alphabet) return future func = { "handle_condition_list": handle_condition_list, "handle_match": handle_match, } fsm_future = parser.traverse_match_tree(func, match_tree) if fsm_future is None: return lego.parse(".*").to_fsm(alphabet) fsm_result = fsm_future.result() return fsm_result
def get_match_path_fsm(match_tree, worker_pool=None): if worker_pool is None: worker_pool = concurrent.futures.ProcessPoolExecutor(max_workers=1) alphabet = set(string.printable) def handle_condition_list(data_list_in, op, negate): def divide_and_conquer(fsm_list, op): num_items = len(fsm_list) fsm_future1 = None fsm_future2 = None if num_items == 1: return fsm_list[0] elif num_items == 2: fsm_future1 = fsm_list[0] fsm_future2 = fsm_list[1] else: half = num_items // 2 fsm_future1 = divide_and_conquer(fsm_list[:half], op) fsm_future2 = divide_and_conquer(fsm_list[half:], op) if fsm_future1 is None and fsm_future2 is None: return None if fsm_future1 is None: return fsm_future2 if fsm_future2 is None: return fsm_future1 fsm_result1 = fsm_future1.result() fsm_result2 = fsm_future2.result() future = worker_pool.submit(fsm_action_task, op, fsm_result1, fsm_result2) return future fsm_future = divide_and_conquer(data_list_in, op) if fsm_future is not None and negate: fsm_result = fsm_future.result() fsm_future = worker_pool.submit(fsm_negate_task, fsm_result) return fsm_future def handle_match(src, fun, inp, negate): if not src == 'path': return None value = inp['value'] lego_regex = value if fun == 'regex' else lego_re_escape(value) if inp.get('ignore_case', False): lego_regex = lego_ignore_case(lego_regex) if fun == 'begins_with': regex = lego_regex + r'.*' elif fun == 'ends_with': regex = r'.*' + lego_regex elif fun == 'contains': regex = r'.*' + lego_regex + r'.*' elif fun in ('exact', 'regex'): regex = lego_regex else: raise ValidateRuleConstraintsException('Handling of ' 'match function ' + str(fun) + ' not implemented.') future = worker_pool.submit(fsm_parse_regex_task, regex, negate, alphabet) return future func = { 'handle_condition_list': handle_condition_list, 'handle_match': handle_match } fsm_future = parser.traverse_match_tree(func, match_tree) if fsm_future is None: return lego.parse('.*').to_fsm(alphabet) fsm_result = fsm_future.result() return fsm_result