Metadata-Version: 2.4
Name: mint-sdk
Version: 1.0.41
Summary: MINT Plugin SDK - Build analysis plugins for the MINT (Mass-spec INtegrated Toolkit) platform
Project-URL: Homepage, https://github.com/MorscherLab/MINT
Project-URL: Documentation, https://github.com/MorscherLab/MINT/tree/main/packages/sdk-python#readme
Project-URL: Repository, https://github.com/MorscherLab/MINT
Author-email: MorscherLab <morscher@chem.ethz.ch>
License-Expression: MIT
Classifier: Development Status :: 4 - Beta
Classifier: Framework :: FastAPI
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.12
Requires-Dist: fastapi>=0.109.0
Requires-Dist: httpx>=0.28.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: typer>=0.15.0
Provides-Extra: dev
Requires-Dist: aiosqlite>=0.19.0; extra == 'dev'
Requires-Dist: greenlet>=3.0.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
Requires-Dist: pytest>=7.0.0; extra == 'dev'
Requires-Dist: sqlmodel>=0.0.16; extra == 'dev'
Provides-Extra: local-db
Requires-Dist: aiosqlite>=0.19.0; extra == 'local-db'
Requires-Dist: greenlet>=3.0.0; extra == 'local-db'
Requires-Dist: sqlmodel>=0.0.16; extra == 'local-db'
Provides-Extra: s3
Requires-Dist: boto3>=1.34.0; extra == 's3'
Description-Content-Type: text/markdown

# MINT SDK (Python)

SDK for building analysis plugins that integrate with the MINT platform.

> **Full Documentation:** See the [comprehensive docs](../../docs/index.md) for detailed API reference and guides.
> - [API Reference](../../docs/python/api-reference.md)
> - [Plugin Development Guide](../../docs/python/plugin-guide.md)
> - [Exception Handling](../../docs/python/exceptions.md)

## Installation

```bash
# From PyPI (when published)
uv add mint-sdk

# From git
uv add git+https://github.com/MorscherLab/MINT#subdirectory=packages/sdk-python
```

## Quick Start

Create a plugin with the CLI:

```bash
mint init my-plugin --template analysis-basic
cd my-plugin
mint sdk generate
mint doctor --explain
mint dev
```

`mint sdk generate` writes the frontend contract and typed client from backend routes and Pydantic schemas, so Vue code can call plugin endpoints without hand-writing route prefixes or request/response types.
Use `mint docs contract` inside a plugin to inspect the generated endpoint and client-call contract without writing files.
Use `mint sdk generate --check --json` in CI or editor tasks when you need machine-readable drift status.
Use `mint doctor --json` for machine-readable project health checks and safe-fix status.
When adding backend pieces, pass `--generate` to supported `mint add` commands to refresh the generated client in the same step.

For R-backed analyses:

```bash
mint init drp-r --template r-analysis
# or add R support to an existing plugin:
mint add r-analysis drp-fit --page
mint doctor --r --explain
mint sdk generate
```

This creates an `RAnalysisBridge` service, FastAPI route, typed frontend composable, optional starter page, and a small `mint_bridge.R` helper for reading inputs, writing outputs, accessing the current experiment id, and writing analysis artifacts while keeping Python/Pydantic as the frontend contract source of truth.

For standard biology design data:

```bash
mint add data-template --list --json
mint docs template plate-map
mint add data-template plate-map --page
```

Built-in templates include `plate-map`, `sample-sheet`, `sample-prep`, `dose-response`, `calibration-curve`, `time-course`, `protocol-steps`, `assay-matrix`, `reagent-list`, `flow-cytometry-panel`, `instrument-run`, and `qpcr-plate`. Generated template routes expose schema/default endpoints and merge multiple templates under `design_data.templates`, so a plugin can combine plate layouts, sample metadata, sample prep, reagents, protocols, calibration curves, time courses, readout matrices, cytometry panels, instrument run queues, and qPCR plates without clobbering prior template data.

Use `create_template_collection()` / `save_template_collection()` when a backend route needs to persist a coordinated set of templates, and `load_template_collection()` when a route needs all envelopes stored for an experiment. Single-template `save_template()` / `load_template()` remains available for narrow routes.

`mint add data-template-pack <name> --page` generates those collection routes and the matching frontend composable for curated packs, so plugin authors can save a whole experiment design scaffold with one API call.

For experiment object files, let the platform choose local, S3, or OpenStack
Swift storage and keep only the returned reference in your experiment data.
Standalone plugin runs use a local store under
`~/.mint/plugins/<plugin-name>/objects`.

