Skip to content

Commit a881e09

Browse files
py: fhirpy: fixed fhirpy client
1 parent 7cf3031 commit a881e09

1 file changed

Lines changed: 162 additions & 42 deletions

File tree

examples/python/fhirpy_client.py

Lines changed: 162 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,185 @@
11
import asyncio
22
import base64
3+
from typing import TypeVar, Dict, Any
4+
from pydantic import BaseModel
5+
from fhirpy import AsyncFHIRClient
36

47
from fhir_types.hl7_fhir_r4_core import HumanName
5-
from fhir_types.hl7_fhir_r4_core.bundle import Bundle
68
from fhir_types.hl7_fhir_r4_core.patient import Patient
7-
from fhirpy import AsyncFHIRClient
9+
from fhir_types.hl7_fhir_r4_core.organization import Organization
10+
11+
T = TypeVar('T', bound=BaseModel)
812

913
FHIR_SERVER_URL = "http://localhost:8080/fhir"
1014
USERNAME = "root"
11-
PASSWORD = (
12-
"<SECRET>" # get actual value from docker-compose.yaml: BOX_ROOT_CLIENT_SECRET
13-
)
15+
PASSWORD = "<SECRET>"
1416
TOKEN = base64.b64encode(f"{USERNAME}:{PASSWORD}".encode()).decode()
1517

1618

