compressedfhir 3.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- compressedfhir/__init__.py +0 -0
- compressedfhir/fhir/__init__.py +0 -0
- compressedfhir/fhir/base_resource_list.py +165 -0
- compressedfhir/fhir/fhir_bundle.py +295 -0
- compressedfhir/fhir/fhir_bundle_entry.py +240 -0
- compressedfhir/fhir/fhir_bundle_entry_list.py +97 -0
- compressedfhir/fhir/fhir_bundle_entry_request.py +73 -0
- compressedfhir/fhir/fhir_bundle_entry_response.py +67 -0
- compressedfhir/fhir/fhir_bundle_entry_search.py +75 -0
- compressedfhir/fhir/fhir_identifier.py +84 -0
- compressedfhir/fhir/fhir_link.py +63 -0
- compressedfhir/fhir/fhir_meta.py +47 -0
- compressedfhir/fhir/fhir_resource.py +170 -0
- compressedfhir/fhir/fhir_resource_list.py +149 -0
- compressedfhir/fhir/fhir_resource_map.py +193 -0
- compressedfhir/fhir/test/__init__.py +0 -0
- compressedfhir/fhir/test/test_bundle_entry.py +129 -0
- compressedfhir/fhir/test/test_bundle_entry_list.py +187 -0
- compressedfhir/fhir/test/test_bundle_entry_request.py +74 -0
- compressedfhir/fhir/test/test_bundle_entry_response.py +65 -0
- compressedfhir/fhir/test/test_fhir_bundle.py +245 -0
- compressedfhir/fhir/test/test_fhir_resource.py +104 -0
- compressedfhir/fhir/test/test_fhir_resource_list.py +160 -0
- compressedfhir/fhir/test/test_fhir_resource_map.py +293 -0
- compressedfhir/py.typed +0 -0
- compressedfhir/utilities/__init__.py +0 -0
- compressedfhir/utilities/compressed_dict/__init__.py +0 -0
- compressedfhir/utilities/compressed_dict/v1/__init__.py +0 -0
- compressedfhir/utilities/compressed_dict/v1/compressed_dict.py +701 -0
- compressedfhir/utilities/compressed_dict/v1/compressed_dict_access_error.py +2 -0
- compressedfhir/utilities/compressed_dict/v1/compressed_dict_storage_mode.py +50 -0
- compressedfhir/utilities/compressed_dict/v1/test/__init__.py +0 -0
- compressedfhir/utilities/compressed_dict/v1/test/test_compressed_dict.py +467 -0
- compressedfhir/utilities/fhir_json_encoder.py +71 -0
- compressedfhir/utilities/json_helpers.py +181 -0
- compressedfhir/utilities/json_serializers/__init__.py +0 -0
- compressedfhir/utilities/json_serializers/test/__init__.py +0 -0
- compressedfhir/utilities/json_serializers/test/test_type_preservation_decoder.py +165 -0
- compressedfhir/utilities/json_serializers/test/test_type_preservation_encoder.py +71 -0
- compressedfhir/utilities/json_serializers/test/test_type_preservation_serializer.py +197 -0
- compressedfhir/utilities/json_serializers/type_preservation_decoder.py +135 -0
- compressedfhir/utilities/json_serializers/type_preservation_encoder.py +55 -0
- compressedfhir/utilities/json_serializers/type_preservation_serializer.py +57 -0
- compressedfhir/utilities/ordered_dict_to_dict_converter/__init__.py +0 -0
- compressedfhir/utilities/ordered_dict_to_dict_converter/ordered_dict_to_dict_converter.py +24 -0
- compressedfhir/utilities/string_compressor/__init__.py +0 -0
- compressedfhir/utilities/string_compressor/v1/__init__.py +0 -0
- compressedfhir/utilities/string_compressor/v1/string_compressor.py +99 -0
- compressedfhir/utilities/string_compressor/v1/test/__init__.py +0 -0
- compressedfhir/utilities/string_compressor/v1/test/test_string_compressor.py +189 -0
- compressedfhir/utilities/test/__init__.py +0 -0
- compressedfhir/utilities/test/test_fhir_json_encoder.py +177 -0
- compressedfhir/utilities/test/test_json_helpers.py +99 -0
- compressedfhir-3.0.2.dist-info/METADATA +139 -0
- compressedfhir-3.0.2.dist-info/RECORD +59 -0
- compressedfhir-3.0.2.dist-info/WHEEL +5 -0
- compressedfhir-3.0.2.dist-info/licenses/LICENSE +201 -0
- compressedfhir-3.0.2.dist-info/top_level.txt +2 -0
- tests/__init__.py +0 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
from datetime import datetime, timezone
|
|
2
|
+
|
|
3
|
+
from compressedfhir.fhir.fhir_bundle_entry_request import FhirBundleEntryRequest
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class TestBundleEntryRequest:
|
|
7
|
+
def test_init_default(self) -> None:
|
|
8
|
+
"""Test initialization with default parameters."""
|
|
9
|
+
request = FhirBundleEntryRequest(url="https://example.com")
|
|
10
|
+
assert request.url == "https://example.com"
|
|
11
|
+
assert request.method == "GET"
|
|
12
|
+
assert request.ifModifiedSince is None
|
|
13
|
+
assert request.ifNoneMatch is None
|
|
14
|
+
|
|
15
|
+
def test_init_full(self) -> None:
|
|
16
|
+
"""Test initialization with all parameters."""
|
|
17
|
+
now = datetime.now(timezone.utc)
|
|
18
|
+
request = FhirBundleEntryRequest(
|
|
19
|
+
url="https://example.com",
|
|
20
|
+
method="POST",
|
|
21
|
+
ifModifiedSince=now,
|
|
22
|
+
ifNoneMatch='W/"abc"',
|
|
23
|
+
)
|
|
24
|
+
assert request.url == "https://example.com"
|
|
25
|
+
assert request.method == "POST"
|
|
26
|
+
assert request.ifModifiedSince == now
|
|
27
|
+
assert request.ifNoneMatch == 'W/"abc"'
|
|
28
|
+
|
|
29
|
+
def test_to_dict_minimal(self) -> None:
|
|
30
|
+
"""Test converting to dictionary with minimal parameters."""
|
|
31
|
+
request = FhirBundleEntryRequest(url="https://example.com")
|
|
32
|
+
result = request.dict()
|
|
33
|
+
assert result == {"url": "https://example.com", "method": "GET"}
|
|
34
|
+
|
|
35
|
+
def test_to_dict_full(self) -> None:
|
|
36
|
+
"""Test converting to dictionary with all parameters."""
|
|
37
|
+
now = datetime.now(timezone.utc)
|
|
38
|
+
request = FhirBundleEntryRequest(
|
|
39
|
+
url="https://example.com",
|
|
40
|
+
method="POST",
|
|
41
|
+
ifModifiedSince=now,
|
|
42
|
+
ifNoneMatch='W/"abc"',
|
|
43
|
+
)
|
|
44
|
+
result = request.dict()
|
|
45
|
+
assert result == {
|
|
46
|
+
"url": "https://example.com",
|
|
47
|
+
"method": "POST",
|
|
48
|
+
"ifModifiedSince": now.isoformat(),
|
|
49
|
+
"ifNoneMatch": 'W/"abc"',
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
def test_from_dict_minimal(self) -> None:
|
|
53
|
+
"""Test creating from dictionary with minimal parameters."""
|
|
54
|
+
data = {"url": "https://example.com", "method": "GET"}
|
|
55
|
+
request = FhirBundleEntryRequest.from_dict(data)
|
|
56
|
+
assert request.url == "https://example.com"
|
|
57
|
+
assert request.method == "GET"
|
|
58
|
+
assert request.ifModifiedSince is None
|
|
59
|
+
assert request.ifNoneMatch is None
|
|
60
|
+
|
|
61
|
+
def test_from_dict_full(self) -> None:
|
|
62
|
+
"""Test creating from dictionary with all parameters."""
|
|
63
|
+
now = datetime.now(timezone.utc)
|
|
64
|
+
data = {
|
|
65
|
+
"url": "https://example.com",
|
|
66
|
+
"method": "POST",
|
|
67
|
+
"ifModifiedSince": now.isoformat(),
|
|
68
|
+
"ifNoneMatch": 'W/"abc"',
|
|
69
|
+
}
|
|
70
|
+
request = FhirBundleEntryRequest.from_dict(data)
|
|
71
|
+
assert request.url == "https://example.com"
|
|
72
|
+
assert request.method == "POST"
|
|
73
|
+
assert request.ifModifiedSince == now
|
|
74
|
+
assert request.ifNoneMatch == 'W/"abc"'
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
from datetime import datetime, timezone
|
|
2
|
+
|
|
3
|
+
from compressedfhir.fhir.fhir_bundle_entry_response import (
|
|
4
|
+
FhirBundleEntryResponse,
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestBundleEntryResponse:
|
|
9
|
+
def test_init_default(self) -> None:
|
|
10
|
+
"""Test initialization with default parameters."""
|
|
11
|
+
response = FhirBundleEntryResponse(status="200", etag=None, lastModified=None)
|
|
12
|
+
assert response.status == "200"
|
|
13
|
+
assert response.etag is None
|
|
14
|
+
assert response.lastModified is None
|
|
15
|
+
|
|
16
|
+
def test_init_full(self) -> None:
|
|
17
|
+
"""Test initialization with all parameters."""
|
|
18
|
+
now = datetime.now(timezone.utc)
|
|
19
|
+
response = FhirBundleEntryResponse(
|
|
20
|
+
status="201", etag='W/"def"', lastModified=now
|
|
21
|
+
)
|
|
22
|
+
assert response.status == "201"
|
|
23
|
+
assert response.etag == 'W/"def"'
|
|
24
|
+
assert response.lastModified == now
|
|
25
|
+
|
|
26
|
+
def test_init_int_status(self) -> None:
|
|
27
|
+
"""Test initialization with integer status."""
|
|
28
|
+
response = FhirBundleEntryResponse(status="200", etag=None, lastModified=None)
|
|
29
|
+
assert response.status == "200"
|
|
30
|
+
|
|
31
|
+
def test_to_dict_minimal(self) -> None:
|
|
32
|
+
"""Test converting to dictionary with minimal parameters."""
|
|
33
|
+
response = FhirBundleEntryResponse(status="200", etag=None, lastModified=None)
|
|
34
|
+
result = response.dict()
|
|
35
|
+
assert result == {"status": "200"}
|
|
36
|
+
|
|
37
|
+
def test_to_dict_full(self) -> None:
|
|
38
|
+
"""Test converting to dictionary with all parameters."""
|
|
39
|
+
now = datetime.now(timezone.utc)
|
|
40
|
+
response = FhirBundleEntryResponse(
|
|
41
|
+
status="201", etag='W/"def"', lastModified=now
|
|
42
|
+
)
|
|
43
|
+
result = response.dict()
|
|
44
|
+
assert result == {
|
|
45
|
+
"status": "201",
|
|
46
|
+
"lastModified": now.isoformat(),
|
|
47
|
+
"etag": 'W/"def"',
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
def test_from_dict_minimal(self) -> None:
|
|
51
|
+
"""Test creating from dictionary with minimal parameters."""
|
|
52
|
+
data = {"status": "200"}
|
|
53
|
+
response = FhirBundleEntryResponse.from_dict(data)
|
|
54
|
+
assert response.status == "200"
|
|
55
|
+
assert response.etag is None
|
|
56
|
+
assert response.lastModified is None
|
|
57
|
+
|
|
58
|
+
def test_from_dict_full(self) -> None:
|
|
59
|
+
"""Test creating from dictionary with all parameters."""
|
|
60
|
+
now = datetime.now(timezone.utc)
|
|
61
|
+
data = {"status": "201", "lastModified": now.isoformat(), "etag": 'W/"def"'}
|
|
62
|
+
response = FhirBundleEntryResponse.from_dict(data)
|
|
63
|
+
assert response.status == "201"
|
|
64
|
+
assert response.lastModified == now
|
|
65
|
+
assert response.etag == 'W/"def"'
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
from compressedfhir.fhir.fhir_bundle import FhirBundle
|
|
4
|
+
from compressedfhir.fhir.fhir_bundle_entry import FhirBundleEntry
|
|
5
|
+
from compressedfhir.fhir.fhir_bundle_entry_list import FhirBundleEntryList
|
|
6
|
+
from compressedfhir.fhir.fhir_resource import FhirResource
|
|
7
|
+
from compressedfhir.utilities.compressed_dict.v1.compressed_dict_storage_mode import (
|
|
8
|
+
CompressedDictStorageMode,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class TestBundle:
|
|
13
|
+
def test_init_minimal(self) -> None:
|
|
14
|
+
"""Test initialization with minimal parameters."""
|
|
15
|
+
bundle = FhirBundle(type_="searchset")
|
|
16
|
+
assert bundle.type_ == "searchset"
|
|
17
|
+
assert len(bundle.entry) == 0
|
|
18
|
+
assert bundle.total is None
|
|
19
|
+
assert bundle.id_ is None
|
|
20
|
+
assert bundle.timestamp is None
|
|
21
|
+
|
|
22
|
+
def test_init_full(self) -> None:
|
|
23
|
+
"""Test initialization with all parameters."""
|
|
24
|
+
entries = FhirBundleEntryList(
|
|
25
|
+
[
|
|
26
|
+
FhirBundleEntry(
|
|
27
|
+
resource={"resourceType": "Patient"},
|
|
28
|
+
request=None,
|
|
29
|
+
response=None,
|
|
30
|
+
storage_mode=CompressedDictStorageMode(),
|
|
31
|
+
),
|
|
32
|
+
FhirBundleEntry(
|
|
33
|
+
resource={"resourceType": "Observation"},
|
|
34
|
+
request=None,
|
|
35
|
+
response=None,
|
|
36
|
+
storage_mode=CompressedDictStorageMode(),
|
|
37
|
+
),
|
|
38
|
+
]
|
|
39
|
+
)
|
|
40
|
+
bundle = FhirBundle(
|
|
41
|
+
type_="searchset",
|
|
42
|
+
entry=entries,
|
|
43
|
+
total=2,
|
|
44
|
+
id_="test-bundle",
|
|
45
|
+
timestamp="2023-12-01T12:00:00Z",
|
|
46
|
+
)
|
|
47
|
+
assert bundle.type_ == "searchset"
|
|
48
|
+
assert bundle.entry is not None
|
|
49
|
+
assert len(bundle.entry) == 2
|
|
50
|
+
assert bundle.total == 2
|
|
51
|
+
assert bundle.id_ == "test-bundle"
|
|
52
|
+
assert bundle.timestamp == "2023-12-01T12:00:00Z"
|
|
53
|
+
|
|
54
|
+
def test_to_dict_minimal(self) -> None:
|
|
55
|
+
"""Test converting to dictionary with minimal parameters."""
|
|
56
|
+
bundle = FhirBundle(type_="searchset")
|
|
57
|
+
result = bundle.dict()
|
|
58
|
+
assert result == {"type": "searchset", "resourceType": "Bundle"}
|
|
59
|
+
|
|
60
|
+
def test_to_dict_full(self) -> None:
|
|
61
|
+
"""Test converting to dictionary with all parameters."""
|
|
62
|
+
entries = FhirBundleEntryList(
|
|
63
|
+
[
|
|
64
|
+
FhirBundleEntry(
|
|
65
|
+
resource={"resourceType": "Patient"},
|
|
66
|
+
request=None,
|
|
67
|
+
response=None,
|
|
68
|
+
storage_mode=CompressedDictStorageMode(),
|
|
69
|
+
),
|
|
70
|
+
FhirBundleEntry(
|
|
71
|
+
resource={"resourceType": "Observation"},
|
|
72
|
+
request=None,
|
|
73
|
+
response=None,
|
|
74
|
+
storage_mode=CompressedDictStorageMode(),
|
|
75
|
+
),
|
|
76
|
+
]
|
|
77
|
+
)
|
|
78
|
+
bundle = FhirBundle(
|
|
79
|
+
type_="searchset",
|
|
80
|
+
entry=entries,
|
|
81
|
+
total=2,
|
|
82
|
+
id_="test-bundle",
|
|
83
|
+
timestamp="2023-12-01T12:00:00Z",
|
|
84
|
+
)
|
|
85
|
+
result = bundle.dict()
|
|
86
|
+
assert result == {
|
|
87
|
+
"type": "searchset",
|
|
88
|
+
"resourceType": "Bundle",
|
|
89
|
+
"id": "test-bundle",
|
|
90
|
+
"timestamp": "2023-12-01T12:00:00Z",
|
|
91
|
+
"total": 2,
|
|
92
|
+
"entry": [
|
|
93
|
+
{"resource": {"resourceType": "Patient"}},
|
|
94
|
+
{"resource": {"resourceType": "Observation"}},
|
|
95
|
+
],
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
def test_to_json(self) -> None:
|
|
99
|
+
"""Test converting Bundle to JSON."""
|
|
100
|
+
entries = FhirBundleEntryList(
|
|
101
|
+
[
|
|
102
|
+
FhirBundleEntry(
|
|
103
|
+
resource={"resourceType": "Patient"},
|
|
104
|
+
request=None,
|
|
105
|
+
response=None,
|
|
106
|
+
storage_mode=CompressedDictStorageMode(),
|
|
107
|
+
),
|
|
108
|
+
FhirBundleEntry(
|
|
109
|
+
resource={"resourceType": "Observation"},
|
|
110
|
+
request=None,
|
|
111
|
+
response=None,
|
|
112
|
+
storage_mode=CompressedDictStorageMode(),
|
|
113
|
+
),
|
|
114
|
+
]
|
|
115
|
+
)
|
|
116
|
+
bundle = FhirBundle(
|
|
117
|
+
type_="searchset",
|
|
118
|
+
entry=entries,
|
|
119
|
+
total=2,
|
|
120
|
+
id_="test-bundle",
|
|
121
|
+
timestamp="2023-12-01T12:00:00Z",
|
|
122
|
+
)
|
|
123
|
+
json_str = bundle.json()
|
|
124
|
+
parsed_json = json.loads(json_str)
|
|
125
|
+
assert parsed_json["type"] == "searchset"
|
|
126
|
+
assert parsed_json["resourceType"] == "Bundle"
|
|
127
|
+
|
|
128
|
+
def test_add_diagnostics_to_operation_outcomes(self) -> None:
|
|
129
|
+
"""Test adding diagnostics to OperationOutcome resources."""
|
|
130
|
+
resource = FhirResource(
|
|
131
|
+
initial_dict={
|
|
132
|
+
"resourceType": "OperationOutcome",
|
|
133
|
+
"issue": [{"severity": "error", "details": {}}],
|
|
134
|
+
},
|
|
135
|
+
storage_mode=CompressedDictStorageMode(),
|
|
136
|
+
)
|
|
137
|
+
diagnostics_coding = [{"code": "test-code"}]
|
|
138
|
+
|
|
139
|
+
updated_resource = FhirBundle.add_diagnostics_to_operation_outcomes(
|
|
140
|
+
resource=resource, diagnostics_coding=diagnostics_coding
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
with updated_resource.transaction():
|
|
144
|
+
assert (
|
|
145
|
+
updated_resource["issue"][0]["details"]["coding"] == diagnostics_coding
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
class TestFhirBundleCopy:
|
|
150
|
+
def test_copy_full_bundle(self) -> None:
|
|
151
|
+
"""
|
|
152
|
+
Test copying a fully populated FhirBundle
|
|
153
|
+
"""
|
|
154
|
+
# Create a mock FhirBundleEntryList
|
|
155
|
+
mock_entry_list = FhirBundleEntryList()
|
|
156
|
+
mock_resource = FhirBundleEntry(
|
|
157
|
+
resource=FhirResource({"resourceType": "Patient", "id": "123"})
|
|
158
|
+
)
|
|
159
|
+
mock_entry_list.append(mock_resource)
|
|
160
|
+
|
|
161
|
+
# Create original bundle
|
|
162
|
+
original_bundle = FhirBundle(
|
|
163
|
+
id_="test-bundle-id",
|
|
164
|
+
timestamp="2023-01-01T00:00:00Z",
|
|
165
|
+
type_="transaction",
|
|
166
|
+
entry=mock_entry_list,
|
|
167
|
+
total=1,
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
# Create a copy
|
|
171
|
+
copied_bundle = original_bundle.copy()
|
|
172
|
+
|
|
173
|
+
# Assert that the copied bundle has the same attributes
|
|
174
|
+
assert copied_bundle.id_ == original_bundle.id_
|
|
175
|
+
assert copied_bundle.timestamp == original_bundle.timestamp
|
|
176
|
+
assert copied_bundle.type_ == original_bundle.type_
|
|
177
|
+
assert copied_bundle.total == original_bundle.total
|
|
178
|
+
|
|
179
|
+
# Ensure the entry list is a copy, not the same object
|
|
180
|
+
assert copied_bundle.entry is not original_bundle.entry
|
|
181
|
+
assert copied_bundle.entry is not None
|
|
182
|
+
assert original_bundle.entry is not None
|
|
183
|
+
assert len(copied_bundle.entry) == len(original_bundle.entry)
|
|
184
|
+
assert copied_bundle.entry[0].dict() == original_bundle.entry[0].dict()
|
|
185
|
+
|
|
186
|
+
def test_copy_empty_bundle(self) -> None:
|
|
187
|
+
"""
|
|
188
|
+
Test copying a bundle with no entries
|
|
189
|
+
"""
|
|
190
|
+
# Create an empty bundle
|
|
191
|
+
original_bundle = FhirBundle(type_="batch", entry=None, total=None)
|
|
192
|
+
|
|
193
|
+
# Create a copy
|
|
194
|
+
copied_bundle = original_bundle.copy()
|
|
195
|
+
|
|
196
|
+
# Assert that the copied bundle has the same attributes
|
|
197
|
+
assert copied_bundle.id_ is None
|
|
198
|
+
assert copied_bundle.timestamp is None
|
|
199
|
+
assert copied_bundle.type_ == "batch"
|
|
200
|
+
assert copied_bundle.total is None
|
|
201
|
+
assert len(copied_bundle.entry) == 0
|
|
202
|
+
|
|
203
|
+
def test_copy_modifying_original_does_not_affect_copy(self) -> None:
|
|
204
|
+
"""
|
|
205
|
+
Test that modifying the original bundle does not affect the copy
|
|
206
|
+
"""
|
|
207
|
+
# Create a mock FhirBundleEntryList
|
|
208
|
+
mock_entry_list = FhirBundleEntryList()
|
|
209
|
+
mock_resource = FhirResource({"resourceType": "Patient", "id": "123"})
|
|
210
|
+
mock_entry_list.append(FhirBundleEntry(resource=mock_resource))
|
|
211
|
+
|
|
212
|
+
# Create original bundle
|
|
213
|
+
original_bundle = FhirBundle(
|
|
214
|
+
id_="test-bundle-id",
|
|
215
|
+
timestamp="2023-01-01T00:00:00Z",
|
|
216
|
+
type_="transaction",
|
|
217
|
+
entry=mock_entry_list,
|
|
218
|
+
total=1,
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
# Create a copy
|
|
222
|
+
copied_bundle = original_bundle.copy()
|
|
223
|
+
|
|
224
|
+
# Modify the original bundle
|
|
225
|
+
original_bundle.id_ = "modified-id"
|
|
226
|
+
original_bundle.timestamp = "2023-02-01T00:00:00Z"
|
|
227
|
+
original_bundle.total = 2
|
|
228
|
+
|
|
229
|
+
# Assert that the copied bundle remains unchanged
|
|
230
|
+
assert copied_bundle.id_ == "test-bundle-id"
|
|
231
|
+
assert copied_bundle.timestamp == "2023-01-01T00:00:00Z"
|
|
232
|
+
assert copied_bundle.total == 1
|
|
233
|
+
|
|
234
|
+
def test_copy_returns_new_instance(self) -> None:
|
|
235
|
+
"""
|
|
236
|
+
Test that copy() returns a new FhirBundle instance
|
|
237
|
+
"""
|
|
238
|
+
# Create a bundle
|
|
239
|
+
original_bundle = FhirBundle(type_="batch")
|
|
240
|
+
|
|
241
|
+
# Create a copy
|
|
242
|
+
copied_bundle = original_bundle.copy()
|
|
243
|
+
|
|
244
|
+
# Assert that it's a different object
|
|
245
|
+
assert copied_bundle is not original_bundle
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from typing import Dict, Any
|
|
3
|
+
|
|
4
|
+
from compressedfhir.fhir.fhir_resource import FhirResource
|
|
5
|
+
from compressedfhir.utilities.compressed_dict.v1.compressed_dict_storage_mode import (
|
|
6
|
+
CompressedDictStorageMode,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class TestFhirResource:
|
|
11
|
+
def test_init_empty(self) -> None:
|
|
12
|
+
"""Test initializing FhirResource with no initial dictionary."""
|
|
13
|
+
resource = FhirResource(storage_mode=CompressedDictStorageMode())
|
|
14
|
+
assert len(resource) == 0
|
|
15
|
+
assert resource.resource_type is None
|
|
16
|
+
assert resource.id is None
|
|
17
|
+
assert resource.resource_type_and_id is None
|
|
18
|
+
|
|
19
|
+
def test_init_with_data(self) -> None:
|
|
20
|
+
"""Test initializing FhirResource with a dictionary."""
|
|
21
|
+
initial_data: Dict[str, Any] = {
|
|
22
|
+
"resourceType": "Patient",
|
|
23
|
+
"id": "123",
|
|
24
|
+
"name": [{"given": ["John"]}],
|
|
25
|
+
}
|
|
26
|
+
resource = FhirResource(
|
|
27
|
+
initial_dict=initial_data, storage_mode=CompressedDictStorageMode()
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
with resource.transaction():
|
|
31
|
+
assert resource.resource_type == "Patient"
|
|
32
|
+
assert resource.id == "123"
|
|
33
|
+
assert resource.resource_type_and_id == "Patient/123"
|
|
34
|
+
assert resource["name"][0]["given"][0] == "John"
|
|
35
|
+
|
|
36
|
+
def test_resource_type_and_id_property(self) -> None:
|
|
37
|
+
"""Test resource_type_and_id property with various scenarios."""
|
|
38
|
+
# Scenario 1: Both resource type and id present
|
|
39
|
+
resource1 = FhirResource(
|
|
40
|
+
initial_dict={"resourceType": "Observation", "id": "456"},
|
|
41
|
+
storage_mode=CompressedDictStorageMode(),
|
|
42
|
+
)
|
|
43
|
+
assert resource1.resource_type_and_id == "Observation/456"
|
|
44
|
+
|
|
45
|
+
# Scenario 2: Missing resource type
|
|
46
|
+
resource2 = FhirResource(
|
|
47
|
+
initial_dict={"id": "789"}, storage_mode=CompressedDictStorageMode()
|
|
48
|
+
)
|
|
49
|
+
assert resource2.resource_type_and_id is None
|
|
50
|
+
|
|
51
|
+
# Scenario 3: Missing id
|
|
52
|
+
resource3 = FhirResource(
|
|
53
|
+
initial_dict={"resourceType": "Patient"},
|
|
54
|
+
storage_mode=CompressedDictStorageMode(),
|
|
55
|
+
)
|
|
56
|
+
assert resource3.resource_type_and_id is None
|
|
57
|
+
|
|
58
|
+
def test_equality(self) -> None:
|
|
59
|
+
"""Test equality comparison between FhirResource instances."""
|
|
60
|
+
# Scenario 1: Equal resources
|
|
61
|
+
resource1 = FhirResource(
|
|
62
|
+
initial_dict={"resourceType": "Patient", "id": "123"},
|
|
63
|
+
storage_mode=CompressedDictStorageMode(),
|
|
64
|
+
)
|
|
65
|
+
resource2 = FhirResource(
|
|
66
|
+
initial_dict={"resourceType": "Patient", "id": "123"},
|
|
67
|
+
storage_mode=CompressedDictStorageMode(),
|
|
68
|
+
)
|
|
69
|
+
assert resource1 == resource2
|
|
70
|
+
|
|
71
|
+
# Scenario 2: Different resource types
|
|
72
|
+
resource3 = FhirResource(
|
|
73
|
+
initial_dict={"resourceType": "Observation", "id": "123"},
|
|
74
|
+
storage_mode=CompressedDictStorageMode(),
|
|
75
|
+
)
|
|
76
|
+
assert resource1 != resource3
|
|
77
|
+
|
|
78
|
+
# Scenario 3: Different ids
|
|
79
|
+
resource4 = FhirResource(
|
|
80
|
+
initial_dict={"resourceType": "Patient", "id": "456"},
|
|
81
|
+
storage_mode=CompressedDictStorageMode(),
|
|
82
|
+
)
|
|
83
|
+
assert resource1 != resource4
|
|
84
|
+
|
|
85
|
+
# Scenario 4: Comparing with non-FhirResource
|
|
86
|
+
assert resource1 != "Not a FhirResource"
|
|
87
|
+
|
|
88
|
+
def test_to_json(self) -> None:
|
|
89
|
+
"""Test JSON serialization of FhirResource."""
|
|
90
|
+
initial_data: Dict[str, Any] = {
|
|
91
|
+
"resourceType": "Patient",
|
|
92
|
+
"id": "123",
|
|
93
|
+
"name": [{"given": ["John"]}],
|
|
94
|
+
}
|
|
95
|
+
resource = FhirResource(
|
|
96
|
+
initial_dict=initial_data, storage_mode=CompressedDictStorageMode()
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
json_str = resource.json()
|
|
100
|
+
parsed_json = json.loads(json_str)
|
|
101
|
+
|
|
102
|
+
assert parsed_json == initial_data
|
|
103
|
+
assert "resourceType" in parsed_json
|
|
104
|
+
assert "id" in parsed_json
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from unittest.mock import Mock
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from compressedfhir.fhir.fhir_resource_list import FhirResourceList
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class TestFhirResourceList:
|
|
10
|
+
def test_get_resource_type_and_ids(self) -> None:
|
|
11
|
+
# Create mock FhirResource objects
|
|
12
|
+
mock_resources = [
|
|
13
|
+
Mock(resource_type="Patient", id="123"),
|
|
14
|
+
Mock(resource_type="Observation", id="456"),
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
resource_list = FhirResourceList(mock_resources)
|
|
18
|
+
|
|
19
|
+
# Check the returned resource type and ids
|
|
20
|
+
expected_result = ["Patient/123", "Observation/456"]
|
|
21
|
+
assert resource_list.get_resource_type_and_ids() == expected_result
|
|
22
|
+
|
|
23
|
+
def test_get_operation_outcomes(self) -> None:
|
|
24
|
+
# Create mock FhirResource objects with different resource types
|
|
25
|
+
mock_resources = [
|
|
26
|
+
Mock(resource_type="OperationOutcome", id="err1"),
|
|
27
|
+
Mock(resource_type="Patient", id="123"),
|
|
28
|
+
Mock(resource_type="OperationOutcome", id="err2"),
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
resource_list = FhirResourceList(mock_resources)
|
|
32
|
+
|
|
33
|
+
# Get operation outcomes
|
|
34
|
+
operation_outcomes = resource_list.get_operation_outcomes()
|
|
35
|
+
|
|
36
|
+
# Check the result
|
|
37
|
+
assert len(operation_outcomes) == 2
|
|
38
|
+
assert all(r.resource_type == "OperationOutcome" for r in operation_outcomes)
|
|
39
|
+
|
|
40
|
+
def test_get_resources_except_operation_outcomes(self) -> None:
|
|
41
|
+
# Create mock FhirResource objects with different resource types
|
|
42
|
+
mock_resources = [
|
|
43
|
+
Mock(resource_type="OperationOutcome", id="err1"),
|
|
44
|
+
Mock(resource_type="Patient", id="123"),
|
|
45
|
+
Mock(resource_type="Observation", id="456"),
|
|
46
|
+
Mock(resource_type="OperationOutcome", id="err2"),
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
resource_list = FhirResourceList(mock_resources)
|
|
50
|
+
|
|
51
|
+
# Get resources except operation outcomes
|
|
52
|
+
valid_resources = resource_list.get_resources_except_operation_outcomes()
|
|
53
|
+
|
|
54
|
+
# Check the result
|
|
55
|
+
assert len(valid_resources) == 2
|
|
56
|
+
assert all(r.resource_type != "OperationOutcome" for r in valid_resources)
|
|
57
|
+
|
|
58
|
+
def test_remove_duplicates(self) -> None:
|
|
59
|
+
# Create mock FhirResource objects with duplicates
|
|
60
|
+
mock_resources = [
|
|
61
|
+
Mock(resource_type="Patient", id="123", resource_type_and_id="Patient/123"),
|
|
62
|
+
Mock(resource_type="Patient", id="123", resource_type_and_id="Patient/123"),
|
|
63
|
+
Mock(
|
|
64
|
+
resource_type="Observation",
|
|
65
|
+
id="456",
|
|
66
|
+
resource_type_and_id="Observation/456",
|
|
67
|
+
),
|
|
68
|
+
Mock(resource_type="Patient", id="789", resource_type_and_id="Patient/789"),
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
resource_list = FhirResourceList(mock_resources)
|
|
72
|
+
|
|
73
|
+
# Remove duplicates
|
|
74
|
+
resource_list.remove_duplicates()
|
|
75
|
+
|
|
76
|
+
# Check the result
|
|
77
|
+
assert len(resource_list) == 3
|
|
78
|
+
assert len(set(r.resource_type_and_id for r in resource_list)) == 3
|
|
79
|
+
|
|
80
|
+
def test_to_json(self) -> None:
|
|
81
|
+
# Create mock FhirResource objects
|
|
82
|
+
mock_resources = [
|
|
83
|
+
Mock(
|
|
84
|
+
resource_type="Patient",
|
|
85
|
+
id="123",
|
|
86
|
+
dict=lambda: {"id": "123", "resourceType": "Patient"},
|
|
87
|
+
),
|
|
88
|
+
Mock(
|
|
89
|
+
resource_type="Observation",
|
|
90
|
+
id="456",
|
|
91
|
+
dict=lambda: {"id": "456", "resourceType": "Observation"},
|
|
92
|
+
),
|
|
93
|
+
]
|
|
94
|
+
|
|
95
|
+
resource_list = FhirResourceList(mock_resources)
|
|
96
|
+
|
|
97
|
+
# Convert to JSON
|
|
98
|
+
json_str = resource_list.json()
|
|
99
|
+
|
|
100
|
+
# Parse and check the JSON
|
|
101
|
+
parsed_json = json.loads(json_str)
|
|
102
|
+
assert len(parsed_json) == 2
|
|
103
|
+
assert parsed_json[0]["resourceType"] == "Patient"
|
|
104
|
+
assert parsed_json[1]["resourceType"] == "Observation"
|
|
105
|
+
|
|
106
|
+
@pytest.mark.asyncio
|
|
107
|
+
async def test_consume_resource_async_default(self) -> None:
|
|
108
|
+
# Create mock FhirResource objects
|
|
109
|
+
mock_resources = [
|
|
110
|
+
Mock(resource_type="Patient", id="123"),
|
|
111
|
+
Mock(resource_type="Observation", id="456"),
|
|
112
|
+
]
|
|
113
|
+
|
|
114
|
+
resource_list = FhirResourceList(mock_resources)
|
|
115
|
+
|
|
116
|
+
# Consume resources asynchronously with default (None) batch size
|
|
117
|
+
async for batch in resource_list.consume_resource_batch_async(batch_size=None):
|
|
118
|
+
assert len(batch) == 2
|
|
119
|
+
|
|
120
|
+
# Ensure all resources are consumed
|
|
121
|
+
assert len(resource_list) == 0
|
|
122
|
+
|
|
123
|
+
@pytest.mark.asyncio
|
|
124
|
+
async def test_consume_resource_async_with_batch_size(self) -> None:
|
|
125
|
+
# Create mock FhirResource objects
|
|
126
|
+
mock_resources = [
|
|
127
|
+
Mock(resource_type="Patient", id="123"),
|
|
128
|
+
Mock(resource_type="Observation", id="456"),
|
|
129
|
+
Mock(resource_type="Condition", id="789"),
|
|
130
|
+
]
|
|
131
|
+
|
|
132
|
+
resource_list = FhirResourceList(mock_resources)
|
|
133
|
+
|
|
134
|
+
# Consume resources asynchronously with batch size of 2
|
|
135
|
+
batches = []
|
|
136
|
+
async for batch in resource_list.consume_resource_batch_async(batch_size=2):
|
|
137
|
+
batches.append(batch)
|
|
138
|
+
|
|
139
|
+
# Check batches
|
|
140
|
+
assert len(batches) == 2
|
|
141
|
+
assert len(batches[0]) == 2
|
|
142
|
+
assert len(batches[1]) == 1
|
|
143
|
+
|
|
144
|
+
# Ensure all resources are consumed
|
|
145
|
+
assert len(resource_list) == 0
|
|
146
|
+
|
|
147
|
+
def test_consume_resource_async_invalid_batch_size(self) -> None:
|
|
148
|
+
resource_list = FhirResourceList()
|
|
149
|
+
|
|
150
|
+
# Test invalid batch sizes
|
|
151
|
+
with pytest.raises(ValueError, match="Batch size must be greater than 0."):
|
|
152
|
+
|
|
153
|
+
async def test() -> None:
|
|
154
|
+
async for _ in resource_list.consume_resource_batch_async(batch_size=0):
|
|
155
|
+
pass
|
|
156
|
+
|
|
157
|
+
# Run the async function
|
|
158
|
+
import asyncio
|
|
159
|
+
|
|
160
|
+
asyncio.run(test())
|