Skip to content

Commit bfc741e

Browse files
authored
Merge pull request #28 from mlaletina95/python-documentation
Update readme with examples
2 parents f58b1ec + b2d0e05 commit bfc741e

1 file changed

Lines changed: 232 additions & 6 deletions

File tree

python/README.md

Lines changed: 232 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,56 @@
1-
# FHIRPathMappingLanguage - fpml python package
1+
# fpml (FHIRPathMappingLanguage)
2+
3+
The FHIRPath Mapping Language (FPML) is a data DSL designed to convert data from QuestionnaireResponse (and not only) to any FHIR Resource.
4+
5+
For more details visit the [FHIRPathMappingLanguage specification](https://github.com/beda-software/FHIRPathMappingLanguage/tree/main?tab=readme-ov-file#specification).
26

37
## Installation
48

9+
You can install the package from PyPI using the following command:
10+
511
```bash
612
pip install fpml
713
```
814

9-
## Usage
15+
## API Reference
16+
17+
### resolve_template
18+
19+
The `resolve_template` function processes a given template with a specified FHIR resource, optionally applying a context and additional processing options.
1020

1121
```python
1222
from fpml import resolve_template
1323

24+
result = resolve_template(
25+
resource,
26+
template,
27+
context=None,
28+
fp_options=None,
29+
strict=False
30+
)
31+
```
32+
33+
### Arguments:
34+
35+
- resource (Resource): The input FHIR resource to process.
36+
- template (Any): The template describing the transformation.
37+
- context (Optional[Context], optional): Additional context data. Defaults to None.
38+
- fp_options (Optional[FPOptions], optional): Options for controlling FHIRPath evaluation. Defaults to None.
39+
- strict (bool, optional): Whether to enforce strict mode. Defaults to False. See more details on [strict mode](https://github.com/beda-software/FHIRPathMappingLanguage/tree/main?tab=readme-ov-file#strict-mode).
40+
41+
### Returns:
1442

43+
- Any: The processed output based on the template.
44+
45+
### Raises:
46+
47+
- FPMLValidationError: If validation of the template or resource fails.
48+
49+
## Usage
50+
51+
For the following QuestionnaireResponse resource:
52+
53+
```python
1554
resource = {
1655
"resourceType": "QuestionnaireResponse",
1756
"status": "completed",
@@ -26,32 +65,219 @@ resource = {
2665
}
2766
]
2867
}
68+
```
69+
70+
71+
Here's an example demonstrating how to use the `resolve_template` function:
72+
73+
```python
74+
from fpml import resolve_template
75+
2976

3077
template = {
3178
"resourceType": "Patient",
32-
"name": "{{ item.where(linkId='name').answer.valueString }}"
79+
"name": [
80+
{
81+
"text": "{{ item.where(linkId='name').answer.valueString }}"
82+
}
83+
]
3384
}
3485

3586
context = {}
3687

3788
result = resolve_template(resource, template, context)
89+
print(result)
90+
```
91+
92+
Output:
93+
```python
94+
{'resourceType': 'Patient', 'name': [{'text': 'Name'}]}
95+
```
96+
97+
### Using FHIR data-model
98+
99+
```python
100+
from fpml import resolve_template
101+
from fhirpathpy.models import models
102+
103+
104+
template = {
105+
"resourceType": "Patient",
106+
"name": [
107+
{
108+
"text": "{{ item.where(linkId='name').answer.value }}" # <-- according R4 model
109+
}
110+
]
111+
}
112+
113+
context = {}
114+
115+
fp_options = {
116+
"model": models["r4"]
117+
}
118+
119+
result = resolve_template(resource, template, context, fp_options)
120+
print(result)
121+
```
122+
123+
Output:
124+
```python
125+
{'resourceType': 'Patient', 'name': [{'text': 'Name'}]}
126+
```
127+
128+
### Using user-defined functions
129+
130+
```python
131+
from fpml import resolve_template
132+
133+
134+
template = {
135+
"resourceType": "Patient",
136+
"name": [
137+
{
138+
"text": "{{ item.where(linkId='name').answer.valueString.strip() }}" # <-- Custom function
139+
}
140+
]
141+
}
142+
143+
context = {}
144+
145+
user_invocation_table = {
146+
"strip": {
147+
"fn": lambda inputs: [i.strip() for i in inputs],
148+
"arity": {0: []},
149+
}
150+
}
151+
152+
fp_options = {
153+
"userInvocationTable": user_invocation_table
154+
}
155+
156+
result = resolve_template(resource, template, context, fp_options)
157+
print(result)
158+
```
159+
160+
Output:
161+
```python
162+
{'resourceType': 'Patient', 'name': [{'text': 'Name'}]}
163+
```
164+
165+
### Handling validation errors
166+
167+
```python
168+
from fpml import FPMLValidationError, resolve_template
169+
170+
171+
template = {
172+
"resourceType": "Patient",
173+
"name": [
174+
{
175+
"text": "{{ item.where( }}" # <-- Invalid expression
176+
}
177+
]
178+
}
179+
180+
context = {}
181+
182+
try:
183+
resolve_template(resource, template, context)
184+
except FPMLValidationError as e:
185+
print(f"Validation error: {e.error_message}")
186+
print(f"Error path: `{e.error_path}`")
187+
```
188+
189+
Output:
190+
```python
191+
"Validation error: Cannot evaluate 'item.where(': where wrong arity: got 0"
192+
"Error path: `name.0.text`"
193+
```
194+
195+
### Using strict mode
196+
197+
In strict mode only context variables can be used (starting with percent sigh). Any access of the resource property will raise a validation error.
198+
199+
```python
200+
from fpml import resolve_template
201+
202+
203+
template = {
204+
"resourceType": "Patient",
205+
"name": [
206+
{
207+
"text": "{{ item.where(linkId='name').answer.valueString }}" # <-- Accessing resource attribute
208+
}
209+
]
210+
}
211+
212+
context = {}
38213

214+
215+
resolve_template(resource, template, context, strict=True)
216+
```
217+
218+
Raises an error:
219+
```
220+
FPMLValidationError: Cannot evaluate 'item.where(linkId='name').answer.valueString': "Forbidden access to resource property 'item' in strict mode. Use context instead.". Path 'name.0.text'
221+
```
222+
223+
Meanwhile using context:
224+
225+
226+
```python
227+
from fpml import resolve_template
228+
229+
230+
template = {
231+
"resourceType": "Patient",
232+
"name": [
233+
{
234+
"text": "{{ %QuestionnaireResponse.item.where(linkId='name').answer.valueString }}" # <-- Accessing context variable
235+
}
236+
]
237+
}
238+
239+
context = {"QuestionnaireResponse": resource} # <-- Context
240+
241+
result = resolve_template(resource, template, context, strict=True)
39242
print(result)
40-
# {'resourceType': 'Patient', 'name': 'Name'}
243+
```
244+
245+
Output:
246+
```python
247+
{'resourceType': 'Patient', 'name': [{'text': 'Name'}]}
41248
```
42249

43250

44251
## Development
45252

253+
### Local environment and testing
254+
255+
```bash
256+
cd ./python
257+
poetry install
258+
```
259+
260+
To run tests:
261+
262+
```bash
263+
poetry run pytest
264+
```
265+
266+
267+
### Pre-commit hook
268+
46269
In `./python` directory:
47270

48271
Run in the shell
49-
```
272+
```bash
50273
autohooks activate
51274
```
52275

53-
And edit `../.git/hooks/pre-commit` by replacing the first line with
276+
And edit `../.git/hooks/pre-commit` replacing the first line with
54277
```
55278
#!/usr/bin/env -S poetry --project=./python run python
56279
```
57280

281+
## License
282+
283+
This project is licensed under the MIT License.

0 commit comments

Comments
 (0)