Skip to content

Commit 6b309bd

Browse files
authored
Merge pull request #70 from projkov/master
Add support for fhir_code, fhir_url and fhir_resource
2 parents db20fc8 + b7598e7 commit 6b309bd

File tree

13 files changed

+174
-46
lines changed

13 files changed

+174
-46
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.1.15
2+
3+
- Add compliance_params (fhirCore, fhirUrl, fhirResource) as operation parameter
4+
15
## 0.1.14
26

37
- Fix db innitialization crash for fhirschema

Pipfile

+1-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ autohooks-plugin-ruff = "~=23.11.0"
2020
autohooks-plugin-black = "~=23.7.0"
2121
coloredlogs = "*"
2222
ruff = "*"
23-
24-
# dependencies for python 3.8
2523
exceptiongroup = "~=1.2.1"
2624
tomli = "~=2.0.1"
2725
async-timeout = "~=4.0.3"
26+
fhirpathpy = "==2.0.0"

Pipfile.lock

+49-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

aidbox_python_sdk/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
__title__ = "aidbox-python-sdk"
2-
__version__ = "0.1.14"
2+
__version__ = "0.1.15"
33
__author__ = "beda.software"
44
__license__ = "None"
55
__copyright__ = "Copyright 2024 beda.software"

aidbox_python_sdk/sdk.py

+4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import asyncio
22
import logging
3+
from typing import Optional
34

45
import jsonschema
56
from fhirpy.base.exceptions import OperationOutcome
67

78
from .aidboxpy import AsyncAidboxClient
89
from .db_migrations import sdk_migrations
10+
from .types import Compliance
911

1012
logger = logging.getLogger("aidbox_sdk")
1113

@@ -151,6 +153,7 @@ def operation( # noqa: PLR0913
151153
access_policy=None,
152154
request_schema=None,
153155
timeout=None,
156+
compliance: Optional[Compliance] = None,
154157
):
155158
if public and access_policy is not None:
156159
raise ValueError("Operation might be public or have access policy, not both")
@@ -184,6 +187,7 @@ def wrapped_func(operation, request):
184187
"method": method,
185188
"path": path,
186189
**({"timeout": timeout} if timeout else {}),
190+
**(compliance if compliance else {}),
187191
}
188192
self._operation_handlers[operation_id] = wrapped_func
189193
if public is True:

aidbox_python_sdk/types.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1-
from typing import Any
1+
from typing import Any, List
22

33
from aiohttp import web
44
from typing_extensions import TypedDict
55

