def test_find_where(self): # "([*] where spam ge 2).bacon" jsonpath = Child( Where(Slice(), Cmp(Fields('spam'), ge, 2)), Fields('bacon') ) matches = jsonpath.find(MENU) self.assertEqual(len(matches), 2) # There are two menu items with bacon where spam >= 2
def get_enrollments_errors(response: dict) -> dict: # $.enrollments.importSummaries[*][?(@.status='ERROR')].description jsonpath_expr = Child( Where( Child(Child(Fields("enrollments"), Fields("importSummaries")), Slice()), Cmp(Fields("status"), eq, "ERROR")), Fields("description")) matches = jsonpath_expr.find(response) return {str(match.full_path): match.value for match in matches}
def get_entity_errors(response: dict) -> dict: # $[?(@.status='ERROR')].description jsonpath_expr = Child(Where(Root(), Cmp(Fields("status"), eq, "ERROR")), Fields("description")) # We write the JSONPath expression programmatically because # currently jsonpath-ng does not support parsing comparison # expressions like ``[?(@.status='ERROR')]`` matches = jsonpath_expr.find(response) return {str(match.full_path): match.value for match in matches}
def get_jsonpath(self, attr_type_uuid): return Union( # Simple values: Return value if it has no children. # (person.attributes[*] where attributeType.uuid eq attr_type_uuid).(value where not *) Child( Where( Child(Child(Fields('person'), Fields('attributes')), Slice()), Cmp(Child(Fields('attributeType'), Fields('uuid')), eq, attr_type_uuid)), WhereNot(Fields('value'), Fields('*'))), # Concept values: Return value.uuid if value.uuid exists: # (person.attributes[*] where attributeType.uuid eq attr_type_uuid).value.uuid Child( Where( Child(Child(Fields('person'), Fields('attributes')), Slice()), Cmp(Child(Fields('attributeType'), Fields('uuid')), eq, attr_type_uuid)), Child(Fields('value'), Fields('uuid'))))
def get_property_map(case_config): """ Returns a map of case properties to OpenMRS patient properties and attributes, and a value source dict to deserialize them. """ property_map = {} for person_prop, value_source_dict in case_config[ 'person_properties'].items(): if 'case_property' in value_source_dict: jsonpath = parse_jsonpath('person.' + person_prop) property_map[value_source_dict['case_property']] = ( jsonpath, value_source_dict) for attr_type_uuid, value_source_dict in case_config[ 'person_attributes'].items(): # jsonpath_rw offers programmatic JSONPath expressions. For details on how to create JSONPath # expressions programmatically see the # `jsonpath_rw documentation <https://github.com/kennknowles/python-jsonpath-rw#programmatic-jsonpath>`__ # # The `Where` JSONPath expression "*jsonpath1* `where` *jsonpath2*" returns nodes matching *jsonpath1* # where a child matches *jsonpath2*. `Cmp` does a comparison in *jsonpath2*. It accepts a # comparison operator and a value. The JSONPath expression for matching simple attribute values is:: # # (person.attributes[*] where attributeType.uuid eq attr_type_uuid).value # # This extracts the person attribute values where their attribute type UUIDs match those configured in # case_config['person_attributes']. # # Person attributes with Concept values have UUIDs. The following JSONPath uses Union to match both simple # values and Concept values. if 'case_property' in value_source_dict: jsonpath = Union( # Simple values: Return value if it has no children. # (person.attributes[*] where attributeType.uuid eq attr_type_uuid).(value where not *) Child( Where( Child(Child(Fields('person'), Fields('attributes')), Slice()), Cmp(Child(Fields('attributeType'), Fields('uuid')), eq, attr_type_uuid)), WhereNot(Fields('value'), Fields('*'))), # Concept values: Return value.uuid if value.uuid exists: # (person.attributes[*] where attributeType.uuid eq attr_type_uuid).value.uuid Child( Where( Child(Child(Fields('person'), Fields('attributes')), Slice()), Cmp(Child(Fields('attributeType'), Fields('uuid')), eq, attr_type_uuid)), Child(Fields('value'), Fields('uuid')))) property_map[value_source_dict['case_property']] = ( jsonpath, value_source_dict) for name_prop, value_source_dict in case_config[ 'person_preferred_name'].items(): if 'case_property' in value_source_dict: jsonpath = parse_jsonpath('person.preferredName.' + name_prop) property_map[value_source_dict['case_property']] = ( jsonpath, value_source_dict) for addr_prop, value_source_dict in case_config[ 'person_preferred_address'].items(): if 'case_property' in value_source_dict: jsonpath = parse_jsonpath('person.preferredAddress.' + addr_prop) property_map[value_source_dict['case_property']] = ( jsonpath, value_source_dict) for id_type_uuid, value_source_dict in case_config[ 'patient_identifiers'].items(): if 'case_property' in value_source_dict: if id_type_uuid == 'uuid': jsonpath = parse_jsonpath('uuid') else: # The JSONPath expression below is the equivalent of:: # # (identifiers[*] where identifierType.uuid eq id_type_uuid).identifier # # Similar to `person_attributes` above, this will extract the person identifier values where # their identifier type UUIDs match those configured in case_config['patient_identifiers'] jsonpath = Child( Where( Child(Fields('identifiers'), Slice()), Cmp(Child(Fields('identifierType'), Fields('uuid')), eq, id_type_uuid)), Fields('identifier')) property_map[value_source_dict['case_property']] = ( jsonpath, value_source_dict) return property_map
def set_property_map(self, case_config): """ Set self._property_map to map OpenMRS properties and attributes to case properties. """ # Example value of case_config:: # # { # "person_properties": { # "birthdate": { # "doc_type": "CaseProperty", # "case_property": "dob" # } # }, # "person_preferred_name": { # "givenName": { # "doc_type": "CaseProperty", # "case_property": "given_name" # }, # "familyName": { # "doc_type": "CaseProperty", # "case_property": "family_name" # } # }, # "person_preferred_address": { # "address1": { # "doc_type": "CaseProperty", # "case_property": "address_1" # }, # "address2": { # "doc_type": "CaseProperty", # "case_property": "address_2" # } # }, # "person_attributes": { # "c1f4239f-3f10-11e4-adec-0800271c1b75": { # "doc_type": "CaseProperty", # "case_property": "caste" # }, # "c1f455e7-3f10-11e4-adec-0800271c1b75": { # "doc_type": "CasePropertyMap", # "case_property": "class", # "value_map": { # "sc": "c1fcd1c6-3f10-11e4-adec-0800271c1b75", # "general": "c1fc20ab-3f10-11e4-adec-0800271c1b75", # "obc": "c1fb51cc-3f10-11e4-adec-0800271c1b75", # "other_caste": "c207073d-3f10-11e4-adec-0800271c1b75", # "st": "c20478b6-3f10-11e4-adec-0800271c1b75" # } # } # } # // ... # } # for person_prop, value_source in case_config['person_properties'].items(): jsonpath = parse('person.' + person_prop) self._property_map.update(get_caseproperty_jsonpathvaluemap(jsonpath, value_source)) for attr_uuid, value_source in case_config['person_attributes'].items(): # jsonpath_rw offers programmatic JSONPath expressions. For details on how to create JSONPath # expressions programmatically see the # `jsonpath_rw documentation <https://github.com/kennknowles/python-jsonpath-rw#programmatic-jsonpath>`__ # # The `Where` JSONPath expression "*jsonpath1* `where` *jsonpath2*" returns nodes matching *jsonpath1* # where a child matches *jsonpath2*. `Cmp` does a comparison in *jsonpath2*. It accepts a # comparison operator and a value. The JSONPath expression below is the equivalent of:: # # (person.attributes[*] where attributeType.uuid eq attr_uuid).value # # This `for` loop will let us extract the person attribute values where their attribute type UUIDs # match those configured in case_config['person_attributes'] jsonpath = Child( Where( Child(Child(Fields('person'), Fields('attributes')), Slice()), Cmp(Child(Fields('attributeType'), Fields('uuid')), eq, attr_uuid) ), Fields('value') ) self._property_map.update(get_caseproperty_jsonpathvaluemap(jsonpath, value_source)) for name_prop, value_source in case_config['person_preferred_name'].items(): jsonpath = parse('person.preferredName.' + name_prop) self._property_map.update(get_caseproperty_jsonpathvaluemap(jsonpath, value_source)) for addr_prop, value_source in case_config['person_preferred_address'].items(): jsonpath = parse('person.preferredAddress.' + addr_prop) self._property_map.update(get_caseproperty_jsonpathvaluemap(jsonpath, value_source)) for id_type_uuid, value_source in case_config['patient_identifiers'].items(): if id_type_uuid == 'uuid': jsonpath = parse('uuid') else: # The JSONPath expression below is the equivalent of:: # # (identifiers[*] where identifierType.uuid eq id_type_uuid).identifier # # Similar to `person_attributes` above, this will extract the person identifier values where # their identifier type UUIDs match those configured in case_config['patient_identifiers'] jsonpath = Child( Where( Child(Fields('identifiers'), Slice()), Cmp(Child(Fields('identifierType'), Fields('uuid')), eq, id_type_uuid) ), Fields('identifier') ) self._property_map.update(get_caseproperty_jsonpathvaluemap(jsonpath, value_source))
def test_cmp_list(self): jsonpath = Cmp(Root(), eq, 1) # "[*] eq 1" matches = jsonpath.find(MENU) self.assertEqual(len(matches), 0)
def test_find_many(self): jsonpath = Cmp(Child(Slice(), Fields('spam')), gt, 0) # "[*].spam gt 0" self.assertEqual(str(jsonpath), '[*].spam gt 0') values = [match.value for match in jsonpath.find(MENU)] self.assertEqual(values, [1, 1, 1, 2, 4, 4, 10])
def test_find_one(self): max_spam = MENU[-1] jsonpath = Cmp(Fields('spam'), gt, 0) # "spam gt 0" values = [match.value for match in jsonpath.find(max_spam)] self.assertEqual(values, [10])
def test_not_equal(self): jsonpath1 = Cmp(Fields('spam'), gt, 0) jsonpath2 = Cmp(Fields('spam'), ge, 0) self.assertNotEqual(jsonpath1, jsonpath2)
def test_str(self): jsonpath = Cmp(Fields('spam'), gt, 0) self.assertEqual(str(jsonpath), 'spam gt 0')