```python
class MyPlugin(AnalysisPlugin):
    async def initialize(self, context=None):
        self._context = context

    async def save_report(self, experiment_id: int, payload: bytes) -> dict:
        store = self.get_data_store(experiment_id)
        ref = await store.put_bytes(
            "reports/report.json",
            payload,
            content_type="application/json",
            metadata={"kind": "qc-report"},
        )
        return ref.to_dict()
```

The platform stores object bytes under `{server.dataPath}/objects` by default.
Admins can switch the object backend between `storage.objects.backend = "local"`
`"s3"`, and `"swift"` and can set `storage.objects.localPath` for local storage.
When the backend is S3, the same SDK calls write to `storage.s3.objectBucket`
under `storage.s3.objectPrefix`. When the backend is Swift, they write to
`storage.swift.objectContainer` under `storage.swift.objectPrefix`. The platform
owns endpoint, region, access key, secret key, session token, SSL, path-style,
Keystone auth URL, project/domain, and Swift password settings; saved
credentials are encrypted at rest and redacted from admin config responses. Use
Admin -> Configuration -> Object Storage to choose Local Path, S3 Bucket, or
OpenStack Swift, and the Test Connection button to validate provider access.
Isolated plugin uploads use multipart transfer for `put_file` / `put_fileobj`
instead of base64 JSON.

S3-compatible provider settings may also come from environment variables. The
platform reads endpoint/region names such as `MINT_S3_ENDPOINT_URL`,
`MINT_S3_REGION_NAME`, `S3_ENDPOINT_URL`, and `AWS_ENDPOINT_URL_S3`; credential
names such as `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and
`AWS_SESSION_TOKEN`; and MINT-specific `MINT_S3_*` /
`MINT_STORAGE__S3__*` variants for SSL and path-style addressing.
Native Swift settings may come from `MINT_SWIFT_*` /
`MINT_STORAGE__SWIFT__*` variables or standard OpenStack variables such as
`OS_AUTH_URL`, `OS_USERNAME`, `OS_PASSWORD`, `OS_PROJECT_NAME`,
`OS_USER_DOMAIN_NAME`, `OS_PROJECT_DOMAIN_NAME`, `OS_AUTH_VERSION`, and
`OS_REGION_NAME`.

Scripts can use `MINTClient.objects` for the same storage API by passing
`plugin_id` explicitly. Older `get_s3_connector()` code can pass
`experiment_id` to receive a compatibility adapter, but new plugins should call
`get_data_store()` directly.

At the Python layer, plugins implement the `AnalysisPlugin` interface:

```python
from mint_sdk import AnalysisPlugin, PluginMetadata, PluginCapabilities
from fastapi import APIRouter

router = APIRouter()

@router.get("/hello")
async def hello():
    return {"message": "Hello from my plugin!"}

class MyPlugin(AnalysisPlugin):
    @property
    def metadata(self) -> PluginMetadata:
        return PluginMetadata(
            name="My Plugin",
            version="1.0.0",
            description="My analysis plugin",
            analysis_type="metabolomics",
            routes_prefix="/my-plugin",
            capabilities=PluginCapabilities(
                requires_auth=True,
                requires_experiments=True,
            ),
        )

    def get_routers(self):
        return [(router, "")]

    async def initialize(self, context=None):
        self._context = context

    async def shutdown(self):
        pass
```

## Plugin Package Structure

```
mint-plugin-example/
├── pyproject.toml
├── README.md
└── src/mint_plugin_example/
    ├── __init__.py
    └── plugin.py
```

### pyproject.toml

```toml
[project]
name = "mint-plugin-example"
version = "1.0.0"
dependencies = ["mint-sdk>=1.0.0"]

[project.entry-points."mint.plugins"]
example = "mint_plugin_example.plugin:MyPlugin"

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["src/mint_plugin_example"]
```

The entry point `mint.plugins` is how the platform discovers your plugin.

## Platform Context

When running integrated with the platform, your plugin receives a `PlatformContext` that provides access to:

- Authentication dependencies (`get_current_user_dependency()`)
- Repositories for experiments, samples, users, etc.
- Platform configuration

```python
async def initialize(self, context=None):
    self._context = context
    if context:
        # Running integrated - use platform services
        self.experiment_repo = context.get_experiment_repository()
    else:
        # Running standalone
        pass
```

## Installation Commands

```bash
# Install from GitHub
uv add git+https://github.com/org/mint-plugin-example

# Install specific version
uv add git+https://github.com/org/mint-plugin-example@v1.0.0

# Install from PyPI
uv add mint-plugin-example

# Install local plugin for development
uv add --editable ./my-plugin
```
