dirigent-fhir 0.29.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.
Files changed (25) hide show
  1. dirigent_fhir-0.29.0/LICENSE +15 -0
  2. dirigent_fhir-0.29.0/PKG-INFO +64 -0
  3. dirigent_fhir-0.29.0/README.md +47 -0
  4. dirigent_fhir-0.29.0/pyproject.toml +121 -0
  5. dirigent_fhir-0.29.0/pyproject.toml.orig +93 -0
  6. dirigent_fhir-0.29.0/src/dirigent_fhir/__init__.py +79 -0
  7. dirigent_fhir-0.29.0/src/dirigent_fhir/client.py +317 -0
  8. dirigent_fhir-0.29.0/src/dirigent_fhir/connection.py +200 -0
  9. dirigent_fhir-0.29.0/src/dirigent_fhir/create.py +38 -0
  10. dirigent_fhir-0.29.0/src/dirigent_fhir/limits.py +145 -0
  11. dirigent_fhir-0.29.0/src/dirigent_fhir/messages.py +86 -0
  12. dirigent_fhir-0.29.0/src/dirigent_fhir/py.typed +0 -0
  13. dirigent_fhir-0.29.0/src/dirigent_fhir/r4.py +212 -0
  14. dirigent_fhir-0.29.0/src/dirigent_fhir/read.py +54 -0
  15. dirigent_fhir-0.29.0/src/dirigent_fhir/references.py +139 -0
  16. dirigent_fhir-0.29.0/src/dirigent_fhir/search.py +92 -0
  17. dirigent_fhir-0.29.0/src/dirigent_fhir/shelves/fhir/README.md +26 -0
  18. dirigent_fhir-0.29.0/src/dirigent_fhir/shelves/fhir/fhir-copy-on-schedule.yaml +91 -0
  19. dirigent_fhir-0.29.0/src/dirigent_fhir/shelves/fhir/fhir-create-if-none-exist.yaml +44 -0
  20. dirigent_fhir-0.29.0/src/dirigent_fhir/shelves/fhir/fhir-read.yaml +49 -0
  21. dirigent_fhir-0.29.0/src/dirigent_fhir/shelves/fhir/fhir-search-paged.yaml +45 -0
  22. dirigent_fhir-0.29.0/src/dirigent_fhir/shelves/fhir/fhir-update-by-identifier.yaml +46 -0
  23. dirigent_fhir-0.29.0/src/dirigent_fhir/transaction.py +189 -0
  24. dirigent_fhir-0.29.0/src/dirigent_fhir/update.py +49 -0
  25. dirigent_fhir-0.29.0/src/dirigent_fhir/writes.py +57 -0
