def test_or_operator_does_not_evaluate_depth_first(self): # 'or' operator should stop at first truthy value evaluated_elements = [] def push(arg): evaluated_elements.append(arg) return arg add_operation('push', push) jsonLogic({'or': [{'push': [False]}, {'push': [False]}]}) self.assertSequenceEqual(evaluated_elements, [False, False]) del (evaluated_elements[:]) jsonLogic({'or': [{'push': [False]}, {'push': [True]}]}) self.assertSequenceEqual(evaluated_elements, [False, True]) del (evaluated_elements[:]) jsonLogic({'or': [{'push': [True]}, {'push': [False]}]}) self.assertSequenceEqual(evaluated_elements, [True]) del (evaluated_elements[:]) jsonLogic({'or': [{'push': [True]}, {'push': [True]}]}) self.assertSequenceEqual(evaluated_elements, [True])
def test_ternary_operator_does_not_evaluate_depth_first(self): # False consequent of '?:' operation condition should not run consequents = [] def push_then(arg): consequents.append(arg) return arg def push_else(arg): consequents.append(arg) return arg add_operation('push_then', push_then) add_operation('push_else', push_else) jsonLogic({ '?:': [True, { 'push_then': ["first"] }, { 'push_else': ["second"] }] }) self.assertSequenceEqual(consequents, ["first"]) del (consequents[:]) jsonLogic({ '?:': [False, { 'push_then': ["first"] }, { 'push_else': ["second"] }] }) self.assertSequenceEqual(consequents, ["second"])
def test_rm_operation_removes_custom_operation(self): add_operation('custom', lambda: "Ha-ha!") try: self.assertEqual(jsonLogic({'custom': []}), "Ha-ha!") finally: rm_operation('custom') self.assertRaisesRegex(ValueError, "Unrecognized operation", jsonLogic, {'custom': []})
def test_rm_operation_restores_overridden_operation(self): self.assertEqual(jsonLogic({'+': [2, 3]}), 5) add_operation('+', lambda *args: "Ha-ha!") try: self.assertEqual(jsonLogic({'+': [2, 3]}), "Ha-ha!") finally: rm_operation('+') self.assertEqual(jsonLogic({'+': [2, 3]}), 5) self.assertNotEqual(jsonLogic({'+': [2, 3]}), "Ha-ha!")
def test_rm_operation_updates_exposed_operations_list(self): haha = lambda *args: "Ha-ha!" add_operation('custom', haha) try: self.assertIn('custom', operations) self.assertIs(operations['custom'], haha) finally: rm_operation('custom') self.assertNotIn('custom', operations)
def test_add_operation_overrides_existing_exposed_operations(self): haha = lambda *args: "Ha-ha!" self.assertIn('+', operations) self.assertIsNot(operations['+'], haha) add_operation('+', haha) try: self.assertIn('+', operations) self.assertIs(operations['+'], haha) finally: rm_operation('+')
def test_rm_operation_restores_overridden_operation_in_exposed_list(self): haha = lambda *args: "Ha-ha!" add_operation('+', haha) try: self.assertIn('+', operations) self.assertIs(operations['+'], haha) finally: rm_operation('+') self.assertIn('+', operations) self.assertIsNot(operations['+'], haha)
def test_depth_first_rule_still_applies_to_custom_operators(self): add_operation('sum_up', lambda *args: sum(args)) try: self.assertEqual( jsonLogic({'sum_up': [{ '-': [5, 3] }, { '*': [2, 3] }]}), 8) finally: rm_operation('sum_up')
def test_add_operation_with_simple_method(self): def add_to_five(*args): return sum((5, ) + args) self.assertRaisesRegex(ValueError, "Unrecognized operation", jsonLogic, {'add_to_five': [3]}) add_operation('add_to_five', add_to_five) try: self.assertEqual(jsonLogic({'add_to_five': 1}), 6) self.assertEqual(jsonLogic({'add_to_five': [3]}), 8) self.assertEqual(jsonLogic({'add_to_five': [3, 2]}), 10) finally: rm_operation('add_to_five')
def test_add_operation_with_packages_fails_midway(self): add_operation('datetime', datetime) try: self.assertRaisesRegex(ValueError, "datetime\.wrong_property(?!\.now)", jsonLogic, {'datetime.wrong_property.now': []}) self.assertRaisesRegex(ValueError, "datetime\.datetime.wrong_method", jsonLogic, {'datetime.datetime.wrong_method': []}) finally: rm_operation('datetime')
def test_add_operation_with_packages(self): self.assertRaisesRegex(ValueError, "Unrecognized operation.*datetime", jsonLogic, {'datetime.datetime.now': []}) add_operation('datetime', datetime) try: # .now() start = datetime.datetime.now() returned_value = jsonLogic({'datetime.datetime.now': []}) self.assertIsInstance(returned_value, datetime.datetime) self.assertTrue(start <= returned_value <= datetime.datetime.now()) # .date() returned_value = jsonLogic({'datetime.date': [2018, 1, 1]}) self.assertIsInstance(returned_value, datetime.date) self.assertEqual(returned_value, datetime.date(2018, 1, 1)) finally: rm_operation('datetime')
def test_add_operation_does_not_override_other_operation_types(self): test_data = (('if', [True, "yes", "no"], {}, "yes"), ('map', [[1, 2, 3], { '*': [{ 'var': '' }, 2] }], {}, [2, 4, 6]), ('var', 'a', { 'a': "Ta-da!" }, "Ta-da!")) for operation, arguments, data, expected_result in test_data: add_operation(operation, lambda *args: "Ha-ha!") try: result = jsonLogic({operation: arguments}, data) self.assertEqual(result, expected_result, operation) self.assertNotEqual(result, "Ha-ha!", operation) finally: rm_operation(operation)
def validate(self, data, mode=MODE_LOOSE): """ The main validator function. 0. If column headers, dropdown values are not proper MDS values, it looks up a translation dictionary and converts them 1. If dates (DOB, episode start, end) are not proper dates, it logs ERRORs and excludes the logic validation checks that involve those fields. 2. Does schema validation using the schema specified in JSON files (schema folder). 3. Does MDS Logic validation using MDS_RULES.py (jsonLogic) """ warnings = {} episodes = data['episodes'] id_field = MDS['ID'] if mode == MODE_LOOSE: # withouth the deep copy of episodes warnings = translate_to_MDS_values(episodes)# translate to official MDS values data = {'episodes': episodes} errors, ercode = self.check_schema_errors(data, id_field) if ercode == -1: return errors, -1 add_operation('has_duplicate_values', has_duplicate_values) add_operation('check_slk', self.check_slk) # change to is_invalid_slk add_operation('has_blanks_in_otherdrugs', has_gaps) add_operation('is_valid_drug_use', is_valid_drug_use) # change to is_invalid_drug use add_operation('is_notin_period', self.is_notin_period) client_eps = {} fn_date_converter = get_date_converter(sample_date_str=episodes[0][MDS_Dates[0]]) for i, ep_data in enumerate(episodes): date_conversion_errors = fix_check_dates(ep_data, i, fn_date_converter, id_field, MDS_Dates) self.validate_logic(errors, ep_data, i, date_conversion_errors, id_field, client_eps) if self.slk_suggestions: fuse_suggestions_into_errors(errors, self.slk_suggestions) return errors , warnings
'''Examples sparql wrapper''' from SPARQLWrapper import SPARQLWrapper, JSON from json_logic import jsonLogic from json_logic import add_operation import editdistance sparql = SPARQLWrapper("http://dbpedia.org/sparql") add_operation("edit_distance", editdistance.eval) '''print(jsonLogic({"edit_distance" : ['bahama', 'banana']})) print(jsonLogic({"edit_distance" : ['bahama', 'de']})) print(jsonLogic({"edit_distance" : ['bahama', 'rear']})) print(jsonLogic({"some" : [["banana", "de", "rear"], { "<=" : [{"edit_distance" : [{"var" : ""}, "bahama"]}, 2]}]})) ''' y = """ PREFIX dbo: <http://dbpedia.org/ontology/> SELECT ?object WHERE { <http://dbpedia.org/resource/Milan> dbo:country ?object. } """ y = """SELECT ?object WHERE { <http://dbpedia.org/resource/Milan> <http://dbpedia.org/ontology/country> ?object. }""" print(y) sparql.setQuery(y) sparql.setReturnFormat(JSON) results1 = sparql.query().convert() print(results1) for result in results1["results"]["bindings"]: print("result:", result) print("object:", result["object"]) print("type:", result["object"]["type"])
def test_if_operator_does_not_evaluate_depth_first(self): # 'if' operation should stop at first truthy condition. # Consequents of falsy conditions should not be evaluated. conditions = [] consequents = [] def push_if(arg): conditions.append(arg) return arg def push_then(arg): consequents.append(arg) return arg def push_else(arg): consequents.append(arg) return arg add_operation('push_if', push_if) add_operation('push_then', push_then) add_operation('push_else', push_else) jsonLogic({ 'if': [{ 'push_if': [True] }, { 'push_then': ["first"] }, { 'push_if': [False] }, { 'push_then': ["second"] }, { 'push_else': ["third"] }] }) self.assertSequenceEqual(conditions, [True]) self.assertSequenceEqual(consequents, ["first"]) del (conditions[:]) del (consequents[:]) jsonLogic({ 'if': [{ 'push_if': [False] }, { 'push_then': ["first"] }, { 'push_if': [True] }, { 'push_then': ["second"] }, { 'push_else': ["third"] }] }) self.assertSequenceEqual(conditions, [False, True]) self.assertSequenceEqual(consequents, ["second"]) del (conditions[:]) del (consequents[:]) jsonLogic({ 'if': [{ 'push_if': [False] }, { 'push_then': ["first"] }, { 'push_if': [False] }, { 'push_then': ["second"] }, { 'push_else': ["third"] }] }) self.assertSequenceEqual(conditions, [False, False]) self.assertSequenceEqual(consequents, ["third"])
#print("object:", result["object"]) #print("type:", result["object"]["type"]) #print("xml:lang:", result["object"]["xml:lang"]) #print("value:", result["object"]["value"]) #print("-----------------------------------") return results def similarity_edit(s1, s2): '''Given 2 strings, it calculates the normalized edit distance (d) between them and later the similarity (s = 1-d)''' return 1 - (editdistance.eval(s1, s2) / max(len(s1), len(s2))) '''Add normalized edit distance operation to jsonLogic''' similarity_edit_distance = similarity_edit add_operation("similarity_edit_distance", similarity_edit_distance) #print(jsonLogic({"similarity_edit_distance" : ["banana", "bahama"]})) #add_operation("edit_distance", editdistance.eval) def similarity_jaccard(s1, s2): '''Given 2 strings, it calculates the jaccard similarity between them''' return jaccard_index(s1, s2) '''Add jaccard similarity operation to jsonLogic''' add_operation("similarity_jaccard", similarity_jaccard) def similarity_equal(s1, s2): return s1 == s2
def test_add_operation_may_override_common_operations(self): add_operation('+', lambda *args: "Ha-ha!") try: self.assertEqual(jsonLogic({'+': [1, 2]}), "Ha-ha!") finally: rm_operation('+')