Metadata-Version: 2.4
Name: ptal-api
Version: 0.18.3.0
Summary: TALISMAN API adapter
Keywords: Talisman,adapter,Talisman API,GraphQL
Author: Matvey Zvantsov
Author-email: zvancov.mu@ispras.ru
Maintainer: Matvey Zvantsov
Maintainer-email: zvancov.mu@ispras.ru
Requires-Python: >=3.12,<4
Classifier: Development Status :: 3 - Alpha
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Requires-Dist: graphql-core (>=3.2.6,<3.3)
Requires-Dist: httpx (>=0.28.1,<1)
Requires-Dist: pydantic (>=2.0.0,<3.0.0)
Requires-Dist: pyjwt (>=2.10.1,<3)
Requires-Dist: python-keycloak (>=5.8.1,<6)
Description-Content-Type: text/markdown

# 📦 ptal‑api Repository Documentation

> **tl;dr** This repository provides a Python client library (`ptal_api`) for interacting with the Talisman GraphQL
> APIs, along with a generator script that automatically creates type‑safe client code from GraphQL schemas.

---

## Table of Contents

1. [What the repository contains](#what-the-repository-contains)
2. [Prerequisites](#prerequisites)
3. [Installation (as a library)](#installation-as-a-library)
4. [Project layout](#project-layout)
5. [Generating API client code](#generating-api-client-code)
6. [Using the generated client](#using-the-generated-client)
7. [Example snippets](#example-snippets)
8. [Testing](#testing)
9. [Code Style](#code-style)

---

## What the repository contains

| Directory / File                        | Purpose                                                                                                                                |
|-----------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------|
| `ptal_api/`                             | Core package that ships the runtime client (`Client`), authentication providers, and generated schema modules.                         |
| `ptal_api/schemas/`                     | Destination for the generated GraphQL operation classes (`mesh_schema`, `system_utils_schema`, …).                                     |
| `generator_script/`                     | Helper utilities that turn GraphQL introspection files into ready‑to‑use Python modules.                                               |
| `generator_script/generate_script.py`   | Orchestrates the whole generation pipeline: runs **ariadne‑codegen**, moves files, patches imports, and cleans the code with **Ruff**. |
| `generator_script/async_base_client.py` | Base async client class shared by all generated modules.                                                                               |
| `generator_script/toml_configs/`        | Ariadne‑codegen configuration (`*.toml`) for each API.                                                                                 |
| `examples/`                             | Small, ready‑to‑run scripts showing how to use the client (adapter usage, mutation, query, raw execution).                             |
| `tests/`                                | Test suite for the library.                                                                                                            |
| `pyproject.toml` / `poetry.lock`        | Poetry‑managed project metadata and dependencies.                                                                                      |
| `README.md` (this file)                 | High‑level documentation (you are reading it!).                                                                                        |
| `CHANGELOG.md`                          | Change history.                                                                                                                        |

---

## Prerequisites

| Tool                      | Minimum version                      | Why you need it                                                                         |
|---------------------------|--------------------------------------|-----------------------------------------------------------------------------------------|
| **Python**                | `3.12+`                              | Required for the async‑first design and the `typing` features used throughout the code. |
| **Poetry**                | `2.0+`                               | Manages the virtual environment and project dependencies.                               |
| **ariadne‑codegen**       | latest (install via `pip` or Poetry) | Generates the type‑safe GraphQL client modules from schema files.                       |
| **ruff**                  | latest (install via `pip` or Poetry) | Auto‑formatter and lint fixer applied to generated code.                                |
| **httpx**                 | any                                  | Underlying HTTP client used by the generated `Client`.                                  |
| **keycloak** (optional)   | any                                  | Required if you plan to use the `KeycloakAuthProvider`.                                 |
| **websockets** (optional) | any                                  | Needed only for GraphQL subscriptions.                                                  |

Install everything with Poetry:

```bash
poetry install
```

Or, if you prefer plain `pip`:

```bash
pip install ariadne-codegen ruff httpx keycloak websockets
```

---

## Installation (as a library)

Once the generated schemas exist (see the *Generating API client code* section), you can install the package locally for
development:

```bash
# From the repository root
poetry build
poetry install
```

Or use it directly from the source tree:

```bash
pip install -e .
```

---

## Project layout

```
ptal-api/
│
├─ ptal_api/
│   ├─ __init__.py
│   ├─ client.py                # High‑level GraphQL client wrapper
│   ├─ auth_provider.py         # Abstract authentication base class
│   ├─ keycloak_provider.py     # Keycloak‑based auth implementation
│   ├─ no_auth_provider.py      # No‑auth placeholder
│   ├─ schemas/                 # ← generated GraphQL modules
│   │   ├─ mesh_schema/
│   │   └─ system_utils_schema/
│   └─ ...                      # Additional utilities
│
├─ generator_script/
│   ├─ async_base_client.py     # Shared async client base class
│   ├─ generate_script.py       # Main generation entry point
│   └─ toml_configs/
│       ├─ mesh.toml
│       └─ system_utils.toml
│
├─ examples/
│   ├─ adapter_usage.py
│   ├─ cancel_job.py
│   ├─ get_periodic_job.py
│   └─ raw_execute.py
│
├─ tests/                       # pytest test suite
│
├─ .gitlab-ci.yml               # CI pipeline definition
├─ pyproject.toml               # Poetry project definition
├─ poetry.lock
└─ README.md                    # (this file)
```

### Key modules

| Module                                                | What it provides                                                                          |
|-------------------------------------------------------|-------------------------------------------------------------------------------------------|
| `ptal_api.client.Client`                              | Thin wrapper around `httpx.AsyncClient` that knows how to send GraphQL queries/mutations. |
| `ptal_api.auth_provider.AuthProvider`                 | Abstract base class for authentication providers.                                         |
| `ptal_api.keycloak_provider.KeycloakAuthProvider`     | Implements `AuthProvider` using Keycloak OIDC token flow.                                 |
| `ptal_api.no_auth_provider.NoAuthProvider`            | Simple provider returning empty headers (useful for public APIs).                         |
| `ptal_api.adapter.TalismanAPIAdapter` *(in examples)* | Convenience wrapper around the generated client exposing higher‑level domain methods.     |

---

## Generating API client code

The repository ships a **generator script** that automates the entire workflow for the two GraphQL APIs (`mesh` and
`system_utils`). The script:

1. **Validates** that it runs from the correct directory.
2. Calls **ariadne‑codegen** with the appropriate TOML configuration.
3. **Moves** the generated package into `ptal_api/schemas/`.
4. **Patches** imports so they point to the shared `ptal_api` package (`ptal_api.base_model`, `ptal_api.base_operation`,
   etc.).
5. Runs **Ruff** to format the code and fix lint issues.

### How to run it

```bash
cd ptal-api/generator_script
python generate_script.py
```

The script will output progress messages such as:

```
Generating mesh_schema
Ended generating mesh_schema
...
Generating system_utils_schema
Ended generating system_utils_schema

... (ruff output) ...
```

When it finishes, you’ll find the generated Python modules under:

```
ptal_api/schemas/mesh_schema/
ptal_api/schemas/system_utils_schema/
```

> **Note** – If you add a new schema, create a matching `*.toml` file in `generator_script/toml_configs/` and extend the
`apis` tuple in `generate_script.py`.

---

## Using the generated client

Below is a minimal example that shows how to set up a client with Keycloak authentication and execute a simple query.

```python
import os
import asyncio

from ptal_api.client import Client
from ptal_api.auth_providers import KeycloakAuthProvider
from ptal_api.schemas.mesh_schema.custom_queries import Query as MeshQuery
from ptal_api.schemas.mesh_schema.custom_fields import DocumentFields


async def main() -> None:
    auth = KeycloakAuthProvider(
        auth_url=os.getenv("KEYCLOAK_URL"),
        realm=os.getenv("KEYCLOAK_REALM"),
        client_id=os.getenv("KEYCLOAK_CLIENT_ID"),
        client_secret=os.getenv("KEYCLOAK_CLIENT_SECRET"),
        user=os.getenv("KEYCLOAK_USER"),
        password=os.getenv("KEYCLOAK_PASSWORD"),
    )

    client = Client(url=os.getenv("GRAPHQL_URL"), auth_provider=auth)

    # Example: fetch a document by ID
    document_query = MeshQuery.document(id="12345")
    document_query.fields(
        DocumentFields.id,
        DocumentFields.title,
        DocumentFields.document_content_type,
    )

    response = await client.query(document_query, operation_name="GetDocument")
    print(response)


if __name__ == "__main__":
    asyncio.run(main())
```

### Quick tips

| Situation                         | What to do                                                                                                               |
|-----------------------------------|--------------------------------------------------------------------------------------------------------------------------|
| **No auth required**              | Use `NoAuthProvider()` when constructing `Client`.                                                                       |
| **Custom headers**                | Subclass `AuthProvider` and return the desired `Headers`.                                                                |
| **Subscriptions**                 | Ensure `websockets` is installed and pass a `ws://` endpoint to `Client`.                                                |
| **Adding new GraphQL operations** | Edit the schema, regenerate with the script, and import the new generated classes under `ptal_api.schemas.<api>_schema`. |

---

## Example snippets

The `examples/` directory contains ready‑to‑run scripts that illustrate common patterns:

| File                  | Description                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------|
| `adapter_usage.py`    | Shows how to obtain a `TalismanAPIAdapter` and call a high‑level method (`get_document`).                                              |
| `cancel_job.py`       | Demonstrates a mutation (`CancelJob`) with custom fields.                                                                              |
| `get_periodic_job.py` | Queries a periodic job using a chain of nested field selections.                                                                       |
| `raw_execute.py`      | Shows the low‑level `client.execute()` call for cases where the generated helpers are insufficient (not recommended for everyday use). |

You can run any example with:

```bash
cd examples
poetry run python <example_name>.py
```

Remember to set the required environment variables (`GRAPHQL_URL`, `KEYCLOAK_*`, etc.) beforehand.

---

## Testing

The repository ships a pytest‑based test suite under `tests/`. To execute it locally:

```bash
poetry run pytest
```

The CI pipeline (see next section) runs the same command on every merge request, ensuring that new changes keep the
library stable.

## Code Style

* Follow the existing formatting (auto‑formatted by Ruff).
* Keep import statements absolute (`from ptal_api.base_model import …`).
* Prefer async functions and `await` wherever possible.

---

