Metadata-Version: 2.4
Name: cyantic
Version: 0.1.5
Summary: Use Pydantic to build complex types from simple parameters.
Project-URL: Homepage, https://github.com/flywhl/cyantic
Project-URL: Repository, https://github.com/flywhl/cyantic
Project-URL: Documentation, https://github.com/flywhl/cyantic#readme
Project-URL: Bug Tracker, https://github.com/flywhl/cyantic/issues
Author-email: Rory Byrne <rory@rory.bio>
License-Expression: Apache-2.0
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Information Technology
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: pydantic>=2.10.3
Description-Content-Type: text/markdown

<p align="center">
  <img src="https://github.com/user-attachments/assets/6004aee7-0a64-4cc4-a7aa-b6790fedccc7">
</p>

> The cyanotype process, which gave birth to the blueprint, uses iron salts and UV light to transform ordinary paper into deep Prussian blue prints.

## Features

Cyantic lets you build complex types from simple blueprints, using Pydantic.

* Build complex objects using intermediate Pydantic models.
* Reference other values using `@value:x.y.z`
* Import objects using `@import:x.y.z`
* Define custom `@reftag` handlers (see tests)

## Installation

* `uv add cyantic`

## Usage

```python
from cyantic import Blueprint, blueprint, CyanticModel
from torch import Tensor
import torch
import yaml

# 1. Create and register some useful parameterisations
#       (or soon install from PyPi, i.e. `rye add cyantic-torch`)

@blueprint(Tensor)
class NormalTensor(Blueprint[Tensor]):

    mean: float
    std: float
    size: tuple[int, ...]

    def build(self) -> Tensor:
        return torch.normal(self.mean, self.std, size=self.size)

@blueprint(Tensor)
class UniformTensor(Blueprint[Tensor]):
    low: float
    high: float
    size: tuple[int, ...]

    def build(self) -> Tensor:
      return torch.empty(self.size).uniform_(self.low, self.high)


# 2. Write pydantic models using `CyanticModel` base class

class MyModel(CyanticModel):
    normal_tensor: Tensor
    uniform_tensor: Tensor


# 3. Validate from YAML files that specify the parameterisation

some_yaml = """common:
    size: [3, 5]
normal_tensor:
    mean: 0.0
    std: 0.1
    size: @value:common.size
uniform_tensor:
    low: -1.0
    std: 1.0
    size: @value:common.size
"""

# 4. Receive objects built from the parameterisations.

my_model = MyModel.model_validate(yaml.safe_load(some_yaml))
assert isinstance(my_model.normal_tensor, Tensor)
assert isinstance(my_model.uniform_tensor, Tensor)
```


## Development

* `git clone https://github.com/flywhl/cyantic.git`
* `cd cyantic`
* `uv sync`
* `just test`

## Flywheel

Science needs humble software tools. [Flywheel](https://flywhl.dev/) is an open source collective building simple tools to preserve scientific momentum, inspired by devtools and devops culture.
