Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions fhirpathpy/engine/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ def doInvoke(ctx, fn_name, data, raw_params):
if "nullable_input" in invocation and util.is_nullable(data):
return []

if "variadic" in invocation:
tp = invocation["variadic"]
raw_params_list = raw_params if isinstance(raw_params, list) else []
thisValue = ctx["$this"] if "$this" in ctx else ctx["dataRoot"]
params = [make_param(ctx, thisValue, tp, pr) for pr in raw_params_list]
res = invocation["fn"](ctx, util.arraify(data), *params)
return util.arraify(res)

if "arity" not in invocation:
if raw_params is None or util.is_empty(raw_params):
res = invocation["fn"](ctx, util.arraify(data))
Expand Down
1 change: 1 addition & 0 deletions fhirpathpy/engine/invocations/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"skip": {"fn": filtering.skip_fn, "arity": {1: ["Integer"]}},
"intersect": {"fn": subsetting.intersect_fn, "arity": {1: ["AnyAtRoot"]}},
"combine": {"fn": combining.combine_fn, "arity": {1: ["AnyAtRoot"]}},
"coalesce": {"fn": combining.coalesce_fn, "variadic": "Expr"},
"iif": {"fn": misc.iif_macro, "arity": {2: ["Expr", "Expr"], 3: ["Expr", "Expr", "Expr"]}},
"trace": {"fn": misc.trace_fn, "arity": {0: [], 1: ["String"]}},
"toInteger": {"fn": misc.to_integer},
Expand Down
9 changes: 9 additions & 0 deletions fhirpathpy/engine/invocations/combining.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from fhirpathpy.engine import util
from fhirpathpy.engine.invocations import existence

"""
Expand All @@ -15,3 +16,11 @@ def combine_fn(ctx, coll1, coll2):

def exclude_fn(ctx, coll1, coll2):
return [element for element in coll1 if element not in coll2]


def coalesce_fn(ctx, data, *exprs):
for expr in exprs:
result = expr(data)
if not util.is_empty(result):
return result
return []
2 changes: 1 addition & 1 deletion fhirpathpy/engine/invocations/navigation.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def func(acc, res):
actualTypes = model["choiceTypePaths"].get(altPropName, [])
if len(actualTypes) > 0:
# If it is, we can use it
fullPath = f"{res.propName}.{prop[:-len(childPath)]}"
fullPath = f"{res.propName}.{prop[: -len(childPath)]}"

if isinstance(value, list):
mapped = [
Expand Down
4 changes: 4 additions & 0 deletions fhirpathpy/engine/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,8 @@ def __str__(self):
return time_str
return self.asStr

__hash__ = None

def __eq__(self, other):
if isinstance(other, str):
return self.getTimeMatchStr()
Expand Down Expand Up @@ -734,6 +736,8 @@ def __str__(self):
return iso_str
return self.asStr

__hash__ = None

def __eq__(self, other):
if isinstance(other, str):
return self.getDateTimeMatchStr()
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
minversion = "6.0"
addopts = "-ra -q --color=yes --cov=fhirpathpy --cov-report=xml"
testpaths = ["tests"]
filterwarnings = ["ignore::pytest.PytestRemovedIn9Warning"]
log_cli = true
log_cli_level = "INFO"
python_functions = "*_test"
Expand Down
33 changes: 33 additions & 0 deletions tests/cases/5.2.8_coalesce.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
tests:
- desc: '5.2.8 coalesce'

- desc: '** returns first non-empty value from identifier'
expression: "coalesce(Patient.identifier.where(system='required-system').value.first(), 'unknown')"
result:
- required-value

- desc: '** returns fallback when first is empty'
expression: "coalesce(Patient.identifier.where(system='other-system').value.first(), 'unknown')"
result:
- unknown

- desc: '** returns first non-empty collection among multiple args'
expression: "coalesce({}, (1 | 2), (3 | 4))"
result:
- 1
- 2

- desc: '** returns single value when first arg is empty'
expression: "coalesce({}, 1)"
result:
- 1

- desc: '** returns empty when only arg is empty'
expression: "coalesce({})"
result: []

subject:
resourceType: Patient
identifier:
- system: required-system
value: required-value
Loading