19+
class CompatibleClient(AsyncFHIRClient):
20+
21+
async def create_from_pydantic_model(self, model: T):
22+
resource_dict = model.model_dump(
23+
mode='json',
24+
by_alias=True,
25+
exclude_none=True
26+
)
27+
28+
resource_type = resource_dict.pop('resourceType', None)
29+
if not resource_type and hasattr(model, 'resource_type'):
30+
resource_type = model.resource_type
31+
32+
if not resource_type:
33+
raise ValueError("Cannot determine resource type from model")
34+
35+
resource = self.resource(resource_type, **resource_dict)
36+
await resource.save()
37+
return resource
38+
39+
async def update_from_pydantic_model(self, model: T, resource_id: str):
40+
resource_dict = model.model_dump(
41+
mode='json',
42+
by_alias=True,
43+
exclude_none=True
44+
)
45+
46+
resource_type = resource_dict.pop('resourceType', None)
47+
if not resource_type and hasattr(model, 'resource_type'):
48+
resource_type = model.resource_type
49+
50+
if not resource_type:
51+
raise ValueError("Cannot determine resource type from model")
52+
53+
resource = self.resource(resource_type, id=resource_id, **resource_dict)
54+
await resource.save()
55+
return resource
56+
57+
def pydantic_model_to_resource(self, model: T):
58+
resource_dict = model.model_dump(
59+
mode='json',
60+
by_alias=True,
61+
exclude_none=True
62+
)
63+
64+
resource_type = resource_dict.pop('resourceType', None)
65+
if not resource_type and hasattr(model, 'resource_type'):
66+
resource_type = model.resource_type
67+
68+
if not resource_type:
69+
raise ValueError("Cannot determine resource type from model")
70+
71+
return self.resource(resource_type, **resource_dict)
72+
73+
1774
async def main():
18-
# Create an instance
19-
client = AsyncFHIRClient(
20-
"http://localhost:8080/fhir",
75+
76+
client = CompatibleClient(
77+
FHIR_SERVER_URL,
2178
authorization=f"Basic {TOKEN}",
2279
)
2380

24-
# Search for patients
25-
resources = client.resources("Patient") # Return lazy search set
26-
resources = resources.search(name="John").limit(10).sort("name")
27-
patients = await resources.fetch() # Returns list of AsyncFHIRResource
28-
29-
# Create Patient reource
3081
patient = Patient(
3182
name=[HumanName(given=["Create"], family="Test")],
3283
gender="female",
3384
birthDate="1980-01-01",
3485
)
35-
pat = await client.create(patient) # returns Patient
36-
print(pat)
37-
38-
# Create Organization resource
39-
organization = client.resource("Organization", name="beda.software", active=False)
40-
await organization.save()
41-
42-
# Update (PATCH) organization. Resource support accessing its elements
43-
# both as attribute and as a dictionary keys
44-
if organization["active"] is False:
45-
organization.active = True
46-
await organization.save(fields=["active"])
47-
# `await organization.patch(active=True)` would do the same PATCH operation
48-
49-
# # Get patient resource by reference and delete
50-
# patient_ref = client.reference("Patient", "new_patient")
51-
# # Get resource from this reference
52-
# # (throw ResourceNotFound if no resource was found)
53-
# patient_res = await patient_ref.to_resource()
54-
# await patient_res.delete()
55-
56-
# Iterate over search set
57-
org_resources = client.resources("Organization")
58-
# Lazy loading resources page by page with page count = 100
59-
async for org_resource in org_resources.limit(100):
60-
print(org_resource.serialize())
86+
87+
created_patient = await client.create_from_pydantic_model(patient)
88+
print(f"Created patient: {created_patient.id}")
89+
print(created_patient.serialize())
90+
91+
organization = Organization(
92+
name="Beda Software",
93+
active=True
94+
)
95+
96+
created_org = await client.create_from_pydantic_model(organization)
97+
print(f"Created organization: {created_org.id}")
98+
99+
another_patient = Patient(
100+
name=[HumanName(given=["John"], family="Doe")],
101+
gender="male",
102+
birthDate="1990-05-15",
103+
)
104+
105+
patient_resource = client.pydantic_model_to_resource(another_patient)
106+
107+
await patient_resource.save()
108+
patient_resource.active = True
109+
await patient_resource.save()
110+
111+
patients = await client.resources("Patient").search(name="Test").fetch()
112+
for pat in patients:
113+
print(f"Found: {pat.get('name', [{}])[0].get('family', 'N/A')}")
61114

62115

63116
if __name__ == "__main__":
64-
loop = asyncio.get_event_loop()
65-
loop.run_until_complete(main())
117+
asyncio.run(main())
118+
119+
120+
# import asyncio
121+
# import base64
122+
#
123+
# from fhir_types.hl7_fhir_r4_core import HumanName
124+
# from fhir_types.hl7_fhir_r4_core.bundle import Bundle
125+
# from fhir_types.hl7_fhir_r4_core.patient import Patient
126+
# from fhirpy import AsyncFHIRClient
127+
#
128+
# FHIR_SERVER_URL = "http://localhost:8080/fhir"
129+
# USERNAME = "root"
130+
# PASSWORD = (
131+
# "mNZq6yJaRi"#"<SECRET>" # get actual value from docker-compose.yaml: BOX_ROOT_CLIENT_SECRET
132+
# )
133+
# TOKEN = base64.b64encode(f"{USERNAME}:{PASSWORD}".encode()).decode()
134+
#
135+
#
136+
# async def main():
137+
# # Create an instance
138+
# client = AsyncFHIRClient(
139+
# "http://localhost:8080/fhir",
140+
# authorization=f"Basic {TOKEN}",
141+
# )
142+
#
143+
# # Search for patients
144+
# resources = client.resources("Patient") # Return lazy search set
145+
# resources = resources.search(name="John").limit(10).sort("name")
146+
# patients = await resources.fetch() # Returns list of AsyncFHIRResource
147+
#
148+
# # Create Patient reource
149+
# patient = Patient(
150+
# name=[HumanName(given=["Create"], family="Test")],
151+
# gender="female",
152+
# birthDate="1980-01-01",
153+
# )
154+
#
155+
# pat = await client.create(patient) # returns Patient
156+
# print(pat)
157+
#
158+
# # Create Organization resource
159+
# organization = client.resource("Organization", name="beda.software", active=False)
160+
# await organization.save()
161+
#
162+
# # Update (PATCH) organization. Resource support accessing its elements
163+
# # both as attribute and as a dictionary keys
164+
# if organization["active"] is False:
165+
# organization.active = True
166+
# await organization.save(fields=["active"])
167+
# # `await organization.patch(active=True)` would do the same PATCH operation
168+
#
169+
# # # Get patient resource by reference and delete
170+
# # patient_ref = client.reference("Patient", "new_patient")
171+
# # # Get resource from this reference
172+
# # # (throw ResourceNotFound if no resource was found)
173+
# # patient_res = await patient_ref.to_resource()
174+
# # await patient_res.delete()
175+
#
176+
# # Iterate over search set
177+
# org_resources = client.resources("Organization")
178+
# # Lazy loading resources page by page with page count = 100
179+
# async for org_resource in org_resources.limit(100):
180+
# print(org_resource.serialize())
181+
#
182+
#
183+
# if __name__ == "__main__":
184+
# loop = asyncio.get_event_loop()
185+
# loop.run_until_complete(main())

0 commit comments

Comments
 (0)