Metadata-Version: 2.4
Name: edgedb-pydantic-codegen
Version: 2025.3.1
Summary: Alternative Python EdgeDB code generator (Pydantic V2 + asyncio, FastAPI compatible)
Project-URL: homepage, https://github.com/Japan7/edgedb-pydantic-codegen
Author-email: NextFire <git@yuru.moe>
License-Expression: MIT
License-File: LICENSE
Requires-Python: >=3.11
Requires-Dist: edgedb<3,>=1
Requires-Dist: jinja2<4,>=3
Requires-Dist: orjson<4,>=3
Requires-Dist: pydantic<3,>=2
Requires-Dist: ruff<1,>=0.1.2
Description-Content-Type: text/markdown

# edgedb-pydantic-codegen

This tool generates Python typesafe async code for EdgeQL queries using [Pydantic V2](https://github.com/pydantic/pydantic).

The generated models can be directly used with other libraries such as [FastAPI](https://github.com/tiangolo/fastapi).

This is an alternative to the [built-in code generator](https://github.com/edgedb/edgedb-python/tree/master/edgedb/codegen) of the official [edgedb-python](https://github.com/edgedb/edgedb-python/tree/master) library.

## Usage

<p>
  <a href="https://pypi.org/project/edgedb-pydantic-codegen" alt="Python version compatibility">
    <img src="https://img.shields.io/pypi/pyversions/edgedb-pydantic-codegen" /></a>
  <a href="https://pypi.org/project/edgedb-pydantic-codegen" alt="PyPI version">
    <img src="https://img.shields.io/pypi/v/edgedb-pydantic-codegen" /></a>
  <a href="https://calver.org" alt="Calendar Versioning scheme">
    <img src="https://img.shields.io/badge/calver-YYYY.0M.MICRO-22bfda" /></a>
</p>

In an EdgeDB initialized project, simply run

```sh
uvx edgedb-pydantic-codegen <directory>
```

All `*.edgeql` files in `<directory>` and its subdirectories will be processed and the generated code saved next to them.

## Generated code example

```py
from enum import StrEnum

from edgedb import AsyncIOExecutor
from pydantic import BaseModel, TypeAdapter

EDGEQL_QUERY = r"""
with
  discord_id := <int64>$discord_id,
  moecoins := <optional int32>$moecoins,
  blood_shards := <optional int32>$blood_shards,
  updated := (
    update waicolle::Player
    filter .client = global client and .user.discord_id = discord_id
    set {
      moecoins := .moecoins + (moecoins ?? 0),
      blood_shards := .blood_shards + (blood_shards ?? 0),
    }
  )
select updated {
  game_mode,
  moecoins,
  blood_shards,
  user: {
    discord_id,
    discord_id_str,
  },
}
"""


class WaicolleGameMode(StrEnum):
    WAIFU = "WAIFU"
    HUSBANDO = "HUSBANDO"
    ALL = "ALL"


class PlayerAddCoinsResultUser(BaseModel):
    discord_id: int
    discord_id_str: str


class PlayerAddCoinsResult(BaseModel):
    game_mode: WaicolleGameMode
    moecoins: int
    blood_shards: int
    user: PlayerAddCoinsResultUser


adapter = TypeAdapter(PlayerAddCoinsResult | None)


async def player_add_coins(
    executor: AsyncIOExecutor,
    *,
    discord_id: int,
    moecoins: int | None = None,
    blood_shards: int | None = None,
) -> PlayerAddCoinsResult | None:
    resp = await executor.query_single_json(
        EDGEQL_QUERY,
        discord_id=discord_id,
        moecoins=moecoins,
        blood_shards=blood_shards,
    )
    return adapter.validate_json(resp, strict=False)
```

## Caveats

Currently this tool does not support:

- `TupleType`, `RangeType` and `MultiRangeType` collections
- `std::duration`, `cal::relative_duration`, `cal::date_duration`, `cfg::memory` and `ext::pgvector::vector` objects