@@ -0,0 +1,15 @@
1
+ Copyright (c) 2026 Morten Olav Hansen <morten@winterop.com>. All rights reserved.
2
+
3
+ This source code and accompanying documentation are the property of
4
+ Morten Olav Hansen. No license, express or implied, is granted to use, copy,
5
+ modify, merge, publish, distribute, sublicense, or sell copies of this
6
+ software or its derivatives.
7
+
8
+ The source is published for reference only. Any use beyond reading
9
+ requires written permission from the copyright holder.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
13
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT.
14
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES,
15
+ OR OTHER LIABILITY ARISING FROM THE USE OF THE SOFTWARE.
@@ -0,0 +1,64 @@
1
+ Metadata-Version: 2.4
2
+ Name: dirigent-fhir
3
+ Version: 0.29.0
4
+ Summary: The FHIR pack for dirigent: a connection kind and the REST blocks for one FHIR server.
5
+ License-Expression: LicenseRef-Proprietary
6
+ License-File: LICENSE
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Programming Language :: Python :: 3.13
9
+ Requires-Dist: dhis2w-fhir-engine>=1.38.2,<2
10
+ Requires-Dist: dirigent-common==0.29.0
11
+ Requires-Dist: dirigent-plugin==0.29.0
12
+ Requires-Dist: httpx2>=2.12.0
13
+ Requires-Python: >=3.13
14
+ Project-URL: Documentation, https://winterop-com.github.io/dirigent-fhir/
15
+ Project-URL: Repository, https://github.com/winterop-com/dirigent-fhir
16
+ Description-Content-Type: text/markdown
17
+
18
+ # dirigent-fhir
19
+
20
+ The FHIR pack for [dirigent](https://github.com/winterop-com/dirigent). It contributes the `fhir`
21
+ connection kind and the REST blocks for one FHIR R4 server:
22
+
23
+ | Block | Effect | What it does |
24
+ | --- | --- | --- |
25
+ | `fhir.read` | reads | Reads one resource by type and id. |
26
+ | `fhir.search` | reads | Searches one type, following `Bundle.link[next]` on the connection's origin under a page cap. |
27
+ | `fhir.create` | writes | Creates a resource, conditionally with `ifNoneExist`. |
28
+ | `fhir.update` | writes | Updates a resource with a conditional update on its identifier, never on a source server's id. |
29
+ | `fhir.transaction` | writes | Writes many resources in one transaction or batch Bundle, references between them rewritten to `urn:uuid` entries. |
30
+
31
+ It is FHIR as a system of its own, not a DHIS2 pack: FHIR to FHIR is as much its purpose as
32
+ feeding DHIS2. Between steps a resource or a Bundle is plain FHIR JSON. Inside a block the R4
33
+ models of `dhis2w-fhir-engine` type what they cover, and a resource they do not model passes
34
+ through as JSON. A server's `OperationOutcome` fails the step classified by its status and its
35
+ issue types, so a `transient` or `throttled` issue is retried and an `invalid` one is not.
36
+
37
+ Documentation: the [`docs/`](docs/) directory, built with `uv run mkdocs build --strict`.
38
+
39
+ ## Install
40
+
41
+ The pack is not on PyPI yet. Install it from a checkout:
42
+
43
+ ```bash
44
+ uv add /path/to/dirigent-fhir
45
+ ```
46
+
47
+ An instance discovers the pack by installing it: the `dirigent.plugins.v1` entry point in
48
+ `pyproject.toml` is the whole registration.
49
+
50
+ ## Develop
51
+
52
+ ```bash
53
+ uv sync
54
+ uv run ruff format --check . && uv run ruff check .
55
+ uv run mypy && uv run pyright
56
+ uv run pytest -m "not live"
57
+ uv run mkdocs build --strict
58
+ ```
59
+
60
+ The tests are offline: every block runs against a fake FHIR server in `tests/fhirserver.py`, and
61
+ the response bounds against a hostile server on loopback. `tests/test_fhir_live.py` reads a real
62
+ server with `DIRIGENT_LIVE=1 FHIR_LIVE_URL=http://localhost:8090/fhir`.
63
+
64
+ The pack follows dirigent's version: 0.29.0 is built against dirigent 0.29.0.
@@ -0,0 +1,47 @@
1
+ # dirigent-fhir
2
+
3
+ The FHIR pack for [dirigent](https://github.com/winterop-com/dirigent). It contributes the `fhir`
4
+ connection kind and the REST blocks for one FHIR R4 server:
5
+
6
+ | Block | Effect | What it does |
7
+ | --- | --- | --- |
8
+ | `fhir.read` | reads | Reads one resource by type and id. |
9
+ | `fhir.search` | reads | Searches one type, following `Bundle.link[next]` on the connection's origin under a page cap. |
10
+ | `fhir.create` | writes | Creates a resource, conditionally with `ifNoneExist`. |
11
+ | `fhir.update` | writes | Updates a resource with a conditional update on its identifier, never on a source server's id. |
12
+ | `fhir.transaction` | writes | Writes many resources in one transaction or batch Bundle, references between them rewritten to `urn:uuid` entries. |
13
+
14
+ It is FHIR as a system of its own, not a DHIS2 pack: FHIR to FHIR is as much its purpose as
15
+ feeding DHIS2. Between steps a resource or a Bundle is plain FHIR JSON. Inside a block the R4
16
+ models of `dhis2w-fhir-engine` type what they cover, and a resource they do not model passes
17
+ through as JSON. A server's `OperationOutcome` fails the step classified by its status and its
18
+ issue types, so a `transient` or `throttled` issue is retried and an `invalid` one is not.
19
+
20
+ Documentation: the [`docs/`](docs/) directory, built with `uv run mkdocs build --strict`.
21
+
22
+ ## Install
23
+
24
+ The pack is not on PyPI yet. Install it from a checkout:
25
+
26
+ ```bash
27
+ uv add /path/to/dirigent-fhir
28
+ ```
29
+
30
+ An instance discovers the pack by installing it: the `dirigent.plugins.v1` entry point in
31
+ `pyproject.toml` is the whole registration.
32
+
33
+ ## Develop
34
+
35
+ ```bash
36
+ uv sync
37
+ uv run ruff format --check . && uv run ruff check .
38
+ uv run mypy && uv run pyright
39
+ uv run pytest -m "not live"
40
+ uv run mkdocs build --strict
41
+ ```
42
+
43
+ The tests are offline: every block runs against a fake FHIR server in `tests/fhirserver.py`, and
44
+ the response bounds against a hostile server on loopback. `tests/test_fhir_live.py` reads a real
45
+ server with `DIRIGENT_LIVE=1 FHIR_LIVE_URL=http://localhost:8090/fhir`.
46
+
47
+ The pack follows dirigent's version: 0.29.0 is built against dirigent 0.29.0.
@@ -0,0 +1,121 @@
1
+ [project]
2
+ name = "dirigent-fhir"
3
+ version = "0.29.0"
4
+ description = "The FHIR pack for dirigent: a connection kind and the REST blocks for one FHIR server."
5
+ readme = "README.md"
6
+ requires-python = ">=3.13"
7
+ license = "LicenseRef-Proprietary"
8
+ license-files = ["LICENSE"]
9
+ classifiers = [
10
+ "Programming Language :: Python :: 3",
11
+ "Programming Language :: Python :: 3.13",
12
+ ]
13
+ dependencies = [
14
+ "dhis2w-fhir-engine>=1.38.2,<2",
15
+ "dirigent-common==0.29.0",
16
+ "dirigent-plugin==0.29.0",
17
+ "httpx2>=2.12.0",
18
+ ]
19
+
20
+ [project.urls]
21
+ Documentation = "https://winterop-com.github.io/dirigent-fhir/"
22
+ Repository = "https://github.com/winterop-com/dirigent-fhir"
23
+
24
+ [project.entry-points."dirigent.plugins.v1"]
25
+ fhir = "dirigent_fhir:plugin"
26
+
27
+ [dependency-groups]
28
+ dev = [
29
+ "dirigent-testing==0.29.0",
30
+ "mkdocs>=1.6.1",
31
+ "mkdocs-material>=9.7.7",
32
+ "mypy>=1.19",
33
+ "pymdown-extensions>=11.0.2",
34
+ "pyright>=1.1",
35
+ "pytest>=8",
36
+ "pytest-asyncio>=0.24",
37
+ "pyyaml>=6",
38
+ "ruff>=0.16",
39
+ "types-pyyaml>=6",
40
+ ]
41
+
42
+ [build-system]
43
+ requires = ["uv_build>=0.12.0,<0.14.0"]
44
+ build-backend = "uv_build"
45
+
46
+ [tool.pytest.ini_options]
47
+ asyncio_mode = "auto"
48
+ asyncio_default_fixture_loop_scope = "function"
49
+ testpaths = ["tests"]
50
+ markers = ["live: reaches a real FHIR server; opt in with DIRIGENT_LIVE=1 and FHIR_LIVE_URL"]
51
+
52
+ [tool.ruff]
53
+ target-version = "py313"
54
+ line-length = 120
55
+ src = [
56
+ "src",
57
+ "tests",
58
+ ]
59
+
60
+ [tool.ruff.lint]
61
+ select = [
62
+ "E",
63
+ "W",
64
+ "F",
65
+ "I",
66
+ "D",
67
+ "SIM",
68
+ "UP",
69
+ "B",
70
+ "TID",
71
+ ]
72
+
73
+ [tool.ruff.lint.per-file-ignores]
74
+ "tests/**" = [
75
+ "D103",
76
+ "D100",
77
+ "D101",
78
+ "D102",
79
+ "D104",
80
+ ]
81
+
82
+ [tool.ruff.lint.pydocstyle]
83
+ convention = "google"
84
+
85
+ [tool.ruff.lint.isort]
86
+ known-first-party = [
87
+ "dirigent_common",
88
+ "dirigent_fhir",
89
+ "dirigent_plugin",
90
+ "dirigent_testing",
91
+ ]
92
+
93
+ [tool.ruff.format]
94
+ quote-style = "double"
95
+ docstring-code-format = true
96
+
97
+ [tool.mypy]
98
+ python_version = "3.13"
99
+ disallow_untyped_defs = true
100
+ warn_return_any = true
101
+ warn_unused_configs = true
102
+ warn_redundant_casts = true
103
+ warn_unused_ignores = true
104
+ no_implicit_optional = true
105
+ strict_equality = true
106
+ plugins = ["pydantic.mypy"]
107
+ files = [
108
+ "src",
109
+ "tests",
110
+ ]
111
+ mypy_path = ["tests"]
112
+
113
+ [tool.pyright]
114
+ pythonVersion = "3.13"
115
+ typeCheckingMode = "strict"
116
+ include = [
117
+ "src",
118
+ "tests",
119
+ ]
120
+ extraPaths = ["tests"]
121
+ reportMissingTypeStubs = false
@@ -0,0 +1,93 @@
1
+ [project]
2
+ name = "dirigent-fhir"
3
+ version = "0.29.0"
4
+ description = "The FHIR pack for dirigent: a connection kind and the REST blocks for one FHIR server."
5
+ readme = "README.md"
6
+ requires-python = ">=3.13"
7
+ license = "LicenseRef-Proprietary"
8
+ license-files = ["LICENSE"]
9
+ classifiers = [
10
+ "Programming Language :: Python :: 3",
11
+ "Programming Language :: Python :: 3.13",
12
+ ]
13
+ dependencies = [
14
+ "dhis2w-fhir-engine>=1.38.2,<2",
15
+ "dirigent-common==0.29.0",
16
+ "dirigent-plugin==0.29.0",
17
+ "httpx2>=2.12.0",
18
+ ]
19
+
20
+ [project.urls]
21
+ Documentation = "https://winterop-com.github.io/dirigent-fhir/"
22
+ Repository = "https://github.com/winterop-com/dirigent-fhir"
23
+
24
+ [project.entry-points."dirigent.plugins.v1"]
25
+ fhir = "dirigent_fhir:plugin"
26
+
27
+ [dependency-groups]
28
+ dev = [
29
+ "dirigent-testing==0.29.0",
30
+ "mkdocs>=1.6.1",
31
+ "mkdocs-material>=9.7.7",
32
+ "mypy>=1.19",
33
+ "pymdown-extensions>=11.0.2",
34
+ "pyright>=1.1",
35
+ "pytest>=8",
36
+ "pytest-asyncio>=0.24",
37
+ "pyyaml>=6",
38
+ "ruff>=0.16",
39
+ "types-pyyaml>=6",
40
+ ]
41
+
42
+ [build-system]
43
+ requires = ["uv_build>=0.12.0,<0.14.0"]
44
+ build-backend = "uv_build"
45
+
46
+ [tool.pytest.ini_options]
47
+ asyncio_mode = "auto"
48
+ asyncio_default_fixture_loop_scope = "function"
49
+ testpaths = ["tests"]
50
+ markers = [
51
+ "live: reaches a real FHIR server; opt in with DIRIGENT_LIVE=1 and FHIR_LIVE_URL",
52
+ ]
53
+
54
+ [tool.ruff]
55
+ target-version = "py313"
56
+ line-length = 120
57
+ src = ["src", "tests"]
58
+
59
+ [tool.ruff.lint]
60
+ select = ["E", "W", "F", "I", "D", "SIM", "UP", "B", "TID"]
61
+
62
+ [tool.ruff.lint.per-file-ignores]
63
+ "tests/**" = ["D103", "D100", "D101", "D102", "D104"]
64
+
65
+ [tool.ruff.lint.pydocstyle]
66
+ convention = "google"
67
+
68
+ [tool.ruff.lint.isort]
69
+ known-first-party = ["dirigent_common", "dirigent_fhir", "dirigent_plugin", "dirigent_testing"]
70
+
71
+ [tool.ruff.format]
72
+ quote-style = "double"
73
+ docstring-code-format = true
74
+
75
+ [tool.mypy]
76
+ python_version = "3.13"
77
+ disallow_untyped_defs = true
78
+ warn_return_any = true
79
+ warn_unused_configs = true
80
+ warn_redundant_casts = true
81
+ warn_unused_ignores = true
82
+ no_implicit_optional = true
83
+ strict_equality = true
84
+ plugins = ["pydantic.mypy"]
85
+ files = ["src", "tests"]
86
+ mypy_path = ["tests"]
87
+
88
+ [tool.pyright]
89
+ pythonVersion = "3.13"
90
+ typeCheckingMode = "strict"
91
+ include = ["src", "tests"]
92
+ extraPaths = ["tests"]
93
+ reportMissingTypeStubs = false
@@ -0,0 +1,79 @@
1
+ """The FHIR pack: the ``fhir`` connection kind and the REST blocks for one FHIR server."""
2
+
3
+ from collections.abc import Sequence
4
+ from importlib.resources import files
5
+ from importlib.resources.abc import Traversable
6
+
7
+ from dirigent_fhir.client import FhirClient
8
+ from dirigent_fhir.connection import FhirConnectionConfig, FhirConnectionKind, build_client, client_for
9
+ from dirigent_fhir.create import FhirCreateConfig, FhirCreateOperator
10
+ from dirigent_fhir.messages import FHIR
11
+ from dirigent_fhir.r4 import FhirIssue
12
+ from dirigent_fhir.read import FhirReadConfig, FhirReadOperator, FhirReadOutput
13
+ from dirigent_fhir.search import FhirSearchConfig, FhirSearchOperator, FhirSearchOutput
14
+ from dirigent_fhir.transaction import (
15
+ FhirEntryResult,
16
+ FhirTransactionConfig,
17
+ FhirTransactionOperator,
18
+ FhirTransactionOutput,
19
+ )
20
+ from dirigent_fhir.update import FhirUpdateConfig, FhirUpdateOperator
21
+ from dirigent_fhir.writes import FhirWriteOutput
22
+ from dirigent_plugin import Contribution, extension
23
+
24
+ #: The directory the pack's example shelves live in, inside this distribution.
25
+ SHELVES_DIRECTORY = "shelves"
26
+
27
+
28
+ class FhirPlugin:
29
+ """The plugin object the host discovers under the dirigent.plugins.v1 entry-point group."""
30
+
31
+ @extension
32
+ def contribute(self) -> Contribution:
33
+ """Contribute the FHIR blocks and the ``fhir`` connection kind they are configured from."""
34
+ return Contribution(
35
+ operators=[
36
+ FhirReadOperator(),
37
+ FhirSearchOperator(),
38
+ FhirCreateOperator(),
39
+ FhirUpdateOperator(),
40
+ FhirTransactionOperator(),
41
+ ],
42
+ connection_kinds=[FhirConnectionKind()],
43
+ labels=[FHIR],
44
+ )
45
+
46
+ @extension
47
+ def examples(self) -> Sequence[Traversable]:
48
+ """Contribute the example shelves this distribution carries."""
49
+ return [files(__package__ or "dirigent_fhir") / SHELVES_DIRECTORY]
50
+
51
+
52
+ plugin = FhirPlugin()
53
+
54
+ __all__ = [
55
+ "SHELVES_DIRECTORY",
56
+ "FhirClient",
57
+ "FhirConnectionConfig",
58
+ "FhirConnectionKind",
59
+ "FhirCreateConfig",
60
+ "FhirCreateOperator",
61
+ "FhirEntryResult",
62
+ "FhirIssue",
63
+ "FhirPlugin",
64
+ "FhirReadConfig",
65
+ "FhirReadOperator",
66
+ "FhirReadOutput",
67
+ "FhirSearchConfig",
68
+ "FhirSearchOperator",
69
+ "FhirSearchOutput",
70
+ "FhirTransactionConfig",
71
+ "FhirTransactionOperator",
72
+ "FhirTransactionOutput",
73
+ "FhirUpdateConfig",
74
+ "FhirUpdateOperator",
75
+ "FhirWriteOutput",
76
+ "build_client",
77
+ "client_for",
78
+ "plugin",
79
+ ]