From 8ee2e503b75c26fd9df47ef116b61302d8cebec7 Mon Sep 17 00:00:00 2001 From: Pip Liggins Date: Mon, 13 May 2024 11:21:18 +0100 Subject: [PATCH] Make Age and Duration extensions lower case for urls (#29) * Change 'age' and 'extension' urls to be lower case, keep Uppercase for python class names * Update .gitignore * Increase test coverage --- .gitignore | 4 +++- fhirflat/resources/extensions.py | 4 ++-- fhirflat/resources/patient.py | 2 +- fhirflat/resources/procedure.py | 4 ++-- fhirflat/util.py | 7 +++++-- tests/data/patient_ext_flat.parquet | Bin 7265 -> 7265 bytes tests/data/procedure_flat.parquet | Bin 13775 -> 13775 bytes tests/test_extensions.py | 14 +++++++------- tests/test_patient_resource.py | 8 ++++---- tests/test_procedure_resource.py | 8 ++++---- tests/test_utils.py | 3 ++- 11 files changed, 30 insertions(+), 24 deletions(-) diff --git a/.gitignore b/.gitignore index 0a4126e..ad56c74 100644 --- a/.gitignore +++ b/.gitignore @@ -66,4 +66,6 @@ coverage.xml *.py,cover .hypothesis/ .pytest_cache/ -cover/ \ No newline at end of file +cover/ + +.DS_Store \ No newline at end of file diff --git a/fhirflat/resources/extensions.py b/fhirflat/resources/extensions.py index d4c1171..dad428b 100644 --- a/fhirflat/resources/extensions.py +++ b/fhirflat/resources/extensions.py @@ -316,7 +316,7 @@ class Duration(_DataType): resource_type = Field("Duration", const=True) - url = Field("Duration", const=True, alias="url") + url = Field("duration", const=True, alias="url") valueQuantity: fhirtypes.QuantityType = Field( None, @@ -352,7 +352,7 @@ class Age(_DataType): resource_type = Field("Age", const=True) - url = Field("Age", const=True, alias="url") + url = Field("age", const=True, alias="url") valueQuantity: fhirtypes.QuantityType = Field( None, diff --git a/fhirflat/resources/patient.py b/fhirflat/resources/patient.py index 06042f9..db465cb 100644 --- a/fhirflat/resources/patient.py +++ b/fhirflat/resources/patient.py @@ -22,7 +22,7 @@ class Patient(Patient, FHIRFlatBase): title="Additional content defined by implementations", description=( """ - Contains the G.H 'Age' and 'birthSex' extensions, + Contains the G.H 'age' and 'birthSex' extensions, and allows extensions from other implementations to be included.""" ), # if property is element of this resource. diff --git a/fhirflat/resources/procedure.py b/fhirflat/resources/procedure.py index 04ea0f2..2dc0989 100644 --- a/fhirflat/resources/procedure.py +++ b/fhirflat/resources/procedure.py @@ -33,7 +33,7 @@ class Procedure(_Procedure, FHIRFlatBase): title="Additional content defined by implementations", description=( """ - Contains the G.H 'timingPhase', 'relativePeriod' and 'Duration' extensions, + Contains the G.H 'timingPhase', 'relativePeriod' and 'duration' extensions, and allows extensions from other implementations to be included.""" ), # if property is element of this resource. @@ -75,7 +75,7 @@ def validate_extension_contents(cls, extensions): if duration_count > 1 or tim_phase_count > 1 or rel_phase_count > 1: raise ValueError( - "Duration, timingPhase and relativePeriod can only appear once." + "duration, timingPhase and relativePeriod can only appear once." ) return extensions diff --git a/fhirflat/util.py b/fhirflat/util.py index 1ca1a1d..fe1a8b6 100644 --- a/fhirflat/util.py +++ b/fhirflat/util.py @@ -32,7 +32,7 @@ def get_fhirtype(t: str | list[str]): if isinstance(t, list): return [get_fhirtype(x) for x in t] - if not hasattr(extensions, t): + if not (hasattr(extensions, t) or hasattr(extensions, t.capitalize())): try: return getattr(getattr(fhir.resources, t.lower()), t) except AttributeError: @@ -61,4 +61,7 @@ def get_local_extension_type(t: str): try: return getattr(extensions, t) except AttributeError: - raise AttributeError(f"Could not find {t} in fhirflat extensions") + try: + return getattr(extensions, t.capitalize()) + except AttributeError: + raise AttributeError(f"Could not find {t} in fhirflat extensions") diff --git a/tests/data/patient_ext_flat.parquet b/tests/data/patient_ext_flat.parquet index 55099d9e0e1218012ea4cf8689358670599402ec..f81ef62c612a0af68241c7d4358a112d2b54db4c 100644 GIT binary patch delta 125 zcmaE8@z7$zS;oYP=O!>FZjNV^WMxd8T*;;YB8KHitCj2V-E2ZZjNV^WMy=mT*;;YB8KHitCj82n(2cj#+1#|SbaEvoX5PXKn^G0PiC-;*ixNvR^Yiq|5_3u?7l?~&UL^I1i!o|)tEw4e_T)XP-9WNI fO?+~^ngV0?<_0xK9>(0shm4{aqc+PLZ(;%f57;df delta 137 zcmX?~eLi~wCo7}NWG>cjMwiXgSbaEvoX5PXKn^G0PiC-;**PJE-9WNI fO?+~^ngXNi<_0xK9>(m+hm4{agEq?=Z(;%fi6<*i diff --git a/tests/test_extensions.py b/tests/test_extensions.py index 7704811..49de855 100644 --- a/tests/test_extensions.py +++ b/tests/test_extensions.py @@ -107,15 +107,15 @@ def test_approximateDate(data, expected_type_date, expected_type_str): assert type(approximate_date.valueString) is expected_type_str -dur = {"url": "Duration", "valueQuantity": {"value": 3, "unit": "days"}} +dur = {"url": "duration", "valueQuantity": {"value": 3, "unit": "days"}} -def test_Duration(): - duration = Duration(**dur) - assert isinstance(duration, DataType) - assert duration.resource_type == "Duration" - assert duration.url == "Duration" - assert type(duration.valueQuantity) is _Quantity +def test_duration(): + duration_inst = Duration(**dur) + assert isinstance(duration_inst, DataType) + assert duration_inst.resource_type == "Duration" + assert duration_inst.url == "duration" + assert type(duration_inst.valueQuantity) is _Quantity dte = {"extension": [{"url": "approximateDate", "valueDate": "2021-01-01"}, rel_day]} diff --git a/tests/test_patient_resource.py b/tests/test_patient_resource.py index ea27ae1..e448353 100644 --- a/tests/test_patient_resource.py +++ b/tests/test_patient_resource.py @@ -90,7 +90,7 @@ def test_bulk_fhir_to_flat_patient(): "id": "f001", "active": True, "extension": [ - {"url": "Age", "valueQuantity": {"value": 25, "unit": "years"}}, + {"url": "age", "valueQuantity": {"value": 25, "unit": "years"}}, { "url": "birthSex", "valueCodeableConcept": { @@ -112,8 +112,8 @@ def test_bulk_fhir_to_flat_patient(): PATIENT_EXT_FLAT = { "resourceType": "Patient", "id": "f001", - "extension.Age.value": 25, - "extension.Age.unit": "years", + "extension.age.value": 25, + "extension.age.unit": "years", "extension.birthSex.code": "http://snomed.info/sct|248152002", "extension.birthSex.text": "Female (finding)", "gender": "female", @@ -123,7 +123,7 @@ def test_bulk_fhir_to_flat_patient(): PATIENT_EXT_DICT_OUT = { "id": "f001", "extension": [ - {"url": "Age", "valueQuantity": {"value": 25, "unit": "years"}}, + {"url": "age", "valueQuantity": {"value": 25, "unit": "years"}}, { "url": "birthSex", "valueCodeableConcept": { diff --git a/tests/test_procedure_resource.py b/tests/test_procedure_resource.py index 92b0b1b..e111203 100644 --- a/tests/test_procedure_resource.py +++ b/tests/test_procedure_resource.py @@ -10,7 +10,7 @@ "instantiatesCanonical": ["http://example.org/fhir/PlanDefinition/KDN5"], "status": "completed", "extension": [ - {"url": "Duration", "valueQuantity": {"value": 1, "unit": "d"}}, + {"url": "duration", "valueQuantity": {"value": 1, "unit": "d"}}, { "url": "timingPhase", "valueCodeableConcept": { @@ -73,8 +73,8 @@ PROCEDURE_FLAT = { "resourceType": "Procedure", - "extension.Duration.value": 1, - "extension.Duration.unit": "d", + "extension.duration.value": 1, + "extension.duration.unit": "d", "extension.timingPhase.code": "timing.com|1234", "extension.timingPhase.text": None, "extension.relativePeriod.relativeStart": 2, @@ -97,7 +97,7 @@ "resourceType": "Procedure", "status": "completed", "extension": [ - {"url": "Duration", "valueQuantity": {"value": 1.0, "unit": "d"}}, + {"url": "duration", "valueQuantity": {"value": 1.0, "unit": "d"}}, { "url": "relativePeriod", "extension": [ diff --git a/tests/test_utils.py b/tests/test_utils.py index d600602..9b65e1a 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -5,7 +5,7 @@ from fhir.resources.codeableconcept import CodeableConcept from fhir.resources.medicationstatement import MedicationStatementAdherence -from fhirflat.resources.extensions import dateTimeExtension +from fhirflat.resources.extensions import dateTimeExtension, Duration def test_group_keys(): @@ -42,6 +42,7 @@ def test_group_keys(): ("CodeableConcept", CodeableConcept), ("MedicationStatementAdherence", MedicationStatementAdherence), ("dateTimeExtension", dateTimeExtension), + ("duration", Duration), ], ) def test_get_fhirtype(input, expected):