Skip to content
Merged
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
2 changes: 0 additions & 2 deletions .env.test
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
PYTEST_PPRL_SERVICE_BASE_URL=
PYTEST_PPRL_SERVICE_VERSION=
PYTEST_BROKER_SERVICE_BASE_URL=
PYTEST_BROKER_SERVICE_VERSION=
32 changes: 30 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,20 @@ They follow the data models that are also used by the FABLE services themselves,
The following demonstrates the four main tasks of the `PPRLClient`: transformation, masking, matching and weight
estimation.

#### Getting the version of the PPRL service

```python
from fable_client import PPRLClient

client = PPRLClient(base_url="http://localhost:8080")

print(client.version)
```

```text
0.3.0
```

#### Entity transformation

```python
Expand Down Expand Up @@ -258,6 +272,20 @@ The following demonstrates the five main tasks of the `BrokerClient`: creating s
sessions, submitting vectors from different clients and fetching matching results. For further explanation read the
documentation of the [Broker service repository](https://github.com/ul-mds/fable-broker).

#### Getting the version of the Broker service

```python
from fable_client import BrokerClient

client = BrokerClient(base_url="http://localhost:8081")

print(client.version)
```

```text
0.9.0
```

#### Creating a session

```python
Expand Down Expand Up @@ -709,9 +737,9 @@ These variables can be defined in `.env` or `.env.test`.
| **Environment variable** | **Description** | **Default** |
|---------------------------------------------|-------------------------------------------------------------------------------|-------------|
| PYTEST_PPRL_SERVICE_BASE_URL<sup>1)</sup> | Base URL for the FABLE PPRL service | |
| PYTEST_PPRL_SERVICE_VERSION | Tag of the FABLE PPRL service image that will run inside the test container | |
| PYTEST_PPRL_SERVICE_VERSION | Tag of the FABLE PPRL service image that will run inside the test container | latest |
| PYTEST_BROKER_SERVICE_BASE_URL<sup>1)</sup> | Base URL for the FABLE Broker service | |
| PYTEST_BROKER_SERVICE_VERSION | Tag of the FABLE Broker service image that will run inside the test container | |
| PYTEST_BROKER_SERVICE_VERSION | Tag of the FABLE Broker service image that will run inside the test container | latest |

<sup>1)</sup> If defined, pytest will not spin up a test container.

Expand Down
10 changes: 9 additions & 1 deletion fable_client/_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
EntityMaskResponse,
EntityTransformRequest,
EntityTransformResponse,
ServiceBaseInformation,
SessionCreationRequest,
SessionCreationResponse,
SessionDeletionRequest,
Expand Down Expand Up @@ -40,7 +41,7 @@ class ValidationErrorResponse(BaseModel):

