compressedfhir 0.0.1__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.
Potentially problematic release.
This version of compressedfhir might be problematic. Click here for more details.
- compressedfhir/__init__.py +0 -0
- compressedfhir/fhir/__init__.py +0 -0
- compressedfhir/fhir/base_resource_list.py +165 -0
- compressedfhir/fhir/fhir_bundle.py +291 -0
- compressedfhir/fhir/fhir_bundle_entry.py +234 -0
- compressedfhir/fhir/fhir_bundle_entry_list.py +82 -0
- compressedfhir/fhir/fhir_bundle_entry_request.py +71 -0
- compressedfhir/fhir/fhir_bundle_entry_response.py +64 -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 +163 -0
- compressedfhir/fhir/fhir_resource_list.py +143 -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 +225 -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 +635 -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 +360 -0
- compressedfhir/utilities/fhir_json_encoder.py +30 -0
- compressedfhir/utilities/json_helpers.py +181 -0
- compressedfhir-0.0.1.dist-info/METADATA +28 -0
- compressedfhir-0.0.1.dist-info/RECORD +41 -0
- compressedfhir-0.0.1.dist-info/WHEEL +5 -0
- compressedfhir-0.0.1.dist-info/licenses/LICENSE +201 -0
- compressedfhir-0.0.1.dist-info/top_level.txt +2 -0
- tests/__init__.py +0 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import copy
|
|
2
|
+
from typing import Deque, Optional, AsyncGenerator, List, Any, Dict, override, Iterable
|
|
3
|
+
|
|
4
|
+
from compressedfhir.fhir.fhir_bundle_entry import FhirBundleEntry
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class FhirBundleEntryList(Deque[FhirBundleEntry]):
|
|
8
|
+
"""
|
|
9
|
+
Represents a list of FHIR Bundle entries.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
__slots__: List[str] = []
|
|
13
|
+
|
|
14
|
+
async def consume_resource_async(
|
|
15
|
+
self,
|
|
16
|
+
*,
|
|
17
|
+
batch_size: Optional[int],
|
|
18
|
+
) -> AsyncGenerator["FhirBundleEntryList", None]:
|
|
19
|
+
"""
|
|
20
|
+
Consume bundle entries in batches asynchronously.
|
|
21
|
+
|
|
22
|
+
:param batch_size: The size of each batch.
|
|
23
|
+
:return: An async generator yielding batches of FhirResourceList.
|
|
24
|
+
"""
|
|
25
|
+
if batch_size is None:
|
|
26
|
+
while self:
|
|
27
|
+
yield FhirBundleEntryList([self.popleft()])
|
|
28
|
+
elif batch_size <= 0:
|
|
29
|
+
raise ValueError("Batch size must be greater than 0.")
|
|
30
|
+
else:
|
|
31
|
+
while self:
|
|
32
|
+
batch = FhirBundleEntryList()
|
|
33
|
+
for _ in range(min(batch_size, len(self))):
|
|
34
|
+
batch.append(self.popleft())
|
|
35
|
+
yield batch
|
|
36
|
+
|
|
37
|
+
def __deepcopy__(self, memo: Dict[int, Any]) -> "FhirBundleEntryList":
|
|
38
|
+
"""
|
|
39
|
+
Create a shallow copy of the FhirBundleEntryList.
|
|
40
|
+
|
|
41
|
+
:return: A new FhirBundleEntryList instance with the same entries.
|
|
42
|
+
"""
|
|
43
|
+
return FhirBundleEntryList([copy.deepcopy(entry) for entry in self])
|
|
44
|
+
|
|
45
|
+
def __repr__(self) -> str:
|
|
46
|
+
"""
|
|
47
|
+
Return a string representation of the FhirBundleEntryList.
|
|
48
|
+
|
|
49
|
+
:return: A string representation of the FhirBundleEntryList.
|
|
50
|
+
"""
|
|
51
|
+
return f"FhirBundleEntryList(entries: {len(self)})"
|
|
52
|
+
|
|
53
|
+
@override
|
|
54
|
+
def append(self, x: FhirBundleEntry, /) -> None:
|
|
55
|
+
"""
|
|
56
|
+
Append an entry to the FhirBundleEntryList.
|
|
57
|
+
|
|
58
|
+
:param x: The entry to append.
|
|
59
|
+
"""
|
|
60
|
+
if not isinstance(x, FhirBundleEntry):
|
|
61
|
+
raise TypeError("Only FhirBundleEntry instances can be appended.")
|
|
62
|
+
|
|
63
|
+
# check that we don't have a duplicate entry
|
|
64
|
+
key: Optional[str] = x.resource_type_and_id
|
|
65
|
+
if key is None:
|
|
66
|
+
super().append(x)
|
|
67
|
+
else:
|
|
68
|
+
for entry in self:
|
|
69
|
+
if entry.resource_type_and_id == key:
|
|
70
|
+
# we have a duplicate entry
|
|
71
|
+
return
|
|
72
|
+
super().append(x)
|
|
73
|
+
|
|
74
|
+
@override
|
|
75
|
+
def extend(self, iterable: Iterable[FhirBundleEntry], /) -> None:
|
|
76
|
+
"""
|
|
77
|
+
Extend the FhirBundleEntryList with entries from an iterable.
|
|
78
|
+
|
|
79
|
+
:param iterable: The iterable containing entries to extend.
|
|
80
|
+
"""
|
|
81
|
+
for entry in iterable:
|
|
82
|
+
self.append(entry)
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from typing import Any, Dict, Optional, OrderedDict
|
|
3
|
+
|
|
4
|
+
from compressedfhir.utilities.json_helpers import FhirClientJsonHelpers
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class FhirBundleEntryRequest:
|
|
8
|
+
"""
|
|
9
|
+
FHIR Bundle Entry Request class for encapsulating the request to be sent to FHIR server
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
__slots__ = ["url", "method", "ifModifiedSince", "ifNoneMatch", "ifNoneExist"]
|
|
13
|
+
|
|
14
|
+
# noinspection PyPep8Naming
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
*,
|
|
18
|
+
url: str,
|
|
19
|
+
method: str = "GET",
|
|
20
|
+
ifNoneMatch: Optional[str] = None,
|
|
21
|
+
ifModifiedSince: Optional[datetime] = None,
|
|
22
|
+
ifNoneExist: Optional[str] = None,
|
|
23
|
+
) -> None:
|
|
24
|
+
self.url: str = url or "https://example.com"
|
|
25
|
+
self.method: str = method or "GET"
|
|
26
|
+
self.ifModifiedSince: Optional[datetime] = ifModifiedSince
|
|
27
|
+
self.ifNoneMatch: Optional[str] = ifNoneMatch
|
|
28
|
+
self.ifNoneExist: Optional[str] = ifNoneExist
|
|
29
|
+
|
|
30
|
+
def dict(self) -> OrderedDict[str, Any]:
|
|
31
|
+
result: OrderedDict[str, Any] = OrderedDict[str, Any](
|
|
32
|
+
{"url": self.url, "method": self.method}
|
|
33
|
+
)
|
|
34
|
+
if self.ifModifiedSince is not None:
|
|
35
|
+
result["ifModifiedSince"] = self.ifModifiedSince.isoformat()
|
|
36
|
+
if self.ifNoneMatch is not None:
|
|
37
|
+
result["ifNoneMatch"] = self.ifNoneMatch
|
|
38
|
+
if self.ifNoneExist is not None:
|
|
39
|
+
result["ifNoneExist"] = self.ifNoneExist
|
|
40
|
+
return FhirClientJsonHelpers.remove_empty_elements_from_ordered_dict(result)
|
|
41
|
+
|
|
42
|
+
@classmethod
|
|
43
|
+
def from_dict(
|
|
44
|
+
cls, d: Dict[str, Any] | OrderedDict[str, Any]
|
|
45
|
+
) -> "FhirBundleEntryRequest":
|
|
46
|
+
return cls(
|
|
47
|
+
url=d.get("url", "https://example.com"),
|
|
48
|
+
method=d.get("method", "GET"),
|
|
49
|
+
ifModifiedSince=(
|
|
50
|
+
datetime.fromisoformat(d["ifModifiedSince"])
|
|
51
|
+
if "ifModifiedSince" in d
|
|
52
|
+
else None
|
|
53
|
+
),
|
|
54
|
+
ifNoneMatch=d["ifNoneMatch"] if "ifNoneMatch" in d else None,
|
|
55
|
+
ifNoneExist=d["ifNoneExist"] if "ifNoneExist" in d else None,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
def __deepcopy__(self, memo: Dict[int, Any]) -> "FhirBundleEntryRequest":
|
|
59
|
+
return FhirBundleEntryRequest(
|
|
60
|
+
url=self.url,
|
|
61
|
+
method=self.method,
|
|
62
|
+
ifModifiedSince=self.ifModifiedSince,
|
|
63
|
+
ifNoneMatch=self.ifNoneMatch,
|
|
64
|
+
ifNoneExist=self.ifNoneExist,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
def __repr__(self) -> str:
|
|
68
|
+
return (
|
|
69
|
+
f"FhirBundleEntryRequest(url={self.url}, method={self.method}, "
|
|
70
|
+
f"ifModifiedSince={self.ifModifiedSince}, ifNoneMatch={self.ifNoneMatch})"
|
|
71
|
+
)
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from typing import Any, Dict, Optional, OrderedDict
|
|
3
|
+
|
|
4
|
+
from compressedfhir.utilities.json_helpers import FhirClientJsonHelpers
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class FhirBundleEntryResponse:
|
|
8
|
+
"""
|
|
9
|
+
FHIR Bundle Entry Response class for encapsulating the response from FHIR server when processing bundle entries
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
__slots__ = ["status", "lastModified", "etag", "location"]
|
|
13
|
+
|
|
14
|
+
# noinspection PyPep8Naming
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
*,
|
|
18
|
+
status: str = "200",
|
|
19
|
+
etag: Optional[str] = None,
|
|
20
|
+
lastModified: Optional[datetime] = None,
|
|
21
|
+
location: Optional[str] = None,
|
|
22
|
+
) -> None:
|
|
23
|
+
self.status: str = status or "200"
|
|
24
|
+
if isinstance(status, int):
|
|
25
|
+
self.status = str(status)
|
|
26
|
+
self.lastModified: Optional[datetime] = lastModified
|
|
27
|
+
self.etag: Optional[str] = etag
|
|
28
|
+
self.location: Optional[str] = location
|
|
29
|
+
|
|
30
|
+
def dict(self) -> OrderedDict[str, Any]:
|
|
31
|
+
result: OrderedDict[str, Any] = OrderedDict[str, Any]({"status": self.status})
|
|
32
|
+
if self.lastModified is not None:
|
|
33
|
+
result["lastModified"] = self.lastModified.isoformat()
|
|
34
|
+
if self.etag is not None:
|
|
35
|
+
result["etag"] = self.etag
|
|
36
|
+
if self.location is not None:
|
|
37
|
+
result["location"] = self.location
|
|
38
|
+
return FhirClientJsonHelpers.remove_empty_elements_from_ordered_dict(result)
|
|
39
|
+
|
|
40
|
+
@classmethod
|
|
41
|
+
def from_dict(
|
|
42
|
+
cls, d: Dict[str, Any] | OrderedDict[str, Any]
|
|
43
|
+
) -> "FhirBundleEntryResponse":
|
|
44
|
+
return cls(
|
|
45
|
+
status=d["status"] if "status" in d else "200",
|
|
46
|
+
lastModified=(
|
|
47
|
+
datetime.fromisoformat(d["lastModified"])
|
|
48
|
+
if "lastModified" in d
|
|
49
|
+
else None
|
|
50
|
+
),
|
|
51
|
+
etag=d["etag"] if "etag" in d else None,
|
|
52
|
+
location=d["location"] if "location" in d else None,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
def __deepcopy__(self, memo: Dict[int, Any]) -> "FhirBundleEntryResponse":
|
|
56
|
+
return FhirBundleEntryResponse(
|
|
57
|
+
status=self.status,
|
|
58
|
+
lastModified=self.lastModified,
|
|
59
|
+
etag=self.etag,
|
|
60
|
+
location=self.location,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
def __repr__(self) -> str:
|
|
64
|
+
return f"FhirBundleEntryResponse(status: {self.status}, lastModified: {self.lastModified}, etag: {self.etag})"
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from typing import Optional, Dict, Any, OrderedDict
|
|
3
|
+
|
|
4
|
+
from compressedfhir.utilities.fhir_json_encoder import FhirJSONEncoder
|
|
5
|
+
from compressedfhir.utilities.json_helpers import FhirClientJsonHelpers
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class FhirBundleEntrySearch:
|
|
9
|
+
"""
|
|
10
|
+
FhirBundleEntrySearch is a class that represents a search entry in a FHIR Bundle.
|
|
11
|
+
It contains the resource, search mode, and search parameters.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
__slots__ = ["mode", "score"]
|
|
15
|
+
|
|
16
|
+
def __init__(self, *, mode: Optional[str], score: Optional[float]) -> None:
|
|
17
|
+
"""
|
|
18
|
+
Initializes the FhirBundleEntrySearch with the given parameters.
|
|
19
|
+
|
|
20
|
+
"""
|
|
21
|
+
self.mode: Optional[str] = mode
|
|
22
|
+
self.score: Optional[float] = score
|
|
23
|
+
|
|
24
|
+
def dict(self) -> OrderedDict[str, Any]:
|
|
25
|
+
"""
|
|
26
|
+
Converts the FhirBundleEntrySearch instance to a dictionary.
|
|
27
|
+
|
|
28
|
+
:return: A dictionary representation of the FhirBundleEntrySearch instance.
|
|
29
|
+
"""
|
|
30
|
+
result: OrderedDict[str, Any] = OrderedDict[str, Any]()
|
|
31
|
+
if self.mode is not None:
|
|
32
|
+
result["mode"] = self.mode
|
|
33
|
+
if self.score is not None:
|
|
34
|
+
result["score"] = self.score
|
|
35
|
+
|
|
36
|
+
return FhirClientJsonHelpers.remove_empty_elements_from_ordered_dict(result)
|
|
37
|
+
|
|
38
|
+
@classmethod
|
|
39
|
+
def from_dict(
|
|
40
|
+
cls, data: Dict[str, Any] | OrderedDict[str, Any]
|
|
41
|
+
) -> "FhirBundleEntrySearch":
|
|
42
|
+
"""
|
|
43
|
+
Creates a FhirBundleEntrySearch object from a dictionary.
|
|
44
|
+
|
|
45
|
+
:param data: A dictionary containing the search entry data.
|
|
46
|
+
:return: An instance of FhirBundleEntrySearch.
|
|
47
|
+
"""
|
|
48
|
+
return cls(
|
|
49
|
+
mode=data.get("mode"),
|
|
50
|
+
score=data.get("score"),
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
def to_json(self) -> str:
|
|
54
|
+
"""
|
|
55
|
+
Converts the FhirBundleEntrySearch instance to a JSON string.
|
|
56
|
+
|
|
57
|
+
:return: A JSON string representation of the FhirBundleEntrySearch instance.
|
|
58
|
+
"""
|
|
59
|
+
return json.dumps(self.dict(), cls=FhirJSONEncoder)
|
|
60
|
+
|
|
61
|
+
def __repr__(self) -> str:
|
|
62
|
+
"""
|
|
63
|
+
Returns a string representation of the FhirBundleEntrySearch instance.
|
|
64
|
+
|
|
65
|
+
:return: A string representation of the FhirBundleEntrySearch instance.
|
|
66
|
+
"""
|
|
67
|
+
return f"FhirBundleEntrySearch(mode={self.mode}, score={self.score})"
|
|
68
|
+
|
|
69
|
+
def __deepcopy__(self, memo: Dict[int, Any]) -> "FhirBundleEntrySearch":
|
|
70
|
+
"""
|
|
71
|
+
Creates a copy of the FhirBundleEntrySearch instance.
|
|
72
|
+
|
|
73
|
+
:return: A new FhirBundleEntrySearch instance with the same attributes.
|
|
74
|
+
"""
|
|
75
|
+
return FhirBundleEntrySearch(mode=self.mode, score=self.score)
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from typing import Optional, Dict, Any, OrderedDict
|
|
3
|
+
|
|
4
|
+
from compressedfhir.utilities.json_helpers import FhirClientJsonHelpers
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class FhirIdentifier:
|
|
8
|
+
"""
|
|
9
|
+
FHIR Identifier class for representing identifiers in FHIR resources.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
__slots__ = ["use", "system", "value"]
|
|
13
|
+
|
|
14
|
+
def __init__(
|
|
15
|
+
self,
|
|
16
|
+
use: Optional[str] = None,
|
|
17
|
+
system: Optional[str] = None,
|
|
18
|
+
value: Optional[str] = None,
|
|
19
|
+
) -> None:
|
|
20
|
+
"""
|
|
21
|
+
Initialize the FhirIdentifier object.
|
|
22
|
+
|
|
23
|
+
:param use: The purpose of the identifier (e.g., official, secondary).
|
|
24
|
+
:param system: The namespace for the identifier.
|
|
25
|
+
:param value: The actual identifier value.
|
|
26
|
+
"""
|
|
27
|
+
self.use: Optional[str] = use
|
|
28
|
+
self.system: Optional[str] = system
|
|
29
|
+
self.value: Optional[str] = value
|
|
30
|
+
|
|
31
|
+
def dict(self) -> OrderedDict[str, Any]:
|
|
32
|
+
"""
|
|
33
|
+
Convert the FhirIdentifier object to a dictionary.
|
|
34
|
+
|
|
35
|
+
:return: A dictionary representation of the FhirIdentifier object.
|
|
36
|
+
"""
|
|
37
|
+
result: OrderedDict[str, Any] = OrderedDict[str, Any]()
|
|
38
|
+
if self.use is not None:
|
|
39
|
+
result["use"] = self.use
|
|
40
|
+
if self.system is not None:
|
|
41
|
+
result["system"] = self.system
|
|
42
|
+
if self.value is not None:
|
|
43
|
+
result["value"] = self.value
|
|
44
|
+
return FhirClientJsonHelpers.remove_empty_elements_from_ordered_dict(result)
|
|
45
|
+
|
|
46
|
+
@classmethod
|
|
47
|
+
def from_dict(
|
|
48
|
+
cls, data: Dict[str, Any] | OrderedDict[str, Any]
|
|
49
|
+
) -> "FhirIdentifier":
|
|
50
|
+
"""
|
|
51
|
+
Create a FhirIdentifier object from a dictionary.
|
|
52
|
+
|
|
53
|
+
:param data: A dictionary containing the identifier data.
|
|
54
|
+
:return: An instance of FhirIdentifier.
|
|
55
|
+
"""
|
|
56
|
+
return cls(
|
|
57
|
+
use=data.get("use"),
|
|
58
|
+
system=data.get("system"),
|
|
59
|
+
value=data.get("value"),
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
def json(self) -> str:
|
|
63
|
+
"""
|
|
64
|
+
Convert the FhirIdentifier object to a JSON string.
|
|
65
|
+
:return: A JSON string representation of the FhirIdentifier object.
|
|
66
|
+
"""
|
|
67
|
+
return json.dumps(self.dict())
|
|
68
|
+
|
|
69
|
+
def __repr__(self) -> str:
|
|
70
|
+
"""
|
|
71
|
+
Return a string representation of the FhirIdentifier object.
|
|
72
|
+
:return: A string representation of the FhirIdentifier object.
|
|
73
|
+
"""
|
|
74
|
+
return (
|
|
75
|
+
f"FhirIdentifier(use={self.use}, system={self.system}, value={self.value})"
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
def __deepcopy__(self, memo: Dict[int, Any]) -> "FhirIdentifier":
|
|
79
|
+
"""
|
|
80
|
+
Create a copy of the FhirIdentifier object.
|
|
81
|
+
|
|
82
|
+
:return: A new FhirIdentifier object with the same attributes.
|
|
83
|
+
"""
|
|
84
|
+
return FhirIdentifier(use=self.use, system=self.system, value=self.value)
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from typing import Any, Dict, OrderedDict
|
|
3
|
+
|
|
4
|
+
from compressedfhir.utilities.fhir_json_encoder import FhirJSONEncoder
|
|
5
|
+
from compressedfhir.utilities.json_helpers import FhirClientJsonHelpers
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class FhirLink:
|
|
9
|
+
"""
|
|
10
|
+
Represents a link in a FHIR
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
__slots__ = ["url", "relation"]
|
|
14
|
+
|
|
15
|
+
def __init__(self, *, url: str, relation: str) -> None:
|
|
16
|
+
"""
|
|
17
|
+
Initializes a FhirLink instance.
|
|
18
|
+
|
|
19
|
+
:param url: The URL of the link.
|
|
20
|
+
:param relation: The relation type of the link.
|
|
21
|
+
"""
|
|
22
|
+
self.url: str = url
|
|
23
|
+
self.relation: str = relation
|
|
24
|
+
|
|
25
|
+
def dict(self) -> OrderedDict[str, Any]:
|
|
26
|
+
"""
|
|
27
|
+
Converts the FhirLink instance to a dictionary.
|
|
28
|
+
|
|
29
|
+
:return: A dictionary representation of the link.
|
|
30
|
+
"""
|
|
31
|
+
result = OrderedDict[str, Any]({"url": self.url, "relation": self.relation})
|
|
32
|
+
return FhirClientJsonHelpers.remove_empty_elements_from_ordered_dict(result)
|
|
33
|
+
|
|
34
|
+
def json(self) -> str:
|
|
35
|
+
"""
|
|
36
|
+
Converts the FhirLink instance to a JSON string.
|
|
37
|
+
|
|
38
|
+
:return: A JSON string representation of the link.
|
|
39
|
+
"""
|
|
40
|
+
return json.dumps(self.dict(), cls=FhirJSONEncoder)
|
|
41
|
+
|
|
42
|
+
def __repr__(self) -> str:
|
|
43
|
+
return f"FhirLink(url={self.url}, relation={self.relation})"
|
|
44
|
+
|
|
45
|
+
@classmethod
|
|
46
|
+
def from_dict(cls, data: Dict[str, Any] | OrderedDict[str, Any]) -> "FhirLink":
|
|
47
|
+
"""
|
|
48
|
+
Populates the FhirLink instance from a dictionary.
|
|
49
|
+
|
|
50
|
+
:param data: A dictionary containing the link data.
|
|
51
|
+
"""
|
|
52
|
+
return cls(
|
|
53
|
+
url=data.get("url") or "unknown",
|
|
54
|
+
relation=data.get("relation") or "unknown",
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
def __deepcopy__(self, memo: Dict[int, Any]) -> "FhirLink":
|
|
58
|
+
"""
|
|
59
|
+
Creates a copy of the FhirLink instance.
|
|
60
|
+
|
|
61
|
+
:return: A new FhirLink instance with the same attributes.
|
|
62
|
+
"""
|
|
63
|
+
return FhirLink(url=self.url, relation=self.relation)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import dataclasses
|
|
2
|
+
from typing import Any, Dict, OrderedDict
|
|
3
|
+
|
|
4
|
+
from compressedfhir.utilities.json_helpers import FhirClientJsonHelpers
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclasses.dataclass(slots=True)
|
|
8
|
+
class FhirMeta:
|
|
9
|
+
"""
|
|
10
|
+
FhirMeta represents the meta information of a FHIR resource.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
version_id: str | None = None
|
|
14
|
+
last_updated: str | None = None
|
|
15
|
+
source: str | None = None
|
|
16
|
+
profile: list[str] | None = None
|
|
17
|
+
security: list[Dict[str, Any]] | None = None
|
|
18
|
+
tag: list[str] | None = None
|
|
19
|
+
|
|
20
|
+
def dict(self) -> OrderedDict[str, Any]:
|
|
21
|
+
result: OrderedDict[str, Any] = OrderedDict[str, Any]()
|
|
22
|
+
if self.version_id is not None:
|
|
23
|
+
result["versionId"] = self.version_id
|
|
24
|
+
if self.last_updated is not None:
|
|
25
|
+
result["lastUpdated"] = self.last_updated
|
|
26
|
+
if self.source is not None:
|
|
27
|
+
result["source"] = self.source
|
|
28
|
+
if self.profile is not None:
|
|
29
|
+
result["profile"] = [p for p in self.profile if p]
|
|
30
|
+
if self.security is not None:
|
|
31
|
+
result["security"] = [
|
|
32
|
+
FhirClientJsonHelpers.remove_empty_elements(s) for s in self.security
|
|
33
|
+
]
|
|
34
|
+
if self.tag is not None:
|
|
35
|
+
result["tag"] = [t for t in self.tag if t]
|
|
36
|
+
return FhirClientJsonHelpers.remove_empty_elements_from_ordered_dict(result)
|
|
37
|
+
|
|
38
|
+
@classmethod
|
|
39
|
+
def from_dict(cls, data: Dict[str, Any]) -> "FhirMeta":
|
|
40
|
+
return cls(
|
|
41
|
+
version_id=data.get("versionId"),
|
|
42
|
+
last_updated=data.get("lastUpdated"),
|
|
43
|
+
source=data.get("source"),
|
|
44
|
+
profile=data.get("profile"),
|
|
45
|
+
security=data.get("security"),
|
|
46
|
+
tag=data.get("tag"),
|
|
47
|
+
)
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import copy
|
|
2
|
+
import json
|
|
3
|
+
from typing import Any, Optional, Dict, List, cast, OrderedDict, override
|
|
4
|
+
|
|
5
|
+
from compressedfhir.fhir.fhir_meta import FhirMeta
|
|
6
|
+
from compressedfhir.utilities.compressed_dict.v1.compressed_dict import (
|
|
7
|
+
CompressedDict,
|
|
8
|
+
)
|
|
9
|
+
from compressedfhir.utilities.compressed_dict.v1.compressed_dict_storage_mode import (
|
|
10
|
+
CompressedDictStorageMode,
|
|
11
|
+
)
|
|
12
|
+
from compressedfhir.utilities.fhir_json_encoder import FhirJSONEncoder
|
|
13
|
+
from compressedfhir.utilities.json_helpers import FhirClientJsonHelpers
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class FhirResource(CompressedDict[str, Any]):
|
|
17
|
+
"""
|
|
18
|
+
FhirResource is a class that represents a FHIR resource.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
__slots__ = CompressedDict.__slots__
|
|
22
|
+
|
|
23
|
+
def __init__(
|
|
24
|
+
self,
|
|
25
|
+
initial_dict: Dict[str, Any] | OrderedDict[str, Any] | None = None,
|
|
26
|
+
*,
|
|
27
|
+
meta: Optional[FhirMeta] = None,
|
|
28
|
+
storage_mode: CompressedDictStorageMode = CompressedDictStorageMode.default(),
|
|
29
|
+
properties_to_cache: Optional[List[str]] = None,
|
|
30
|
+
) -> None:
|
|
31
|
+
if meta is not None:
|
|
32
|
+
initial_dict = initial_dict or {}
|
|
33
|
+
initial_dict["meta"] = meta.dict()
|
|
34
|
+
super().__init__(
|
|
35
|
+
initial_dict=initial_dict,
|
|
36
|
+
storage_mode=storage_mode,
|
|
37
|
+
properties_to_cache=properties_to_cache or ["resourceType", "id", "meta"],
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
@classmethod
|
|
41
|
+
def construct(cls, **kwargs: Any) -> "FhirResource":
|
|
42
|
+
"""
|
|
43
|
+
Constructs a FhirResource object from keyword arguments.
|
|
44
|
+
|
|
45
|
+
:param kwargs: Keyword arguments to initialize the resource.
|
|
46
|
+
:return: A FhirResource object.
|
|
47
|
+
"""
|
|
48
|
+
return cls(initial_dict=kwargs)
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def resource_type(self) -> Optional[str]:
|
|
52
|
+
"""Get the resource type from the resource dictionary."""
|
|
53
|
+
return self.get("resourceType")
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def resource_type_and_id(self) -> Optional[str]:
|
|
57
|
+
"""Get the resource type and ID from the resource dictionary."""
|
|
58
|
+
return (
|
|
59
|
+
f"{self.resource_type}/{self.id}"
|
|
60
|
+
if self.resource_type and self.id
|
|
61
|
+
else None
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
def json(self) -> str:
|
|
65
|
+
"""Convert the resource to a JSON string."""
|
|
66
|
+
return json.dumps(obj=self.dict(), cls=FhirJSONEncoder)
|
|
67
|
+
|
|
68
|
+
@classmethod
|
|
69
|
+
def from_json(cls, json_str: str) -> "FhirResource":
|
|
70
|
+
"""
|
|
71
|
+
Create a FhirResource object from a JSON string.
|
|
72
|
+
|
|
73
|
+
:param json_str: The JSON string to convert.
|
|
74
|
+
:return: A FhirResource object.
|
|
75
|
+
"""
|
|
76
|
+
data = json.loads(json_str)
|
|
77
|
+
return cls.from_dict(data)
|
|
78
|
+
|
|
79
|
+
def __deepcopy__(self, memo: Dict[int, Any]) -> "FhirResource":
|
|
80
|
+
"""Create a copy of the resource."""
|
|
81
|
+
return FhirResource(
|
|
82
|
+
initial_dict=super().dict(),
|
|
83
|
+
storage_mode=self._storage_mode,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
def __repr__(self) -> str:
|
|
87
|
+
"""Custom string representation for debugging."""
|
|
88
|
+
return f"FhirResource({self.resource_type}/{self.id})"
|
|
89
|
+
|
|
90
|
+
def copy(self) -> "FhirResource":
|
|
91
|
+
"""
|
|
92
|
+
Creates a copy of the BundleEntry object.
|
|
93
|
+
|
|
94
|
+
:return: A new BundleEntry object with the same attributes.
|
|
95
|
+
"""
|
|
96
|
+
return copy.deepcopy(self)
|
|
97
|
+
|
|
98
|
+
@override
|
|
99
|
+
def dict(self, *, remove_nulls: bool = True) -> OrderedDict[str, Any]:
|
|
100
|
+
"""
|
|
101
|
+
Converts the FhirResource object to a dictionary.
|
|
102
|
+
|
|
103
|
+
:param remove_nulls: If True, removes None values from the dictionary.
|
|
104
|
+
:return: A dictionary representation of the FhirResource object.
|
|
105
|
+
"""
|
|
106
|
+
ordered_dict = super().dict()
|
|
107
|
+
result: OrderedDict[str, Any] = copy.deepcopy(ordered_dict)
|
|
108
|
+
if remove_nulls:
|
|
109
|
+
result = FhirClientJsonHelpers.remove_empty_elements_from_ordered_dict(
|
|
110
|
+
result
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
return result
|
|
114
|
+
|
|
115
|
+
@classmethod
|
|
116
|
+
def from_dict(
|
|
117
|
+
cls,
|
|
118
|
+
d: Dict[str, Any],
|
|
119
|
+
*,
|
|
120
|
+
storage_mode: CompressedDictStorageMode = CompressedDictStorageMode.default(),
|
|
121
|
+
) -> "FhirResource":
|
|
122
|
+
"""
|
|
123
|
+
Creates a FhirResource object from a dictionary.
|
|
124
|
+
|
|
125
|
+
:param d: The dictionary to convert.
|
|
126
|
+
:param storage_mode: The storage mode for the CompressedDict.
|
|
127
|
+
:return: A FhirResource object.
|
|
128
|
+
"""
|
|
129
|
+
return cls(initial_dict=d, storage_mode=storage_mode)
|
|
130
|
+
|
|
131
|
+
def remove_nulls(self) -> None:
|
|
132
|
+
"""
|
|
133
|
+
Removes None values from the resource dictionary.
|
|
134
|
+
"""
|
|
135
|
+
self.replace(value=self.dict(remove_nulls=True))
|
|
136
|
+
|
|
137
|
+
@property
|
|
138
|
+
def id(self) -> Optional[str]:
|
|
139
|
+
"""Get the ID from the resource dictionary."""
|
|
140
|
+
return self.get("id")
|
|
141
|
+
|
|
142
|
+
@id.setter
|
|
143
|
+
def id(self, value: Optional[str]) -> None:
|
|
144
|
+
"""Set the ID of the Bundle."""
|
|
145
|
+
self["id"] = value
|
|
146
|
+
|
|
147
|
+
@property
|
|
148
|
+
def meta(self) -> FhirMeta | None:
|
|
149
|
+
"""Get the meta information from the resource dictionary."""
|
|
150
|
+
return (
|
|
151
|
+
FhirMeta.from_dict(cast(Dict[str, Any], self.get("meta")))
|
|
152
|
+
if "meta" in self
|
|
153
|
+
else None
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
@meta.setter
|
|
157
|
+
def meta(self, value: FhirMeta | None) -> None:
|
|
158
|
+
"""Set the meta information of the resource."""
|
|
159
|
+
if value is None:
|
|
160
|
+
self.pop("meta", None)
|
|
161
|
+
else:
|
|
162
|
+
assert isinstance(value, FhirMeta)
|
|
163
|
+
self["meta"] = value.dict()
|