6+
class Compliance(TypedDict, total=True):
7+
fhirUrl: str
8+
fhirCode: str
9+
fhirResource: List[str]
10+
611
SDKOperationRequest = TypedDict(
712
"SDKOperationRequest",
813
{"app": web.Application, "params": dict, "route-params": dict, "headers": dict, "resource": Any},

docker-compose.yaml

+23-40
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,42 @@
11
version: '3.1'
22
services:
3-
devbox-db:
4-
image: "healthsamurai/aidboxdb:14.5"
3+
aidbox-db:
4+
image: "healthsamurai/aidboxdb:16.1"
5+
env_file:
6+
- ./envs/db
57
ports:
6-
- "5434:5432"
7-
environment:
8-
POSTGRES_USER: postgres
9-
POSTGRES_PASSWORD: postgres
10-
POSTGRES_DB: devbox
11-
devbox:
12-
image: "healthsamurai/aidboxone:latest"
8+
- 5432:5432
9+
healthcheck:
10+
test: ["CMD", "pg_isready", "-U", "postgres"]
11+
interval: 5s
12+
timeout: 5s
13+
retries: 10
14+
aidbox:
15+
image: ${AIDBOX_PROJECT_IMAGE}
16+
build: example/aidbox-project/
1317
depends_on:
14-
- devbox-db
15-
links:
16-
- "devbox-db:database"
17-
ports:
18-
- "8080:8080"
18+
aidbox-db:
19+
condition: service_healthy
1920
env_file:
20-
- env_tests
21+
- ./envs/aidbox
2122
environment:
22-
PGHOST: database
23-
PGDATABASE: devbox
24-
PGPORT: 5432
25-
PGUSER: postgres
26-
PGPASSWORD: postgres
27-
AIDBOX_CONFIG: /var/config/config.edn
2823
AIDBOX_LICENSE: ${AIDBOX_LICENSE}
29-
volumes:
30-
- ./config:/var/config
31-
devbox-healthcheck:
32-
image: curlimages/curl
33-
entrypoint: /bin/sleep 10000
34-
links:
35-
- devbox
36-
depends_on:
37-
- devbox
3824
healthcheck:
39-
test: curl --fail http://devbox:8080/__healthcheck || exit 1
40-
interval: 1s
41-
timeout: 20s
42-
retries: 100
25+
test: curl --fail http://localhost:8080/health || exit 1
26+
interval: 5s
27+
timeout: 30s
28+
retries: 50
4329
app:
4430
build:
4531
context: .
4632
args:
4733
PYTHON_VERSION: ${PYTHON:-3.11}
4834
command: ["pipenv", "run", "pytest"]
4935
depends_on:
50-
devbox-healthcheck:
51-
condition:
52-
service_healthy
53-
links:
54-
- devbox
36+
aidbox:
37+
condition: service_healthy
5538
env_file:
56-
- env_tests
39+
- ./envs/backend
5740
ports:
5841
- "8081:8081"
5942
volumes:

envs/aidbox

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
AIDBOX_STDOUT_PRETTY=all
2+
AIDBOX_CLIENT_ID=root
3+
AIDBOX_CLIENT_SECRET=secret
4+
AIDBOX_BASE_URL=http://aidbox:8080
5+
AIDBOX_PORT=8080
6+
AIDBOX_FHIR_VERSION=4.0.0
7+
8+
PGHOST=aidbox-db
9+
PGPORT=5432
10+
PGDATABASE=aidbox-tests
11+
PGUSER=postgres
12+
PGPASSWORD=postgres
13+
14+
BOX_PROJECT_GIT_TARGET__PATH=/aidbox-project
15+
AIDBOX_ZEN_PATHS=path:package-dir:/aidbox-project
16+
AIDBOX_ZEN_ENTRYPOINT=main/box
17+
AIDBOX_DEV_MODE=false
18+
AIDBOX_ZEN_DEV_MODE=false
19+
AIDBOX_COMPLIANCE=enabled

envs/backend

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
APP_INIT_CLIENT_ID=root
2+
APP_INIT_CLIENT_SECRET=secret
3+
APP_INIT_URL=http://aidbox:8080
4+
5+
APP_ID=backend-test
6+
APP_SECRET=secret
7+
APP_URL=http://backend:8081
8+
APP_PORT=8081
9+
AIO_PORT=8081
10+
AIO_HOST=0.0.0.0

envs/db

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
POSTGRES_USER=postgres
2+
POSTGRES_PASSWORD=postgres
3+
POSTGRES_DB=aidbox-tests

main.py

+12
Original file line numberDiff line numberDiff line change
@@ -160,3 +160,15 @@ async def db_tests(request):
160160
result = await db.alchemy(statement)
161161
logging.debug("Result:\n%s", result)
162162
return web.json_response({})
163+
164+
165+
@sdk.operation(
166+
["POST"],
167+
["Observation", "observation-custom-op"],
168+
compliance={
169+
"fhirCode": "observation-custom-op",
170+
"fhirUrl": "http://test.com",
171+
"fhirResource": ["Observation"],
172+
})
173+
async def observation_custom_op(operation, request):
174+
return {"message": "Observation custom operation response"}

run_test.sh

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1-
#!/bin/bash
1+
#!/bin/sh
22

3+
if [ -f "envs/aidbox" ]; then
4+
export `cat envs/aidbox`
5+
fi
6+
7+
if [ -z "${AIDBOX_LICENSE}" ]; then
8+
echo "AIDBOX_LICENSE is required to run tests"
9+
exit 1
10+
fi
11+
12+
13+
docker compose -f docker-compose.yaml pull --quiet
314
docker compose -f docker-compose.yaml up --exit-code-from app app
15+
16+
exit $?

tests/test_sdk.py

+28
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,38 @@
33
from unittest import mock
44

55
import pytest
6+
from fhirpathpy import evaluate
67

78
import main
89

910

11+
@pytest.mark.asyncio
12+
@pytest.mark.parametrize(
13+
("expression", "expected"),
14+
[
15+
(
16+
"CapabilityStatement.rest.operation.where(definition='http://test.com').count()",
17+
1,
18+
),
19+
(
20+
"CapabilityStatement.rest.operation.where(definition='http://test.com').first().name",
21+
"observation-custom-op",
22+
),
23+
(
24+
"CapabilityStatement.rest.resource.where(type='Observation').operation.where(definition='http://test.com').count()",
25+
1,
26+
),
27+
(
28+
"CapabilityStatement.rest.resource.where(type='Observation').operation.where(definition='http://test.com').first().name",
29+
"observation-custom-op",
30+
),
31+
],
32+
)
33+
async def test_operation_with_compliance_params(aidbox_client, expression, expected):
34+
response = await aidbox_client.execute("fhir/metadata", method="GET")
35+
assert evaluate(response, expression, {})[0] == expected
36+
37+
1038
@pytest.mark.asyncio()
1139
async def test_health_check(client):
1240
resp = await client.get("/health")

0 commit comments

Comments
 (0)