-
Notifications
You must be signed in to change notification settings - Fork 5
Python: support for fhirpy client #43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
5f62ee7
py: fhirpy: add client test
ryukzak 0bfef03
py: fhirpy: add client test
ryukzak 7cf3031
Merge remote-tracking branch 'origin/fhirpy-client' into fhirpy-client
MikhailArtemyev a881e09
py: fhirpy: fixed fhirpy client
MikhailArtemyev c57d602
py: fhirpy: direct usage of AsyncFHIRClient
MikhailArtemyev 9990bc2
py: fhirpy: extended fhirpy client support
MikhailArtemyev 07f9cbb
py: changed example for supporting fhirpy client
MikhailArtemyev 1097371
minor format fix
MikhailArtemyev 2721421
py: replaced fhirpy example with a common client example
MikhailArtemyev e3af334
py: renamed FHIRBase into FhirBaseModel
MikhailArtemyev ac8e693
py: renamed FhirBaseModel into FhirpyBaseModel
MikhailArtemyev b5b3eee
py: fhirpy: added comments to fhirpy_client.py
MikhailArtemyev f1bea26
ci: py: added a ci step for fhirpy generator
MikhailArtemyev cd79e9e
minor format fix
MikhailArtemyev 65f50eb
Merge branch 'main' into fhirpy-client-2
MikhailArtemyev b491851
py: fixed failing test
MikhailArtemyev 219e383
py: separated simple Python and FHIRPy examples into different direct…
MikhailArtemyev 7a6208a
chore: retrigger CI
MikhailArtemyev 9a669fc
Merge branch 'main' into fhirpy-client-2
MikhailArtemyev f6fc413
py: fixed generate.ts
MikhailArtemyev File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| from typing import Any, Union, Optional, Iterator, Tuple, Dict | ||
| from pydantic import BaseModel, Field | ||
| from typing import Protocol | ||
|
|
||
|
|
||
| class ResourceProtocol(Protocol): | ||
| resourceType: Any | ||
| id: Union[str, None] | ||
|
|
||
|
|
||
| class FhirpyBaseModel(BaseModel): | ||
| """ | ||
| This class satisfies ResourceProtocol | ||
| """ | ||
| resource_type: str = Field(alias="resourceType") | ||
| id: Optional[str] = Field(None, alias="id") | ||
|
|
||
| @property | ||
| def resourceType(self) -> str: | ||
| return self.resource_type | ||
|
|
||
| @resourceType.setter | ||
| def resourceType(self, value: str) -> None: | ||
| self.resource_type = value | ||
|
|
||
| def __iter__(self) -> Iterator[Tuple[str, Any]]: # type: ignore[override] | ||
| data = self.model_dump(mode='json', by_alias=True, exclude_none=True) | ||
| return iter(data.items()) | ||
|
|
||
| def serialize(self) -> Dict[str, Any]: | ||
| """Serialize to dict (compatible with fhirpy's serialize method)""" | ||
| return self.model_dump(mode='json', by_alias=True, exclude_none=True) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| .pytest_cache | ||
| __pycache__ | ||
| .mypy_cache | ||
| venv |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,147 @@ | ||
| # Python fhirpy Example | ||
|
|
||
| FHIR R4 type generation with Pydantic models integrated with the [fhirpy](https://github.com/beda-software/fhir-py) async client library. | ||
|
|
||
| ## Overview | ||
|
|
||
| This example demonstrates how to use generated Python/Pydantic models with the `fhirpy` async FHIR client. It includes: | ||
|
|
||
| - Full FHIR R4 resource type definitions as Pydantic models | ||
| - Integration with `fhirpy` AsyncFHIRClient | ||
| - Automatic validation and serialization | ||
| - Async/await patterns for FHIR operations | ||
|
|
||
| For a simpler example using `requests`, see [python-simple/](../python-simple/). | ||
|
|
||
| ## Setup | ||
|
|
||
| ### Python Environment | ||
|
|
||
| 1. Create virtual environment: | ||
|
|
||
| ```bash | ||
| cd examples/python-fhirpy | ||
| python3 -m venv venv | ||
|
|
||
| # On macOS/Linux: | ||
| source venv/bin/activate | ||
| # On Windows: | ||
| venv\Scripts\activate | ||
| ``` | ||
|
|
||
| 2. Install Python dependencies: | ||
|
|
||
| ```bash | ||
| pip install -r fhir_types/requirements.txt | ||
| pip install fhirpy | ||
| ``` | ||
|
|
||
| 3. Check Python version: | ||
|
|
||
| ```bash | ||
| python --version # Should be 3.10 or higher | ||
| ``` | ||
|
|
||
| ## Generating Types | ||
|
|
||
| To generate Python/Pydantic types for FHIR R4 with fhirpy support: | ||
|
|
||
| ```bash | ||
| bun run examples/python-fhirpy/generate.ts | ||
| ``` | ||
|
|
||
| This will output to `./examples/python-fhirpy/fhir_types/` | ||
|
|
||
| ## Configuration | ||
|
|
||
| Edit `generate.ts` to customize: | ||
|
|
||
| ```typescript | ||
| .python({ | ||
| allowExtraFields: false, // Reject unknown fields in models | ||
| fieldFormat: "snake_case", // or "camelCase" | ||
| fhirpyClient: true // Enable fhirpy integration | ||
| }) | ||
| ``` | ||
|
|
||
| The `fhirpyClient: true` option generates models that inherit from a base class compatible with fhirpy's client API. | ||
|
|
||
| ## Using with fhirpy | ||
|
|
||
| ### Basic Usage | ||
|
|
||
| ```python | ||
| import asyncio | ||
| from fhirpy import AsyncFHIRClient | ||
| from fhir_types.hl7_fhir_r4_core import HumanName | ||
| from fhir_types.hl7_fhir_r4_core.patient import Patient | ||
|
|
||
| async def main(): | ||
| client = AsyncFHIRClient( | ||
| "http://localhost:8080/fhir", | ||
| authorization="Basic <token>", | ||
| ) | ||
|
|
||
| # Create a patient using typed models | ||
| patient = Patient( | ||
| name=[HumanName(given=["John"], family="Doe")], | ||
| gender="male", | ||
| birthDate="1980-01-01", | ||
| ) | ||
|
|
||
| # Use fhirpy's client API with the typed model | ||
| created = await client.create(patient) | ||
| print(f"Created patient: {created.id}") | ||
|
|
||
| # Search for patients | ||
| patients = await client.resources("Patient").fetch() | ||
| for pat in patients: | ||
| print(f"Found: {pat.get('name', [{}])[0].get('family', 'N/A')}") | ||
|
|
||
| asyncio.run(main()) | ||
| ``` | ||
|
|
||
| ### Resource API | ||
|
|
||
| ```python | ||
| from fhir_types.hl7_fhir_r4_core.organization import Organization | ||
|
|
||
| organization = Organization( | ||
| name="My Organization", | ||
| active=True | ||
| ) | ||
|
|
||
| # Use fhirpy's resource API | ||
| org_resource = await client.resource( | ||
| "Organization", | ||
| **organization.model_dump(exclude_none=True) | ||
| ).save() | ||
|
|
||
| print(f"Created organization: {org_resource.id}") | ||
| ``` | ||
|
|
||
| ## Type Checking | ||
|
|
||
| ### MyPy Integration | ||
|
|
||
| Verify type safety with MyPy: | ||
|
|
||
| ```bash | ||
| pip install mypy | ||
| mypy fhir_types/ | ||
| ``` | ||
|
|
||
| ## Running the Demo | ||
|
|
||
| Start a FHIR server (e.g., using the docker-compose in examples/), then run: | ||
|
|
||
| ```bash | ||
| python client.py | ||
| ``` | ||
|
|
||
| ## Next Steps | ||
|
|
||
| - See [python-simple/](../python-simple/) for basic requests-based example | ||
| - See [examples/](../) overview for other language examples | ||
| - Check [../../CLAUDE.md](../../CLAUDE.md) for architecture details | ||
| - Learn more about [fhirpy](https://github.com/beda-software/fhir-py) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.