Skip to content

Commit 775b53b

Browse files
committed
Add support for array expression. Closes #20
1 parent a667218 commit 775b53b

File tree

8 files changed

+41
-12
lines changed

8 files changed

+41
-12
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
## 0.1.0
2+
3+
- Add `{[ expr ]}` that always returns an array #20
4+
5+
## 0.0.1
6+
7+
- Initial PyPI release

python/fpml/core/extract.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,17 @@ def process_template_string(
125125
context: Context,
126126
fp_options: Optional[FPOptions],
127127
) -> Any:
128-
template_regexp = re.compile(r"{{\+?\s*([\s\S]+?)\s*\+?}}")
128+
array_template_regexp = re.compile(r"{\[\s*([\s\S]+?)\s*\]}")
129+
130+
match = array_template_regexp.match(node)
131+
if match:
132+
expr = match.group(1)
133+
return evaluate_expression(path, resource, expr, context, fp_options)
134+
135+
single_template_regexp = re.compile(r"{{\+?\s*([\s\S]+?)\s*\+?}}")
129136
result = node
130137

131-
for match in template_regexp.finditer(node):
138+
for match in single_template_regexp.finditer(node):
132139
expr = match.group(1)
133140
try:
134141
replacement = evaluate_expression(path, resource, expr, context, fp_options)[0]

python/pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
[project]
22
name = "fpml"
3+
version = "0.1.0"
34
description = "The FHIRPath mapping language is a data DSL designed to convert data from QuestionnaireResponse (and not only) to any FHIR Resource."
45
authors = [{ name = "Beda Software", email = "ilya@beda.software" }]
56
maintainers = [
@@ -9,7 +10,7 @@ maintainers = [
910
license = { text = "MIT" }
1011
requires-python = ">=3.9"
1112
keywords = ["fhir", "fhirpath"]
12-
dynamic = ["version", "classifiers"]
13+
dynamic = ["classifiers"]
1314
dependencies = ["fhirpathpy (>=1.2.1,<2.0.0)"]
1415

1516
[project.urls]
@@ -19,7 +20,6 @@ documentation = "https://github.com/beda-software/FHIRPathMappingLanguage/tree/m
1920
"Bug Tracker" = "https://github.com/beda-software/FHIRPathMappingLanguage/issues"
2021

2122
[tool.poetry]
22-
version = "0.0.1"
2323
packages = [{ include = "fpml" }]
2424
classifiers = [
2525
"Development Status :: 5 - Production/Stable",

python/tests/core/test_extract.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,11 @@ def test_transformation_fails_with_incorrect_fhirpath_expression() -> None:
125125
resolve_template({}, "{{ item.where(linkId='a) }}")
126126

127127

128+
def test_transformation_for_array_template_works_properly() -> None:
129+
resource: Resource = {"list": [{"key": 1}, {"key": 2}]}
130+
assert resolve_template(resource, "{[ list.key ]}") == [1, 2]
131+
132+
128133
def test_context_block_resolve_template() -> None:
129134
resource: Resource = {
130135
"foo": "bar",

tests/__data__/complex-example.aidbox.template.yaml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@ body:
22
"{% assign %}":
33
- patientId: "{{ %Patient.id }}"
44
- recordedDate: "{{ %QuestionnaireResponse.authored }}"
5-
- provenanceTargetIds:
6-
"{% for id in %Provenance.target.id %}": "{{ %id }}"
5+
- provenanceTargetIds: "{[ %Provenance.target.id ]}"
76
- weight: "{{ repeat(item).where(linkId='WEIGHT').answer.value.children() }}"
87
- height: "{{ repeat(item).where(linkId='HEIGHT').answer.value.children() }}"
9-
- medConditions:
10-
"{% for answer in repeat(item).where(linkId in 'MEDCOND1' | 'MEDCOND2').answer.value.children() %}": "{{ %answer }}"
8+
- medConditions: "{[ repeat(item).where(linkId in 'MEDCOND1' | 'MEDCOND2').answer.value.children() ]}"
119
- observationEntries:
1210
- "{% if %weight.exists() and %height.exists() %}":
1311
"{% assign %}":

tests/__data__/complex-example.fhir.template.yaml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@ body:
22
"{% assign %}":
33
- patientRef: "Patient/{{ %Patient.id }}"
44
- recordedDate: "{{ %QuestionnaireResponse.authored }}"
5-
- provenanceTargetIds:
6-
"{% for id in %Provenance.target.select(reference.split('/').last()) %}": "{{ %id }}"
5+
- provenanceTargetIds: "{[ %Provenance.target.select(reference.split('/').last()) ]}"
76
- weight: "{{ repeat(item).where(linkId='WEIGHT').answer.value }}"
87
- height: "{{ repeat(item).where(linkId='HEIGHT').answer.value }}"
9-
- medConditions:
10-
"{% for answer in repeat(item).where(linkId in 'MEDCOND1' | 'MEDCOND2').answer.value %}": "{{ %answer }}"
8+
- medConditions: "{[ repeat(item).where(linkId in 'MEDCOND1' | 'MEDCOND2').answer.value ]}"
119
- observationEntries:
1210
- "{% if %weight.exists() and %height.exists() %}":
1311
"{% assign %}":

ts/server/src/core/extract.spec.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,12 @@ describe('Transformation', () => {
121121
FPMLValidationError,
122122
);
123123
});
124+
125+
test('array template works properly', () => {
126+
expect(resolveTemplate({ list: [{ key: 1 }, { key: 2 }] }, '{[ list.key ]}')).toStrictEqual(
127+
[1, 2],
128+
);
129+
});
124130
});
125131

126132
describe('Context block', () => {

ts/server/src/core/extract.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,14 @@ function processTemplateString(
119119
| RegExpExecArray
120120
| { [Symbol.replace](string: string, replaceValue: string): string }[];
121121

122+
const arrayTemplateRegExp = /{\[\s*([\s\S]+?)\s*\]}/g;
123+
match = arrayTemplateRegExp.exec(node);
124+
if (match) {
125+
const expr = match[1];
126+
127+
return evaluateExpression(path, resource, expr, context, model, fpOptions);
128+
}
129+
122130
const singleTemplateRegExp = /{{\+?\s*([\s\S]+?)\s*\+?}}/g;
123131
let result: any = node;
124132

0 commit comments

Comments
 (0)