fhirpathpy 2.1.0__tar.gz → 2.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/PKG-INFO +7 -5
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/README.md +1 -1
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/__init__.py +109 -7
- fhirpathpy-2.2.0/fhirpathpy/py.typed +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/pyproject.toml +14 -22
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/LICENSE.md +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/engine/__init__.py +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/engine/evaluators/__init__.py +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/engine/invocations/__init__.py +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/engine/invocations/aggregate.py +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/engine/invocations/collections.py +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/engine/invocations/combining.py +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/engine/invocations/constants.py +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/engine/invocations/datetime.py +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/engine/invocations/equality.py +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/engine/invocations/existence.py +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/engine/invocations/filtering.py +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/engine/invocations/logic.py +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/engine/invocations/math.py +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/engine/invocations/misc.py +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/engine/invocations/navigation.py +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/engine/invocations/strings.py +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/engine/invocations/subsetting.py +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/engine/invocations/types.py +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/engine/nodes.py +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/engine/util.py +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/models/__init__.py +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/models/dstu2/choiceTypePaths.json +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/models/dstu2/path2Type.json +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/models/dstu2/pathsDefinedElsewhere.json +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/models/dstu2/type2Parent.json +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/models/r4/choiceTypePaths.json +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/models/r4/path2Type.json +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/models/r4/pathsDefinedElsewhere.json +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/models/r4/type2Parent.json +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/models/r5/choiceTypePaths.json +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/models/r5/path2Type.json +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/models/r5/pathsDefinedElsewhere.json +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/models/r5/type2Parent.json +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/models/stu3/choiceTypePaths.json +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/models/stu3/path2Type.json +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/models/stu3/pathsDefinedElsewhere.json +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/models/stu3/type2Parent.json +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/parser/ASTPathListener.py +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/parser/FHIRPath.g4 +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/parser/README.md +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/parser/__init__.py +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/parser/generated/FHIRPath.interp +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/parser/generated/FHIRPath.tokens +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/parser/generated/FHIRPathLexer.interp +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/parser/generated/FHIRPathLexer.py +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/parser/generated/FHIRPathLexer.tokens +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/parser/generated/FHIRPathListener.py +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/parser/generated/FHIRPathParser.py +0 -0
- {fhirpathpy-2.1.0 → fhirpathpy-2.2.0}/fhirpathpy/parser/generated/__init__.py +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fhirpathpy
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: FHIRPath implementation in Python
|
|
5
5
|
Keywords: fhir,fhirpath
|
|
6
6
|
Author-email: "beda.software" <fhirpath@beda.software>
|
|
7
|
-
Requires-Python: >=3.
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
8
|
Description-Content-Type: text/markdown
|
|
9
9
|
Classifier: Development Status :: 5 - Production/Stable
|
|
10
10
|
Classifier: Environment :: Web Environment
|
|
@@ -12,17 +12,19 @@ Classifier: Intended Audience :: Developers
|
|
|
12
12
|
Classifier: Operating System :: OS Independent
|
|
13
13
|
Classifier: Programming Language :: Python
|
|
14
14
|
Classifier: Programming Language :: Python :: 3
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
17
15
|
Classifier: Programming Language :: Python :: 3.10
|
|
18
16
|
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
19
|
Classifier: Topic :: Internet :: WWW/HTTP
|
|
20
20
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Classifier: Typing :: Typed
|
|
21
22
|
License-File: LICENSE.md
|
|
22
23
|
Requires-Dist: antlr4-python3-runtime~=4.10
|
|
23
24
|
Requires-Dist: python-dateutil~=2.8
|
|
24
25
|
Requires-Dist: pytest==7.1.1 ; extra == "test"
|
|
25
26
|
Requires-Dist: pyyaml==5.4 ; extra == "test"
|
|
27
|
+
Requires-Dist: pydantic==2.13.1 ; extra == "test"
|
|
26
28
|
Project-URL: Changelog, https://github.com/beda-software/fhirpath-py/blob/master/CHANGELOG.md
|
|
27
29
|
Project-URL: Documentation, https://github.com/beda-software/fhirpath-py#readme
|
|
28
30
|
Project-URL: Homepage, https://github.com/beda-software/fhirpath-py
|
|
@@ -35,7 +37,7 @@ fhirpath.py
|
|
|
35
37
|
[](https://github.com/beda-software/fhirpath-py/actions)
|
|
36
38
|
[](https://codecov.io/gh/beda-software/fhirpath-py)
|
|
37
39
|
[](https://pypi.org/project/fhirpathpy/)
|
|
38
|
-
[](https://www.python.org/downloads/release/python-3100/)
|
|
39
41
|
|
|
40
42
|
[FHIRPath](https://www.hl7.org/fhir/fhirpath.html) implementation in Python
|
|
41
43
|
|
|
@@ -4,7 +4,7 @@ fhirpath.py
|
|
|
4
4
|
[](https://github.com/beda-software/fhirpath-py/actions)
|
|
5
5
|
[](https://codecov.io/gh/beda-software/fhirpath-py)
|
|
6
6
|
[](https://pypi.org/project/fhirpathpy/)
|
|
7
|
-
[](https://www.python.org/downloads/release/python-3100/)
|
|
8
8
|
|
|
9
9
|
[FHIRPath](https://www.hl7.org/fhir/fhirpath.html) implementation in Python
|
|
10
10
|
|
|
@@ -1,18 +1,26 @@
|
|
|
1
|
-
from
|
|
2
|
-
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Callable, Mapping, Sequence
|
|
4
|
+
from typing import Any, Protocol, TypeVar, cast
|
|
5
|
+
|
|
3
6
|
from fhirpathpy.engine import do_eval
|
|
4
|
-
from fhirpathpy.engine.
|
|
7
|
+
from fhirpathpy.engine.invocations.constants import constants
|
|
5
8
|
from fhirpathpy.engine.nodes import FP_Type, ResourceNode
|
|
9
|
+
from fhirpathpy.engine.util import arraify, get_data, process_user_invocation_table, set_paths
|
|
10
|
+
from fhirpathpy.parser import parse
|
|
6
11
|
|
|
7
12
|
__title__ = "fhirpathpy"
|
|
8
|
-
__version__ = "2.
|
|
13
|
+
__version__ = "2.2.0"
|
|
9
14
|
__author__ = "beda.software"
|
|
10
15
|
__license__ = "MIT"
|
|
11
|
-
__copyright__ = "Copyright
|
|
16
|
+
__copyright__ = "Copyright 2026 beda.software"
|
|
12
17
|
|
|
13
18
|
# Version synonym
|
|
14
19
|
VERSION = __version__
|
|
15
20
|
|
|
21
|
+
ResourceType = Mapping[str, Any]
|
|
22
|
+
ContextType = Mapping[str, Any] | None
|
|
23
|
+
|
|
16
24
|
|
|
17
25
|
def apply_parsed_path(resource, parsedPath, context=None, model=None, options=None):
|
|
18
26
|
constants.reset()
|
|
@@ -84,7 +92,13 @@ def apply_parsed_path(resource, parsedPath, context=None, model=None, options=No
|
|
|
84
92
|
return visit(node)
|
|
85
93
|
|
|
86
94
|
|
|
87
|
-
def evaluate(
|
|
95
|
+
def evaluate(
|
|
96
|
+
resource: ResourceType | list,
|
|
97
|
+
path: str | dict,
|
|
98
|
+
context: dict | None = None,
|
|
99
|
+
model: dict | None = None,
|
|
100
|
+
options: dict | None = None,
|
|
101
|
+
) -> list:
|
|
88
102
|
"""
|
|
89
103
|
Evaluates the "path" FHIRPath expression on the given resource, using data
|
|
90
104
|
from "context" for variables mentioned in the "path" expression.
|
|
@@ -109,7 +123,9 @@ def evaluate(resource, path, context=None, model=None, options=None):
|
|
|
109
123
|
return apply_parsed_path(resource, node, context or {}, model, options)
|
|
110
124
|
|
|
111
125
|
|
|
112
|
-
def compile(
|
|
126
|
+
def compile(
|
|
127
|
+
path: str, model: dict | None = None, options: dict | None = None
|
|
128
|
+
) -> Callable[[ResourceType, ContextType], list]:
|
|
113
129
|
"""
|
|
114
130
|
Returns a function that takes a resource and an optional context hash (see
|
|
115
131
|
"evaluate"), and returns the result of evaluating the given FHIRPath
|
|
@@ -124,3 +140,89 @@ def compile(path, model=None, options=None):
|
|
|
124
140
|
For example, you could pass in the result of require("fhirpath/fhir-context/r4")
|
|
125
141
|
"""
|
|
126
142
|
return set_paths(apply_parsed_path, parsedPath=parse(path), model=model, options=options)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
InputType = TypeVar("InputType")
|
|
146
|
+
OutputType = TypeVar("OutputType")
|
|
147
|
+
# Contravariant: a callable accepting a wider input type is a valid subtype.
|
|
148
|
+
_I_contra = TypeVar("_I_contra", contravariant=True)
|
|
149
|
+
# Covariant: a callable returning a narrower output type is a valid subtype.
|
|
150
|
+
# Sequence (read-only) is required here because list is invariant and rejects covariant TypeVars.
|
|
151
|
+
_O_co = TypeVar("_O_co", covariant=True)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
class CompiledFirst(Protocol[_I_contra, _O_co]):
|
|
155
|
+
def __call__(self, resource: _I_contra, context: ContextType = ...) -> _O_co | None: ...
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
class CompiledArray(Protocol[_I_contra, _O_co]):
|
|
159
|
+
def __call__(self, resource: _I_contra, context: ContextType = ...) -> Sequence[_O_co]: ...
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def compile_as_array(
|
|
163
|
+
expression: str, input_type: type[InputType], output_type: type[OutputType]
|
|
164
|
+
) -> CompiledArray[InputType, OutputType]:
|
|
165
|
+
path_fn = compile(expression)
|
|
166
|
+
|
|
167
|
+
def fn(resource: Any, context: ContextType = None) -> Any:
|
|
168
|
+
return _format_result(
|
|
169
|
+
path_fn(_prepare_data(resource, input_type), context),
|
|
170
|
+
output_type,
|
|
171
|
+
is_array=True,
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
return cast(CompiledArray[InputType, OutputType], fn)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def compile_as_first(
|
|
178
|
+
expression: str, input_type: type[InputType], output_type: type[OutputType]
|
|
179
|
+
) -> CompiledFirst[InputType, OutputType]:
|
|
180
|
+
path_fn = compile(expression)
|
|
181
|
+
|
|
182
|
+
def fn(resource: Any, context: ContextType = None) -> Any:
|
|
183
|
+
return _format_result(
|
|
184
|
+
path_fn(_prepare_data(resource, input_type), context),
|
|
185
|
+
output_type,
|
|
186
|
+
is_array=False,
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
return cast(CompiledFirst[InputType, OutputType], fn)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def _prepare_data(resource: Any, input_type: type[InputType]) -> ResourceType:
|
|
193
|
+
if not isinstance(resource, input_type):
|
|
194
|
+
raise Exception(
|
|
195
|
+
f"Resource type is {type(resource).__name__}, expected {input_type.__name__}"
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
if isinstance(resource, dict):
|
|
199
|
+
return resource
|
|
200
|
+
|
|
201
|
+
if hasattr(resource, "model_dump"):
|
|
202
|
+
return resource.model_dump()
|
|
203
|
+
|
|
204
|
+
raise Exception(f"Don't know how to work with type {type(resource).__name__}")
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def _format_result(result: list, output_type: type[OutputType], is_array=False) -> Any:
|
|
208
|
+
result = [_format_item(item, output_type) for item in result]
|
|
209
|
+
|
|
210
|
+
if is_array:
|
|
211
|
+
return result
|
|
212
|
+
|
|
213
|
+
if len(result) == 0:
|
|
214
|
+
return None
|
|
215
|
+
|
|
216
|
+
return result[0]
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def _format_item(item: Any, output_type: type[OutputType]) -> OutputType:
|
|
220
|
+
if hasattr(output_type, "model_validate"):
|
|
221
|
+
return cast(Any, output_type).model_validate(item)
|
|
222
|
+
|
|
223
|
+
if not isinstance(item, output_type):
|
|
224
|
+
raise Exception(
|
|
225
|
+
f"Expected result to be {output_type.__name__}, but got {type(item).__name__}"
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
return item
|
|
File without changes
|
|
@@ -1,17 +1,3 @@
|
|
|
1
|
-
[tool.black]
|
|
2
|
-
line-length = 100
|
|
3
|
-
target-version = ['py311']
|
|
4
|
-
exclude = '''
|
|
5
|
-
(
|
|
6
|
-
/(
|
|
7
|
-
| \.git
|
|
8
|
-
| \.pytest_cache
|
|
9
|
-
| pyproject.toml
|
|
10
|
-
| dist
|
|
11
|
-
)/
|
|
12
|
-
)
|
|
13
|
-
'''
|
|
14
|
-
|
|
15
1
|
[tool.pytest.ini_options]
|
|
16
2
|
minversion = "6.0"
|
|
17
3
|
addopts = "-ra -q --color=yes --cov=fhirpathpy --cov-report=xml"
|
|
@@ -40,17 +26,18 @@ classifiers = [
|
|
|
40
26
|
"Operating System :: OS Independent",
|
|
41
27
|
"Programming Language :: Python",
|
|
42
28
|
"Programming Language :: Python :: 3",
|
|
43
|
-
"Programming Language :: Python :: 3.8",
|
|
44
|
-
"Programming Language :: Python :: 3.9",
|
|
45
29
|
"Programming Language :: Python :: 3.10",
|
|
46
30
|
"Programming Language :: Python :: 3.11",
|
|
31
|
+
"Programming Language :: Python :: 3.12",
|
|
32
|
+
"Programming Language :: Python :: 3.13",
|
|
47
33
|
"Topic :: Internet :: WWW/HTTP",
|
|
48
34
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
35
|
+
"Typing :: Typed",
|
|
49
36
|
]
|
|
50
|
-
requires-python = ">=3.
|
|
37
|
+
requires-python = ">=3.10"
|
|
51
38
|
|
|
52
39
|
[project.optional-dependencies]
|
|
53
|
-
test = ["pytest==7.1.1", "pyyaml==5.4"]
|
|
40
|
+
test = ["pytest==7.1.1", "pyyaml==5.4", "pydantic==2.13.1"]
|
|
54
41
|
|
|
55
42
|
[project.urls]
|
|
56
43
|
Homepage = "https://github.com/beda-software/fhirpath-py"
|
|
@@ -60,17 +47,22 @@ Changelog = "https://github.com/beda-software/fhirpath-py/blob/master/CHANGELOG.
|
|
|
60
47
|
|
|
61
48
|
|
|
62
49
|
[tool.ruff]
|
|
63
|
-
target-version = "
|
|
50
|
+
target-version = "py310"
|
|
64
51
|
line-length = 100
|
|
65
|
-
include = ["
|
|
52
|
+
include = ["fhirpathpy/**/*.py", "tests/**/*.py"]
|
|
66
53
|
|
|
67
54
|
[tool.ruff.lint]
|
|
68
55
|
select = ["B", "F", "I", "E", "UP", "N", "PL", "PERF"]
|
|
69
|
-
# Black is responsible for E501
|
|
70
56
|
# N803/N806 is not relevant for us because we use camelCase for historical reasons
|
|
71
57
|
ignore = ["E501", "N803", "N806"]
|
|
72
58
|
unfixable = ["F401"]
|
|
73
59
|
|
|
60
|
+
[tool.mypy]
|
|
61
|
+
python_version = "3.10"
|
|
62
|
+
ignore_missing_imports = true
|
|
63
|
+
plugins = ["pydantic.mypy"]
|
|
64
|
+
|
|
65
|
+
|
|
74
66
|
[tool.autohooks]
|
|
75
67
|
mode = "pipenv"
|
|
76
|
-
pre-commit = ["autohooks.plugins.
|
|
68
|
+
pre-commit = ["autohooks.plugins.ruff.check", "autohooks.plugins.ruff.format"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|