advanced-alchemy


Nameadvanced-alchemy JSON
Version 0.9.0 PyPI version JSON
download
home_pageNone
SummaryReady-to-go SQLAlchemy concoctions.
upload_time2024-04-07 18:53:52
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseMIT
keywords alembic fastapi flask litestar sanic sqlalchemy
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Advanced Alchemy

<div align="center">

| Project   |     | Status                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| --------- | :-- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| CI/CD     |     | [![Latest Release](https://github.com/jolt-org/advanced-alchemy/actions/workflows/publish.yaml/badge.svg)](https://github.com/jolt-org/advanced-alchemy/actions/workflows/publish.yaml) [![Tests And Linting](https://github.com/jolt-org/advanced-alchemy/actions/workflows/ci.yaml/badge.svg)](https://github.com/jolt-org/advanced-alchemy/actions/workflows/ci.yaml) [![Documentation Building](https://github.com/jolt-org/advanced-alchemy/actions/workflows/docs.yaml/badge.svg)](https://github.com/jolt-org/advanced-alchemy/actions/workflows/docs.yaml)                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| Quality   |     | [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=jolt-org_advanced-alchemy&metric=coverage)](https://sonarcloud.io/summary/new_code?id=jolt-org_advanced-alchemy) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=jolt-org_advanced-alchemy&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=jolt-org_advanced-alchemy) [![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=jolt-org_advanced-alchemy&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=jolt-org_advanced-alchemy) [![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=jolt-org_advanced-alchemy&metric=reliability_rating)](https://sonarcloud.io/summary/new_code?id=jolt-org_advanced-alchemy) [![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=jolt-org_advanced-alchemy&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=jolt-org_advanced-alchemy)                            |
| Community |     | [![Discord](https://img.shields.io/discord/1149784127659319356?labelColor=F50057&color=202020&label=chat%20on%20discord&logo=discord&logoColor=202020)](https://discord.gg/XpFNTjjtTK)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| Meta      |     | [![Jolt Project](https://img.shields.io/badge/Jolt%20Org-%E2%AD%90-F50057.svg?logo=python&labelColor=F50057&color=202020&logoColor=202020)](https://github.com/jolt-org/) [![types - Mypy](https://img.shields.io/badge/types-Mypy-F50057.svg?logo=python&labelColor=F50057&color=202020&logoColor=202020)](https://github.com/python/mypy) [![License - MIT](https://img.shields.io/badge/license-MIT-F50057.svg?logo=python&labelColor=F50057&color=202020&logoColor=202020)](https://spdx.org/licenses/) [![Jolt Sponsors](https://img.shields.io/badge/Sponsor-%E2%9D%A4-%23202020.svg?&logo=github&logoColor=202020&labelColor=F50057)](https://github.com/sponsors/jolt-org) [![linting - Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json&labelColor=F50057)](https://github.com/astral-sh/ruff) [![code style - Black](https://img.shields.io/badge/code%20style-black-000000.svg?logo=python&labelColor=F50057&logoColor=202020)](https://github.com/psf/black) |

</div>

Check out the [project documentation][project-docs] 📚 for more information.

## About

A carefully crafted, thoroughly tested, optimized companion library for SQLAlchemy,
offering features such as:

- Sync and async repositories, featuring common CRUD and highly optimized bulk operations
- Integration with major web frameworks including Litestar, Starlette, FastAPI, Sanic.
- Custom-built alembic configuration and CLI with optional framework integration
- Utility base classes with audit columns, primary keys and utility functions
- Optimized JSON types including a custom JSON type for Oracle.
- Integrated support for UUID6 and UUID7 using [`uuid-utils`](https://github.com/aminalaee/uuid-utils) (install with the `uuid` extra)

- Pre-configured base classes with audit columns UUID or Big Integer primary keys and
  a [sentinel column](https://docs.sqlalchemy.org/en/20/core/connections.html#configuring-sentinel-columns).
- Synchronous and asynchronous repositories featuring:
  - Common CRUD operations for SQLAlchemy models
  - Bulk inserts, updates, upserts, and deletes with dialect-specific enhancements
  - [lambda_stmt](https://docs.sqlalchemy.org/en/20/core/sqlelement.html#sqlalchemy.sql.expression.lambda_stmt) when possible
    for improved query building performance
  - Integrated counts, pagination, sorting, filtering with `LIKE`, `IN`, and dates before and/or after.
- Tested support for multiple database backends including:

  - SQLite via [aiosqlite](https://aiosqlite.omnilib.dev/en/stable/) or [sqlite](https://docs.python.org/3/library/sqlite3.html)
  - Postgres via [asyncpg](https://magicstack.github.io/asyncpg/current/) or [psycopg3 (async or sync)](https://www.psycopg.org/psycopg3/)
  - MySQL via [asyncmy](https://github.com/long2ice/asyncmy)
  - Oracle via [oracledb (async or sync)](https://oracle.github.io/python-oracledb/) (tested on 18c and 23c)
  - Google Spanner via [spanner-sqlalchemy](https://github.com/googleapis/python-spanner-sqlalchemy/)
  - DuckDB via [duckdb_engine](https://github.com/Mause/duckdb_engine)
  - Microsoft SQL Server via [pyodbc](https://github.com/mkleehammer/pyodbc) or [aioodbc](https://github.com/aio-libs/aioodbc)
  - CockroachDB via [sqlalchemy-cockroachdb (async or sync)](https://github.com/cockroachdb/sqlalchemy-cockroachdb)

## Usage

### Installation

```shell
pip install advanced-alchemy
```

> [!IMPORTANT]\
> Check out [the installation guide][install-guide] in our official documentation!

### Repositories

Advanced Alchemy includes a set of asynchronous and synchronous repository classes for easy CRUD
operations on your SQLAlchemy models.

<details>
<summary>Click to expand the example</summary>

```python
from advanced_alchemy.base import UUIDBase
from advanced_alchemy.filters import LimitOffset
from advanced_alchemy.repository import SQLAlchemySyncRepository
from sqlalchemy import create_engine
from sqlalchemy.orm import Mapped, sessionmaker


class User(UUIDBase):
    # you can optionally override the generated table name by manually setting it.
    __tablename__ = "user_account"  # type: ignore[assignment]
    email: Mapped[str]
    name: Mapped[str]


class UserRepository(SQLAlchemySyncRepository[User]):
    """User repository."""

    model_type = User


# use any compatible sqlalchemy engine.
engine = create_engine("duckdb:///:memory:")
session_factory = sessionmaker(engine, expire_on_commit=False)

# Initializes the database.
with engine.begin() as conn:
    User.metadata.create_all(conn)

with session_factory() as db_session:
    repo = UserRepository(session=db_session)
    # 1) Create multiple users with `add_many`
    bulk_users = [
        {"email": 'cody@advanced-alchemy.dev', 'name': 'Cody'},
        {"email": 'janek@advanced-alchemy.dev', 'name': 'Janek'},
        {"email": 'peter@advanced-alchemy.dev', 'name': 'Peter'},
        {"email": 'jacob@advanced-alchemy.dev', 'name': 'Jacob'}
    ]
    objs = repo.add_many([User(**raw_user) for raw_user in bulk_users])
    db_session.commit()
    print(f"Created {len(objs)} new objects.")

    # 2) Select paginated data and total row count.  Pass additional filters as kwargs
    created_objs, total_objs = repo.list_and_count(LimitOffset(limit=10, offset=0), name="Cody")
    print(f"Selected {len(created_objs)} records out of a total of {total_objs}.")

    # 3) Let's remove the batch of records selected.
    deleted_objs = repo.delete_many([new_obj.id for new_obj in created_objs])
    print(f"Removed {len(deleted_objs)} records out of a total of {total_objs}.")

    # 4) Let's count the remaining rows
    remaining_count = repo.count()
    print(f"Found {remaining_count} remaining records after delete.")
```

</details>

For a full standalone example, see the sample [here][standalone-example]

### Services

Advanced Alchemy includes an additional service class to make working with a repository easier.
This class is designed to accept data as a dictionary or SQLAlchemy model,
and it will handle the type conversions for you.

<details>
<summary>Here's the same example from above but using a service to create the data:</summary>

```python
from advanced_alchemy.base import UUIDBase
from advanced_alchemy.filters import LimitOffset
from advanced_alchemy import SQLAlchemySyncRepository, SQLAlchemySyncRepositoryService
from sqlalchemy import create_engine
from sqlalchemy.orm import Mapped, sessionmaker


class User(UUIDBase):
    # you can optionally override the generated table name by manually setting it.
    __tablename__ = "user_account"  # type: ignore[assignment]
    email: Mapped[str]
    name: Mapped[str]


class UserRepository(SQLAlchemySyncRepository[User]):
    """User repository."""

    model_type = User


class UserService(SQLAlchemySyncRepositoryService[User]):
    """User repository."""

    repository_type = UserRepository


# use any compatible sqlalchemy engine.
engine = create_engine("duckdb:///:memory:")
session_factory = sessionmaker(engine, expire_on_commit=False)

# Initializes the database.
with engine.begin() as conn:
    User.metadata.create_all(conn)

with session_factory() as db_session:
    service = UserService(session=db_session)
    # 1) Create multiple users with `add_many`
    objs = service.create_many([
        {"email": 'cody@advanced-alchemy.dev', 'name': 'Cody'},
        {"email": 'janek@advanced-alchemy.dev', 'name': 'Janek'},
        {"email": 'peter@advanced-alchemy.dev', 'name': 'Peter'},
        {"email": 'jacob@advanced-alchemy.dev', 'name': 'Jacob'}
    ])
    print(objs)
    print(f"Created {len(objs)} new objects.")

    # 2) Select paginated data and total row count.  Pass additional filters as kwargs
    created_objs, total_objs = service.list_and_count(LimitOffset(limit=10, offset=0), name="Cody")
    print(f"Selected {len(created_objs)} records out of a total of {total_objs}.")

    # 3) Let's remove the batch of records selected.
    deleted_objs = service.delete_many([new_obj.id for new_obj in created_objs])
    print(f"Removed {len(deleted_objs)} records out of a total of {total_objs}.")

    # 4) Let's count the remaining rows
    remaining_count = service.count()
    print(f"Found {remaining_count} remaining records after delete.")
```

</details>

### Web Frameworks

Advanced Alchemy works with nearly all Python web frameworks.
Several helpers for popular libraries are included, and additional PRs to support others are welcomed.

#### Litestar

Advanced Alchemy is the official SQLAlchemy integration for Litestar.

In addition to installing with `pip install advanced-alchemy`,
it can also be installed as a Litestar extra with `pip install litestar[sqlalchemy]`.

<details>
<summary>Litestar Example</summary>

```python
from litestar import Litestar
from litestar.plugins.sqlalchemy import SQLAlchemyPlugin, SQLAlchemyAsyncConfig
# alternately...
# from advanced_alchemy.extensions.litestar.plugins import SQLAlchemyPlugin
# from advanced_alchemy.extensions.litestar.plugins.init.config import SQLAlchemyAsyncConfig

alchemy = SQLAlchemyPlugin(
  config=SQLAlchemyAsyncConfig(connection_string="sqlite+aiosqlite:///test.sqlite"),
)
app = Litestar(plugins=[alchemy])
```

</details>

For a full Litestar example, check [here][litestar-example]

#### FastAPI

<details>
<summary>FastAPI Example</summary>

```python
from fastapi import FastAPI

from advanced_alchemy.config import SQLAlchemyAsyncConfig
from advanced_alchemy.extensions.starlette import StarletteAdvancedAlchemy

app = FastAPI()
alchemy = StarletteAdvancedAlchemy(
    config=SQLAlchemyAsyncConfig(connection_string="sqlite+aiosqlite:///test.sqlite"), app=app,
)
```

</details>

For a full FastAPI example, see [here][fastapi-example]

#### Starlette

<details>
<summary>Pre-built Example Apps</summary>

```python
from starlette.applications import Starlette

from advanced_alchemy.config import SQLAlchemyAsyncConfig
from advanced_alchemy.extensions.starlette import StarletteAdvancedAlchemy

app = Starlette()
alchemy = StarletteAdvancedAlchemy(
    config=SQLAlchemyAsyncConfig(connection_string="sqlite+aiosqlite:///test.sqlite"), app=app,
)
```

</details>

#### Sanic

<details>
<summary>Pre-built Example Apps</summary>

```python
from sanic import Sanic
from sanic_ext import Extend

from advanced_alchemy.config import SQLAlchemyAsyncConfig
from advanced_alchemy.extensions.sanic import SanicAdvancedAlchemy

app = Sanic("AlchemySanicApp")
alchemy = SanicAdvancedAlchemy(
    sqlalchemy_config=SQLAlchemyAsyncConfig(connection_string="sqlite+aiosqlite:///test.sqlite"),
)
Extend.register(alchemy)
```

</details>

## Contributing

All [Jolt][jolt-org] projects will always be a community-centered, available for contributions of any size.

Before contributing, please review the [contribution guide][contributing].

If you have any questions, reach out to us on [Discord][discord], our org-wide [GitHub discussions][jolt-discussions] page,
or the [project-specific GitHub discussions page][project-discussions].

<hr>

<!-- markdownlint-disable -->
<p align="center">
  <!-- github-banner-start -->
  <img src="https://raw.githubusercontent.com/jolt-org/meta/2901c9c5c5895a83fbfa56944c33bca287f88d42/branding/SVG%20-%20Transparent/logo-full-wide.svg" alt="Litestar Logo - Light" width="20%" height="auto" />
  <br>A <a href="https://github.com/jolt-org">Jolt Organization</a> Project
  <!-- github-banner-end -->
</p>

[jolt-org]: https://github.com/jolt-org
[contributing]: https://docs.advanced-alchemy.jolt.rs/latest/contribution-guide.html
[discord]: https://discord.gg/XpFNTjjtTK
[jolt-discussions]: https://github.com/orgs/jolt-org/discussions
[project-discussions]: https://github.com/jolt-org/advanced-alchemy/discussions
[project-docs]: https://docs.advanced-alchemy.jolt.rs
[install-guide]: https://docs.advanced-alchemy.jolt.rs/latest/#installation
[fastapi-example]: https://github.com/jolt-org/advanced-alchemy/blob/main/examples/fastapi.py
[litestar-example]: https://github.com/jolt-org/advanced-alchemy/blob/main/examples/litestar/litestar_service.py
[standalone-example]: https://github.com/jolt-org/advanced-alchemy/blob/main/examples/standalone.py

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "advanced-alchemy",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "alembic, fastapi, flask, litestar, sanic, sqlalchemy",
    "author": null,
    "author_email": "Cody Fincher <cody.fincher@gmail.com>, Peter Schutt <peter.github@proton.me>, Janek Nouvertn\u00e9 <j.a.nouvertne@posteo.de>, Jacob Coffee <jacob@z7x.org>",
    "download_url": "https://files.pythonhosted.org/packages/e6/53/ef5831d7aad4348cfd7030150ba704015cb90d61152deaf4315ee1f93ee2/advanced_alchemy-0.9.0.tar.gz",
    "platform": null,
    "description": "# Advanced Alchemy\n\n<div align=\"center\">\n\n| Project   |     | Status                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |\n| --------- | :-- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| CI/CD     |     | [![Latest Release](https://github.com/jolt-org/advanced-alchemy/actions/workflows/publish.yaml/badge.svg)](https://github.com/jolt-org/advanced-alchemy/actions/workflows/publish.yaml) [![Tests And Linting](https://github.com/jolt-org/advanced-alchemy/actions/workflows/ci.yaml/badge.svg)](https://github.com/jolt-org/advanced-alchemy/actions/workflows/ci.yaml) [![Documentation Building](https://github.com/jolt-org/advanced-alchemy/actions/workflows/docs.yaml/badge.svg)](https://github.com/jolt-org/advanced-alchemy/actions/workflows/docs.yaml)                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |\n| Quality   |     | [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=jolt-org_advanced-alchemy&metric=coverage)](https://sonarcloud.io/summary/new_code?id=jolt-org_advanced-alchemy) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=jolt-org_advanced-alchemy&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=jolt-org_advanced-alchemy) [![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=jolt-org_advanced-alchemy&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=jolt-org_advanced-alchemy) [![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=jolt-org_advanced-alchemy&metric=reliability_rating)](https://sonarcloud.io/summary/new_code?id=jolt-org_advanced-alchemy) [![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=jolt-org_advanced-alchemy&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=jolt-org_advanced-alchemy)                            |\n| Community |     | [![Discord](https://img.shields.io/discord/1149784127659319356?labelColor=F50057&color=202020&label=chat%20on%20discord&logo=discord&logoColor=202020)](https://discord.gg/XpFNTjjtTK)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |\n| Meta      |     | [![Jolt Project](https://img.shields.io/badge/Jolt%20Org-%E2%AD%90-F50057.svg?logo=python&labelColor=F50057&color=202020&logoColor=202020)](https://github.com/jolt-org/) [![types - Mypy](https://img.shields.io/badge/types-Mypy-F50057.svg?logo=python&labelColor=F50057&color=202020&logoColor=202020)](https://github.com/python/mypy) [![License - MIT](https://img.shields.io/badge/license-MIT-F50057.svg?logo=python&labelColor=F50057&color=202020&logoColor=202020)](https://spdx.org/licenses/) [![Jolt Sponsors](https://img.shields.io/badge/Sponsor-%E2%9D%A4-%23202020.svg?&logo=github&logoColor=202020&labelColor=F50057)](https://github.com/sponsors/jolt-org) [![linting - Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json&labelColor=F50057)](https://github.com/astral-sh/ruff) [![code style - Black](https://img.shields.io/badge/code%20style-black-000000.svg?logo=python&labelColor=F50057&logoColor=202020)](https://github.com/psf/black) |\n\n</div>\n\nCheck out the [project documentation][project-docs] \ud83d\udcda for more information.\n\n## About\n\nA carefully crafted, thoroughly tested, optimized companion library for SQLAlchemy,\noffering features such as:\n\n- Sync and async repositories, featuring common CRUD and highly optimized bulk operations\n- Integration with major web frameworks including Litestar, Starlette, FastAPI, Sanic.\n- Custom-built alembic configuration and CLI with optional framework integration\n- Utility base classes with audit columns, primary keys and utility functions\n- Optimized JSON types including a custom JSON type for Oracle.\n- Integrated support for UUID6 and UUID7 using [`uuid-utils`](https://github.com/aminalaee/uuid-utils) (install with the `uuid` extra)\n\n- Pre-configured base classes with audit columns UUID or Big Integer primary keys and\n  a [sentinel column](https://docs.sqlalchemy.org/en/20/core/connections.html#configuring-sentinel-columns).\n- Synchronous and asynchronous repositories featuring:\n  - Common CRUD operations for SQLAlchemy models\n  - Bulk inserts, updates, upserts, and deletes with dialect-specific enhancements\n  - [lambda_stmt](https://docs.sqlalchemy.org/en/20/core/sqlelement.html#sqlalchemy.sql.expression.lambda_stmt) when possible\n    for improved query building performance\n  - Integrated counts, pagination, sorting, filtering with `LIKE`, `IN`, and dates before and/or after.\n- Tested support for multiple database backends including:\n\n  - SQLite via [aiosqlite](https://aiosqlite.omnilib.dev/en/stable/) or [sqlite](https://docs.python.org/3/library/sqlite3.html)\n  - Postgres via [asyncpg](https://magicstack.github.io/asyncpg/current/) or [psycopg3 (async or sync)](https://www.psycopg.org/psycopg3/)\n  - MySQL via [asyncmy](https://github.com/long2ice/asyncmy)\n  - Oracle via [oracledb (async or sync)](https://oracle.github.io/python-oracledb/) (tested on 18c and 23c)\n  - Google Spanner via [spanner-sqlalchemy](https://github.com/googleapis/python-spanner-sqlalchemy/)\n  - DuckDB via [duckdb_engine](https://github.com/Mause/duckdb_engine)\n  - Microsoft SQL Server via [pyodbc](https://github.com/mkleehammer/pyodbc) or [aioodbc](https://github.com/aio-libs/aioodbc)\n  - CockroachDB via [sqlalchemy-cockroachdb (async or sync)](https://github.com/cockroachdb/sqlalchemy-cockroachdb)\n\n## Usage\n\n### Installation\n\n```shell\npip install advanced-alchemy\n```\n\n> [!IMPORTANT]\\\n> Check out [the installation guide][install-guide] in our official documentation!\n\n### Repositories\n\nAdvanced Alchemy includes a set of asynchronous and synchronous repository classes for easy CRUD\noperations on your SQLAlchemy models.\n\n<details>\n<summary>Click to expand the example</summary>\n\n```python\nfrom advanced_alchemy.base import UUIDBase\nfrom advanced_alchemy.filters import LimitOffset\nfrom advanced_alchemy.repository import SQLAlchemySyncRepository\nfrom sqlalchemy import create_engine\nfrom sqlalchemy.orm import Mapped, sessionmaker\n\n\nclass User(UUIDBase):\n    # you can optionally override the generated table name by manually setting it.\n    __tablename__ = \"user_account\"  # type: ignore[assignment]\n    email: Mapped[str]\n    name: Mapped[str]\n\n\nclass UserRepository(SQLAlchemySyncRepository[User]):\n    \"\"\"User repository.\"\"\"\n\n    model_type = User\n\n\n# use any compatible sqlalchemy engine.\nengine = create_engine(\"duckdb:///:memory:\")\nsession_factory = sessionmaker(engine, expire_on_commit=False)\n\n# Initializes the database.\nwith engine.begin() as conn:\n    User.metadata.create_all(conn)\n\nwith session_factory() as db_session:\n    repo = UserRepository(session=db_session)\n    # 1) Create multiple users with `add_many`\n    bulk_users = [\n        {\"email\": 'cody@advanced-alchemy.dev', 'name': 'Cody'},\n        {\"email\": 'janek@advanced-alchemy.dev', 'name': 'Janek'},\n        {\"email\": 'peter@advanced-alchemy.dev', 'name': 'Peter'},\n        {\"email\": 'jacob@advanced-alchemy.dev', 'name': 'Jacob'}\n    ]\n    objs = repo.add_many([User(**raw_user) for raw_user in bulk_users])\n    db_session.commit()\n    print(f\"Created {len(objs)} new objects.\")\n\n    # 2) Select paginated data and total row count.  Pass additional filters as kwargs\n    created_objs, total_objs = repo.list_and_count(LimitOffset(limit=10, offset=0), name=\"Cody\")\n    print(f\"Selected {len(created_objs)} records out of a total of {total_objs}.\")\n\n    # 3) Let's remove the batch of records selected.\n    deleted_objs = repo.delete_many([new_obj.id for new_obj in created_objs])\n    print(f\"Removed {len(deleted_objs)} records out of a total of {total_objs}.\")\n\n    # 4) Let's count the remaining rows\n    remaining_count = repo.count()\n    print(f\"Found {remaining_count} remaining records after delete.\")\n```\n\n</details>\n\nFor a full standalone example, see the sample [here][standalone-example]\n\n### Services\n\nAdvanced Alchemy includes an additional service class to make working with a repository easier.\nThis class is designed to accept data as a dictionary or SQLAlchemy model,\nand it will handle the type conversions for you.\n\n<details>\n<summary>Here's the same example from above but using a service to create the data:</summary>\n\n```python\nfrom advanced_alchemy.base import UUIDBase\nfrom advanced_alchemy.filters import LimitOffset\nfrom advanced_alchemy import SQLAlchemySyncRepository, SQLAlchemySyncRepositoryService\nfrom sqlalchemy import create_engine\nfrom sqlalchemy.orm import Mapped, sessionmaker\n\n\nclass User(UUIDBase):\n    # you can optionally override the generated table name by manually setting it.\n    __tablename__ = \"user_account\"  # type: ignore[assignment]\n    email: Mapped[str]\n    name: Mapped[str]\n\n\nclass UserRepository(SQLAlchemySyncRepository[User]):\n    \"\"\"User repository.\"\"\"\n\n    model_type = User\n\n\nclass UserService(SQLAlchemySyncRepositoryService[User]):\n    \"\"\"User repository.\"\"\"\n\n    repository_type = UserRepository\n\n\n# use any compatible sqlalchemy engine.\nengine = create_engine(\"duckdb:///:memory:\")\nsession_factory = sessionmaker(engine, expire_on_commit=False)\n\n# Initializes the database.\nwith engine.begin() as conn:\n    User.metadata.create_all(conn)\n\nwith session_factory() as db_session:\n    service = UserService(session=db_session)\n    # 1) Create multiple users with `add_many`\n    objs = service.create_many([\n        {\"email\": 'cody@advanced-alchemy.dev', 'name': 'Cody'},\n        {\"email\": 'janek@advanced-alchemy.dev', 'name': 'Janek'},\n        {\"email\": 'peter@advanced-alchemy.dev', 'name': 'Peter'},\n        {\"email\": 'jacob@advanced-alchemy.dev', 'name': 'Jacob'}\n    ])\n    print(objs)\n    print(f\"Created {len(objs)} new objects.\")\n\n    # 2) Select paginated data and total row count.  Pass additional filters as kwargs\n    created_objs, total_objs = service.list_and_count(LimitOffset(limit=10, offset=0), name=\"Cody\")\n    print(f\"Selected {len(created_objs)} records out of a total of {total_objs}.\")\n\n    # 3) Let's remove the batch of records selected.\n    deleted_objs = service.delete_many([new_obj.id for new_obj in created_objs])\n    print(f\"Removed {len(deleted_objs)} records out of a total of {total_objs}.\")\n\n    # 4) Let's count the remaining rows\n    remaining_count = service.count()\n    print(f\"Found {remaining_count} remaining records after delete.\")\n```\n\n</details>\n\n### Web Frameworks\n\nAdvanced Alchemy works with nearly all Python web frameworks.\nSeveral helpers for popular libraries are included, and additional PRs to support others are welcomed.\n\n#### Litestar\n\nAdvanced Alchemy is the official SQLAlchemy integration for Litestar.\n\nIn addition to installing with `pip install advanced-alchemy`,\nit can also be installed as a Litestar extra with `pip install litestar[sqlalchemy]`.\n\n<details>\n<summary>Litestar Example</summary>\n\n```python\nfrom litestar import Litestar\nfrom litestar.plugins.sqlalchemy import SQLAlchemyPlugin, SQLAlchemyAsyncConfig\n# alternately...\n# from advanced_alchemy.extensions.litestar.plugins import SQLAlchemyPlugin\n# from advanced_alchemy.extensions.litestar.plugins.init.config import SQLAlchemyAsyncConfig\n\nalchemy = SQLAlchemyPlugin(\n  config=SQLAlchemyAsyncConfig(connection_string=\"sqlite+aiosqlite:///test.sqlite\"),\n)\napp = Litestar(plugins=[alchemy])\n```\n\n</details>\n\nFor a full Litestar example, check [here][litestar-example]\n\n#### FastAPI\n\n<details>\n<summary>FastAPI Example</summary>\n\n```python\nfrom fastapi import FastAPI\n\nfrom advanced_alchemy.config import SQLAlchemyAsyncConfig\nfrom advanced_alchemy.extensions.starlette import StarletteAdvancedAlchemy\n\napp = FastAPI()\nalchemy = StarletteAdvancedAlchemy(\n    config=SQLAlchemyAsyncConfig(connection_string=\"sqlite+aiosqlite:///test.sqlite\"), app=app,\n)\n```\n\n</details>\n\nFor a full FastAPI example, see [here][fastapi-example]\n\n#### Starlette\n\n<details>\n<summary>Pre-built Example Apps</summary>\n\n```python\nfrom starlette.applications import Starlette\n\nfrom advanced_alchemy.config import SQLAlchemyAsyncConfig\nfrom advanced_alchemy.extensions.starlette import StarletteAdvancedAlchemy\n\napp = Starlette()\nalchemy = StarletteAdvancedAlchemy(\n    config=SQLAlchemyAsyncConfig(connection_string=\"sqlite+aiosqlite:///test.sqlite\"), app=app,\n)\n```\n\n</details>\n\n#### Sanic\n\n<details>\n<summary>Pre-built Example Apps</summary>\n\n```python\nfrom sanic import Sanic\nfrom sanic_ext import Extend\n\nfrom advanced_alchemy.config import SQLAlchemyAsyncConfig\nfrom advanced_alchemy.extensions.sanic import SanicAdvancedAlchemy\n\napp = Sanic(\"AlchemySanicApp\")\nalchemy = SanicAdvancedAlchemy(\n    sqlalchemy_config=SQLAlchemyAsyncConfig(connection_string=\"sqlite+aiosqlite:///test.sqlite\"),\n)\nExtend.register(alchemy)\n```\n\n</details>\n\n## Contributing\n\nAll [Jolt][jolt-org] projects will always be a community-centered, available for contributions of any size.\n\nBefore contributing, please review the [contribution guide][contributing].\n\nIf you have any questions, reach out to us on [Discord][discord], our org-wide [GitHub discussions][jolt-discussions] page,\nor the [project-specific GitHub discussions page][project-discussions].\n\n<hr>\n\n<!-- markdownlint-disable -->\n<p align=\"center\">\n  <!-- github-banner-start -->\n  <img src=\"https://raw.githubusercontent.com/jolt-org/meta/2901c9c5c5895a83fbfa56944c33bca287f88d42/branding/SVG%20-%20Transparent/logo-full-wide.svg\" alt=\"Litestar Logo - Light\" width=\"20%\" height=\"auto\" />\n  <br>A <a href=\"https://github.com/jolt-org\">Jolt Organization</a> Project\n  <!-- github-banner-end -->\n</p>\n\n[jolt-org]: https://github.com/jolt-org\n[contributing]: https://docs.advanced-alchemy.jolt.rs/latest/contribution-guide.html\n[discord]: https://discord.gg/XpFNTjjtTK\n[jolt-discussions]: https://github.com/orgs/jolt-org/discussions\n[project-discussions]: https://github.com/jolt-org/advanced-alchemy/discussions\n[project-docs]: https://docs.advanced-alchemy.jolt.rs\n[install-guide]: https://docs.advanced-alchemy.jolt.rs/latest/#installation\n[fastapi-example]: https://github.com/jolt-org/advanced-alchemy/blob/main/examples/fastapi.py\n[litestar-example]: https://github.com/jolt-org/advanced-alchemy/blob/main/examples/litestar/litestar_service.py\n[standalone-example]: https://github.com/jolt-org/advanced-alchemy/blob/main/examples/standalone.py\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Ready-to-go SQLAlchemy concoctions.",
    "version": "0.9.0",
    "project_urls": {
        "Changelog": "https://docs.advanced-alchemy.jolt.rs/latest/changelog",
        "Discord": "https://discord.gg/XpFNTjjtTK",
        "Documentation": "https://docs.advanced-alchemy.jolt.rs/latest/",
        "Funding": "https://github.com/sponsors/jolt-org",
        "Homepage": "https://docs.advanced-alchemy.jolt.rs/latest/",
        "Issue": "https://github.com/jolt-org/advanced-alchemy/issues/",
        "Source": "https://github.com/jolt-org/advanced-alchemy"
    },
    "split_keywords": [
        "alembic",
        " fastapi",
        " flask",
        " litestar",
        " sanic",
        " sqlalchemy"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "426415b47968207bc520b8de65a67a9b82afc398cd075c3a1dc433d79a458398",
                "md5": "ca72004c6943fde0c616bd5d59f2a71b",
                "sha256": "882cf8b27cc8800f80971d44eb2c65f3a8718c28f2552a04ffe345ba7ac1e922"
            },
            "downloads": -1,
            "filename": "advanced_alchemy-0.9.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "ca72004c6943fde0c616bd5d59f2a71b",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 114845,
            "upload_time": "2024-04-07T18:53:49",
            "upload_time_iso_8601": "2024-04-07T18:53:49.996159Z",
            "url": "https://files.pythonhosted.org/packages/42/64/15b47968207bc520b8de65a67a9b82afc398cd075c3a1dc433d79a458398/advanced_alchemy-0.9.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "e653ef5831d7aad4348cfd7030150ba704015cb90d61152deaf4315ee1f93ee2",
                "md5": "aeb270aa6bca5783d2b2b9a4016fed21",
                "sha256": "25c27f57cb1b9cebf3073742c64061cea2b8b765660cb59fa02430cfb7a5c018"
            },
            "downloads": -1,
            "filename": "advanced_alchemy-0.9.0.tar.gz",
            "has_sig": false,
            "md5_digest": "aeb270aa6bca5783d2b2b9a4016fed21",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 534245,
            "upload_time": "2024-04-07T18:53:52",
            "upload_time_iso_8601": "2024-04-07T18:53:52.302525Z",
            "url": "https://files.pythonhosted.org/packages/e6/53/ef5831d7aad4348cfd7030150ba704015cb90d61152deaf4315ee1f93ee2/advanced_alchemy-0.9.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-04-07 18:53:52",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "sponsors",
    "github_project": "jolt-org",
    "github_not_found": true,
    "lcname": "advanced-alchemy"
}
        
Elapsed time: 0.28705s