Metadata-Version: 2.1
Name: alchemista
Version: 0.1.1
Summary: Tools to convert SQLAlchemy models to Pydantic models
Home-page: https://github.com/ggabriel96/alchemista
License: MIT
Author: Gabriel Galli
Author-email: ggabriel96@hotmail.com
Requires-Python: >=3.6.2,<4.0.0
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Requires-Dist: SQLAlchemy (>=1.4.14,<2.0.0)
Requires-Dist: importlib-metadata (>=1.6.0,<4.0.0); python_version < "3.8"
Requires-Dist: pydantic (>=1.8.1,<2.0.0)
Project-URL: Repository, https://github.com/ggabriel96/alchemista
Description-Content-Type: text/markdown

# Alchemista

[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![codecov](https://codecov.io/gh/ggabriel96/alchemista/branch/main/graph/badge.svg?token=MYXKIH09FJ)](https://codecov.io/gh/ggabriel96/alchemista)

Tools to generate Pydantic models from SQLAlchemy models.

Still experimental.

## Installation

Alchemista is [available in PyPI](https://pypi.org/project/alchemista/).
To install it with `pip`, run:


```shell
pip install alchemista
```

## Usage

Simply call the `sqlalchemy_to_pydantic` function with a SQLAlchemy model.
Each `Column` in its definition will result in an attribute of the generated model via the Pydantic `Field` function.

For example, a SQLAlchemy model like the following

```python
from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import declarative_base


Base = declarative_base()

class PersonDB(Base):
    __tablename__ = "people"

    id = Column(Integer, primary_key=True)
    age = Column(Integer, default=0, nullable=False, doc="Age in years")
    name = Column(String(128), nullable=False, doc="Full name")
```

could have a generated Pydantic model via

```python
from alchemista import sqlalchemy_to_pydantic

Person = sqlalchemy_to_pydantic(PersonDB)
```

and would result in a Pydantic model equivalent to

```python
from pydantic import BaseModel, Field


class Person(BaseModel):
    id: int
    age: int = Field(0, description="Age in years")
    name: str = Field(..., max_length=128, description="Full name")

    class Config:
        orm_mode = True
```

Note that the string length from the column definition was sufficient to add a `max_length` constraint.
Additionally, by default, the generated model will have `orm_mode=True`.
That can be customized via the `config` keyword argument.
There is also an `exclude` keyword argument that accepts a set of field names to _not_ include in the generated model.

This example is available in a short executable form in the [`examples/`](examples/) directory.

## `Field` arguments and `info`

Currently, the type, default value (either scalar or callable), and the description (from the `doc` attribute) are
extracted directly from the `Column` definition.
However, except for the type, all of them can be overridden via the `info` dictionary attribute.
All other custom arguments to the `Field` function are specified there too.
The supported keys are listed in `alchemista.field.Info`.

**Everything specified in `info` is preferred from what has been extracted from `Column`**.
This means that the default value and the description can be **overridden** if so desired.
Also, similarly to using Pydantic directly, `default` and `default_factory` are mutually-exclusive,
so they cannot be used together.
Use `default_factory` if the default value comes from calling a function (without any arguments).

For example, in the case above,

```python
name = Column(String(128), nullable=False, doc="Full name", info=dict(description=None, max_length=64))
```

would instead result in

```python
name: str = Field(..., max_length=64)
```

## License

This project is licensed under the terms of the MIT license.

