Metadata-Version: 2.4
Name: ocean-runner
Version: 0.3.4
Summary: A fluent API for OceanProtocol algorithms
Project-URL: Homepage, https://github.com/AgrospAI/ocean-runner
Project-URL: Issues, https://github.com/AgrospAI/ocean-runner/issues
Author-email: AgrospAI <agrospai@udl.cat>, Christian López <christian.lopez@udl.cat>
License: Copyright 2025 spin3l
        
        Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
License-File: LICENSE
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Requires-Python: >=3.10
Requires-Dist: aiofiles>=25.1.0
Requires-Dist: oceanprotocol-job-details>=0.4.2
Requires-Dist: pydantic-settings>=2.12.0
Requires-Dist: pydantic>=2.12.5
Requires-Dist: pytest>=8.4.2
Requires-Dist: returns[compatible-mypy]>=0.26.0
Description-Content-Type: text/markdown

# Ocean Runner

[![PyPI](https://img.shields.io/pypi/v/ocean-runner?label=pypi&style=flat-square)](https://pypi.org/project/ocean-runner/)
[![Coverage](https://raw.githubusercontent.com/agrospai/ocean-runner/main/coverage.svg)](https://github.com/agrospai/ocean-runner)

Ocean Runner is a package that eases algorithm creation in the scope of OceanProtocol.

## Installation

```bash
pip install ocean-runner
# or
uv add ocean-runner
```

## Usage

### Minimal Example

```python
import random
from ocean_runner import Algorithm

algorithm = Algorithm()


@algorithm.run
def run(_: Algorithm):
    return random.randint()


if __name__ == "__main__":
    algorithm()
```

This code snippet will:

- Read the OceanProtocol JobDetails from the environment variables and use default configuration file paths.
- Execute the run function.
- Execute the default saving function, storing the result in a "result.txt" file within the default outputs path.

### Tuning

#### Application Config

The application configuration can be tweaked by passing a Config instance to its constructor.

```python
from ocean_runner import Algorithm, Config

algorithm = Algorithm(
    Config(
        custom_input: ... # dataclass
        # Custom algorithm parameters dataclass.

        logger: ... # type: logging.Logger
        # Custom logger to use.

        source_paths: ... # type: Iterable[Path]
        # Source paths to include in the PATH

        environment: ...
        # type: ocean_runner.Environment. Mock of environment variables.
    )
)
```

```python
import logging

from pydantic import BaseModel
from ocean_runner import Algorithm, Config


class CustomInput(BaseModel):
    foobar: string


logger = logging.getLogger(__name__)


algorithm = Algorithm(
    Config(
        custom_input: CustomInput,
        """
        Load the Algorithm's Custom Input into a CustomInput instance.
        """

        source_paths: [Path("/algorithm/src")],
        """
        Source paths to include in the PATH. '/algorithm/src' is the default since our templates place the algorithm source files there.
        """

        logger: logger,
        """
        Custom logger to use in the Algorithm.
        """

        environment: Environment(
            base_dir: "./_data",
            """
            Custom data path to use test data.
            """

            dids: '["17feb697190d9f5912e064307006c06019c766d35e4e3f239ebb69fb71096e42"]',
            """
            Dataset DID.
            """

            transformation_did: "1234",
            """
            Random transformation DID to use while testing.
            """

            secret: "1234",
            """
            Random secret to use while testing.
            """
        )
        """
        Should not be needed in production algorithms, used to mock environment variables, defaults to using env.
        """
    )
)

```

#### Behaviour Config

To fully configure the behaviour of the algorithm as in the [Minimal Example](#minimal-example), you can do it decorating your defined function as in the following example, which features all the possible algorithm customization.

```python
from pathlib import Path

import pandas as pd
from ocean_runner import Algorithm

algorithm = Algorithm()


@algorithm.on_error
def error_callback(algorithm: Algorithm, ex: Exception):
    algorithm.logger.exception(ex)
    raise algorithm.Error() from ex


@algorithm.validate
def val(algorithm: Algorithm):
    assert algorithm.job_details.files, "Empty input dir"


@algorithm.run
def run(algorithm: Algorithm) -> pd.DataFrame:
    _, filename = next(algorithm.job_details.inputs())
    return pd.read_csv(filename).describe(include="all")


@algorithm.save_results
def save(algorithm: Algorithm, result: pd.DataFrame, base: Path):
    algorithm.logger.info(f"Descriptive statistics: {result}")
    result.to_csv(base / "result.csv")


if __name__ == "__main__":
    algorithm()
```

### Default implementations

As seen in the minimal example, all methods implemented in `Algorithm` have a default implementation which will be commented here.

```python
.validate()

    """
    Will validate the algorithm's job detail instance, checking for the existence of:
    - `job_details.ddos`
    - `job_details.files`
    """

.run()

    """
    Has NO default implementation, must pass a callback that returns a result of any type.
    """

.save_results()

    """
    Stores the result of running the algorithm in "outputs/results.txt"
    """
```

### Job Details

To load the OceanProtocol JobDetails instance, the program will read some environment variables, they can be mocked passing an instance of `Environment` through the configuration of the algorithm.

Environment variables:

- `DIDS` (optional) Input dataset(s) DID's, must have format: `["abc..90"]`. Defaults to reading them automatically from the `DDO` data directory.
- `TRANSFORMATION_DID` (optional, default="DEFAULT"): Algorithm DID, must have format: `abc..90`.
- `SECRET` (optional, default="DEFAULT"): Algorithm secret.
- `BASE_DIR` (optional, default="/data"): Base path to the OceanProtocol data directories.
