Skip to content

Repository files navigation

PyPI Python Versions Code Coverage License Conventional Commits

MOSAIC Client

The mosaic_client library provides wrappers around the SOAP (Simple Object Access Protocol) interfaces of E-PIX and gPAS by the THS Greifswald. The main entrypoints are mosaic_client.EPIXClient and mosaic_client.GPASClient, which are classes that simply take the URLs to the WSDL endpoints of their respective services and expose functions to interact with these services. Both client classes are implemented as Zeep clients while validation is leveraged by marshmallow.

Installation

To install the client, Python 3.11 or higher is required.

pip install mosaic-python-client

Getting started

Both E-PIX and gPAS client can be either instantiated by passing the WSDL URLs as strings or by passing your own zeep.Client instance. This section briefly demonstrates the usage of both clients. For more information, have a look at the clients available methods and the respective docstrings.

E-PIX client

As a very first step, we need to instantiate the client. EPIXClient expects a WSDL URL for the regular E-PIX service which enables operations like requesting an MPI (Master Patient Index) or deactivating/deleting identities and a WSDL URL for the management service which leverages the management of domains.

from mosaic_client import EPIXClient

epix = EPIXClient(
    client="http://localhost:8081/epix/epixService?wsdl",
    management_client="http://localhost:8081/epix/epixManagementService?wsdl",
)

To be able to request an MPI, we first need to create a data domain where the identity we want an MPI for is saved. We name that new data domain default. Note that E-PIX comes with a data source named dummy_safe_source and an identifier domain named MPI by default.

from mosaic_client import EPIXClient
from mosaic_client.epix import Domain

epix = EPIXClient(
    client="http://localhost:8081/epix/epixService?wsdl",
    management_client="http://localhost:8081/epix/epixManagementService?wsdl",
)

epix.add_domain(
    domain=Domain(
        name="default",
        label="default",
        mpi_domain=epix.get_identifier_domain(identifier_domain_name="MPI"),
        safe_source=epix.get_source(source_name="dummy_safe_source"),
    )
)

Now, it is possible to request an MPI for an identity. The default configuration of a data domain assumes that first and last name, gender and birthdate are required for new identities.

from dataclasses import asdict
import datetime
import json
from mosaic_client import EPIXClient
from mosaic_client.epix import Identity

epix = EPIXClient(
    client="http://localhost:8081/epix/epixService?wsdl",
    management_client="http://localhost:8081/epix/epixManagementService?wsdl",
)

mpi_response = epix.request_mpi(
    domain_name="default",
    source_name="dummy_safe_source",
    identity=Identity(
        first_name="Foo",
        last_name="Bar",
        gender="f",
        birth_date=datetime.datetime(1970, 1, 1, tzinfo=datetime.UTC),
    ),
)

print(json.dumps(asdict(mpi_response), indent=2, default=str))
{
  "match_status": "NO_MATCH",
  "person": {
    "deactivated": false,
    "mpi_id": {
      "value": "1001000000011",
      "identifier_domain": {
        "name": "MPI",
        "label": "MPI",
        "oid": "1.2.276.0.76.3.1.132.1.1.1",
        "description": null,
        "entry_date": "2026-09-29 15:57:00.492000+02:00",
        "update_date": "2026-09-29 15:57:00.492000+02:00"
      },
      "entry_date": "2026-09-29 15:57:43.496000+02:00",
      "description": "generated MPI id",
      "fresh": false
    },
    "person_created": "2026-09-29 15:57:43.496000+02:00",
    "person_id": 1,
    "person_last_edited": "2026-09-29 15:57:43.496000+02:00",
    "other_identities": [],
    "reference_identity": {
      "birth_date": "1970-01-01 01:00:00+01:00",
      "birth_place": null,
      "civil_status": null,
      "degree": null,
      "external_date": null,
      "first_name": "Foo",
      "gender": "F",
      "identifiers": [],
      "last_name": "Bar",
      "middle_name": null,
      "mother_tongue": null,
      "mothers_maiden_name": null,
      "nationality": null,
      "vital_status": null,
      "death_date": null,
      "prefix": null,
      "race": null,
      "religion": null,
      "suffix": null,
      "value_1": null,
      "value_2": null,
      "value_3": null,
      "value_4": null,
      "value_5": null,
      "value_6": null,
      "value_7": null,
      "value_8": null,
      "value_9": null,
      "value_10": null,
      "contacts": [],
      "deactivated": false,
      "identity_created": "2026-09-29 15:57:43.496000+02:00",
      "identity_id": 1,
      "identity_last_edited": "2026-09-29 15:57:43.496000+02:00",
      "identity_version": 1,
      "person_id": 1,
      "source": {
        "name": "dummy_safe_source",
        "description": "dummy because of the default-property \"safe_source\" in table domain",
        "label": "dummy_safe_source",
        "entry_date": "2026-09-29 15:57:00.531000+02:00",
        "update_date": "2026-09-29 15:57:00.531000+02:00"
      }
    },
    "domain_name": "default"
  },
  "mpi_error_code": null
}