class FableError(httpx.HTTPError):
def __init__(
self, message: str, request: httpx.Request, error: GenericErrorResponse | ValidationErrorResponse = None
self, message: str, request: httpx.Request, error: GenericErrorResponse | ValidationErrorResponse | None = None
):
super().__init__(message)
self._request = request
Expand Down Expand Up @@ -121,6 +122,13 @@ def _request(

return model_out.model_validate(r.json())

@property
def version(self) -> str:
r = self._client.get("")
r.raise_for_status()

return ServiceBaseInformation(**r.json()).version


class PPRLClient(BaseClient):
def match(self, request: VectorMatchRequest) -> VectorMatchResponse:
Expand Down
2 changes: 1 addition & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "fable-client"
version = "0.7.0"
version = "0.8.0"
description = "HTTP-based client for interacting with the FABLE services for privacy-preserving record linkage with Bloom filters."
authors = [
{name = "Maximilian Jugl"},
Expand Down Expand Up @@ -70,5 +70,6 @@ dev = [
"pytest-cov (>=7.1.0,<8.0.0)",
"pre-commit (>=4.6.1,<5.0.0)",
"readme-coverage-badger (>=1.1.0,<2.0.0)",
"ruff (>=0.16.0,<0.17.0)"
"ruff (>=0.16.0,<0.17.0)",
"docker (>=7.2.0,<8.0.0)"
]
25 changes: 19 additions & 6 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import uuid
from random import Random

import docker
import httpx2 as httpx
import pytest
from testcontainers.core.container import DockerContainer
Expand Down Expand Up @@ -34,10 +35,14 @@ def pprl_base_url(network, pprl_service_use_testcontainer):
yield os.environ["PYTEST_PPRL_SERVICE_BASE_URL"]
return

pprl_service_tag = os.environ["PYTEST_PPRL_SERVICE_VERSION"]
pprl_service_tag = os.environ.get("PYTEST_PPRL_SERVICE_VERSION", "latest")
image = f"ghcr.io/ul-mds/fable-pprl-service:{pprl_service_tag}"

if pprl_service_tag == "latest":
docker.from_env().images.pull(image)

container = (
DockerContainer(f"ghcr.io/ul-mds/fable-pprl-service:{pprl_service_tag}")
DockerContainer(image)
.with_exposed_ports(8080)
.waiting_for(LogMessageWaitStrategy("Application startup complete"))
.with_env("ROLE", "both")
Expand Down Expand Up @@ -116,13 +121,17 @@ def broker_worker(
):
if broker_service_use_testcontainer:
network_alias = "broker-worker"
broker_service_tag = os.environ["PYTEST_BROKER_SERVICE_VERSION"]
broker_service_tag = os.environ.get("PYTEST_BROKER_SERVICE_VERSION", "latest")
image = f"ghcr.io/ul-mds/fable-broker:{broker_service_tag}"

if pprl_service_use_testcontainer:
pprl_base_url = "http://matcher:8080"

if broker_service_tag == "latest":
docker.from_env().images.pull(image)

container = (
DockerContainer(f"ghcr.io/ul-mds/fable-broker:{broker_service_tag}")
DockerContainer(image)
.with_command(["celery", "-A", "fable_broker.worker.celery", "worker", "--loglevel", "INFO"])
.with_network(network)
.with_network_aliases(network_alias)
Expand Down Expand Up @@ -153,13 +162,17 @@ def broker_base_url(
yield os.environ["PYTEST_BROKER_SERVICE_BASE_URL"]
return

broker_service_tag = os.environ["PYTEST_BROKER_SERVICE_VERSION"]
broker_service_tag = os.environ.get("PYTEST_BROKER_SERVICE_VERSION", "latest")
image = f"ghcr.io/ul-mds/fable-broker:{broker_service_tag}"

if pprl_service_use_testcontainer:
pprl_base_url = "http://matcher:8080"

if broker_service_tag == "latest":
docker.from_env().images.pull(image)

container = (
DockerContainer(f"ghcr.io/ul-mds/fable-broker:{broker_service_tag}")
DockerContainer(image)
.with_command(
[
"uvicorn",
Expand Down
5 changes: 5 additions & 0 deletions tests/test_broker_client.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import time

import httpx2
import pytest
from fable_model import (
ClientResultRequest,
Expand Down Expand Up @@ -97,3 +98,7 @@ def _wait_for_matching_to_finish():
assert r.finished

assert_eventually(_wait_for_matching_to_finish)


def test_version(broker_base_url, broker_client):
assert broker_client.version == httpx2.get(broker_base_url).json()["version"]
5 changes: 5 additions & 0 deletions tests/test_pprl_client.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import httpx2
import pytest
from fable_model import (
BitVectorEntity,
Expand Down Expand Up @@ -95,3 +96,7 @@ def test_mask(pprl_client, uuid4_factory, faker):

assert len(entities) == len(r.entities)
assert input_ids == output_ids


def test_version(pprl_base_url, pprl_client):
assert pprl_client.version == httpx2.get(pprl_base_url).json()["version"]