gPAS client

As before, we first need to instantiate the client. GPASClient expects a WSDL URL for the regular gPAS service which enables operations like creating pseudonyms and a WSDL URL for the domain service which leverages the management of domains.

from mosaic_client import GPASClient

gpas = GPASClient(
    client="http://localhost:8080/gpas/gpasService?wsdl",
    domain_client="http://localhost:8080/gpas/DomainService?wsdl",
)

To be able to create pseudonyms, we first need to create a new domain since pseudonyms are organized in domains. We name that new domain default.

from mosaic_client import GPASClient
from mosaic_client.gpas import Domain

gpas = GPASClient(
    client="http://localhost:8080/gpas/gpasService?wsdl",
    domain_client="http://localhost:8080/gpas/DomainService?wsdl",
)

gpas.add_domain(domain=Domain(name="default", label="default"))

Now, we are able to create a new pseudonym for the value value123.

from mosaic_client import GPASClient

gpas = GPASClient(
    client="http://localhost:8080/gpas/gpasService?wsdl",
    domain_client="http://localhost:8080/gpas/DomainService?wsdl",
)

pseudonym = gpas.get_or_create_pseudonym_for(domain_name="default", value="value123")

print(f"Pseudonym: {pseudonym}")
Pseudonym: 199799437

Running tests

This library implements its tests via pytest. In order to run integration tests, a running instance of E-PIX and gPAS are needed. The first option is to spin up the services independently and direct pytest to it. Have a look at the provided docker compose file ./tests/docker/docker-compose.yml for a quick solution. For more sophisticated deployments, please read the documentation of E-PIX and gPAS. Alternatively, pytest can start Docker test-containers for the duration of the test run. Since containers are started and stopped for each run individually, such a test run takes more time.

The following table shows all available options to configure pytest.

Environment variable Description Default
PYTEST_USE_TESTCONTAINERS Whether pytest should use test-containers or not 0
PYTEST_EPIX_WSDL_URL1) WSDL URL for the E-PIX service
PYTEST_EPIX_MANAGEMENT_WSDL_URL1) WSDL URL for the E-PIX management service
PYTEST_EPIX_IMAGE_TAG2) E-PIX image tag that is used for the test-container latest
PYTEST_GPAS_WSDL_URL1) WSDL URL for the gPAS service
PYTEST_GPAS_DOMAIN_WSDL_URL1) WSDL URL for the gPAS domain service
PYTEST_GPAS_IMAGE_TAG2) gPAS image tag that is used for the test-container latest

1) Only needed, if PYTEST_USE_TESTCONTAINERS is set to 0.
2) Only used, if PYTEST_USE_TESTCONTAINERS is set to 1.

It is possible to define these variables in a .env.test file. The .env.example file provides a template. You can copy the content of .env.example to directly get started with pytest using test-containers.

cp .env.example .env.test

License

MIT.

About

Zeep client for interacting with the SOAP interfaces provided by E-PIX and gPAS of the MOSAIC suite by the THS Greifswald.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages