Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:

- name: Run ruff via nox
run: |
uv run nox -s format
uv run nox -s format_check

pyright:
runs-on: ubuntu-latest
Expand All @@ -38,3 +38,25 @@ jobs:
- name: Run pyright via nox
run: |
uv run nox -s pyright
sqlc:
runs-on: ubuntu-latest
name: "Run sqlc verify via nox"
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v5
with:
version: "0.6.9"
python-version: "3.13"

- name: Install sqlc
uses: sqlc-dev/setup-sqlc@v4
with:
sqlc-version: '1.28.0'

- name: Run sqlc verify via nox
run: |
uv run nox -s sqlc_verify



25 changes: 25 additions & 0 deletions db/query.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
-- name: GetAuthor :one
SELECT * FROM authors
WHERE id = ? LIMIT 1;

-- name: ListAuthors :many
SELECT * FROM authors
ORDER BY name;

-- name: CreateAuthor :one
INSERT INTO authors (
name, bio
) VALUES (
?, ?
)
RETURNING *;

-- name: UpdateAuthor :exec
UPDATE authors
set name = ?,
bio = ?
WHERE id = ?;

-- name: DeleteAuthor :exec
DELETE FROM authors
WHERE id = ?;
5 changes: 5 additions & 0 deletions db/schema.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
CREATE TABLE authors (
id INTEGER PRIMARY KEY,
name text NOT NULL,
bio text
);
21 changes: 18 additions & 3 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@

PATH_TO_PROJECT = os.path.join(".", "src")
SCRIPT_PATHS = [PATH_TO_PROJECT, "noxfile.py"]
SQLC_CONFIG = "sqlc.yaml"

options.default_venv_backend = "uv"
options.sessions = ["format_fix", "pyright"]
options.sessions = ["format", "pyright"]


# uv_sync taken from: https://github.com/hikari-py/hikari/blob/master/pipelines/nox.py#L48
Expand Down Expand Up @@ -45,14 +46,14 @@ def uv_sync(


@nox.session()
def format_fix(session: nox.Session) -> None:
def format(session: nox.Session) -> None:
uv_sync(session, groups=["dev"])
session.run("python", "-m", "ruff", "format", *SCRIPT_PATHS)
session.run("python", "-m", "ruff", "check", *SCRIPT_PATHS, "--fix")


@nox.session()
def format(session: nox.Session) -> None:
def format_check(session: nox.Session) -> None:
uv_sync(session, groups=["dev"])
session.run("python", "-m", "ruff", "format", *SCRIPT_PATHS, "--check")
session.run("python", "-m", "ruff", "check", *SCRIPT_PATHS)
Expand All @@ -62,3 +63,17 @@ def format(session: nox.Session) -> None:
def pyright(session: nox.Session) -> None:
uv_sync(session, include_self=True, groups=["dev"])
session.run("pyright", *SCRIPT_PATHS)


@nox.session()
def sqlc(session: nox.Session) -> None:
# note: this required sqlc to be installed on the system.
# https://docs.sqlc.dev/en/latest/overview/install.html
session.run("sqlc", "generate", "-f", SQLC_CONFIG, external=True)


@nox.session()
def sqlc_verify(session: nox.Session) -> None:
# note: this required sqlc to be installed on the system.
# https://docs.sqlc.dev/en/latest/overview/install.html
session.run("sqlc", "diff", "-f", SQLC_CONFIG, external=True)
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ dependencies = [
"hikari-arc>=2.0.0",
"hikari[speedups]>=2.2.0",
"python-dotenv>=1.0.1",
"sqlc-asyncpg-compat",
]

[dependency-groups]
Expand Down Expand Up @@ -78,6 +79,9 @@ ignore_errors = true
[tool.uv]
required-version = "~=0.6"

[tool.uv.sources]
sqlc-asyncpg-compat = { git = "https://github.com/tandemdude/sqlc-asyncpg-compat" }

[tool.pyright]
pythonVersion = "3.13"
typeCheckingMode = "strict"
Expand Down
18 changes: 18 additions & 0 deletions sqlc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
version: "2"
plugins:
- name: py
wasm:
url: "https://downloads.sqlc.dev/plugin/sqlc-gen-python_1.3.0.wasm"
sha256: "fbedae96b5ecae2380a70fb5b925fd4bff58a6cfb1f3140375d098fbab7b3a3c"
sql:
- engine: "sqlite"
queries: "db/query.sql"
schema: "db/schema.sql"
codegen:
- out: "src/db"
plugin: py
options:
package: "src.db"
emit_sync_querier: false
emit_async_querier: true
emit_str_enum: true
Empty file added src/db/__init__.py
Empty file.
12 changes: 12 additions & 0 deletions src/db/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Code generated by sqlc. DO NOT EDIT.
# versions:
# sqlc v1.28.0
import dataclasses
from typing import Any, Optional


@dataclasses.dataclass()
class Author:
id: Any
name: Any
bio: Optional[Any]
73 changes: 73 additions & 0 deletions src/db/query.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Code generated by sqlc. DO NOT EDIT.
# versions:
# sqlc v1.28.0
# source: query.sql
from typing import Any, AsyncIterator, Optional

import sqlalchemy
import sqlalchemy.ext.asyncio

from src.db import models

CREATE_AUTHOR = """-- name: create_author \\:one
INSERT INTO authors (
name, bio
) VALUES (
?, ?
)
RETURNING id, name, bio
"""


DELETE_AUTHOR = """-- name: delete_author \\:exec
DELETE FROM authors
WHERE id = ?
"""


GET_AUTHOR = """-- name: get_author \\:one
SELECT id, name, bio FROM authors
WHERE id = ? LIMIT 1
"""


LIST_AUTHORS = """-- name: list_authors \\:many
SELECT id, name, bio FROM authors
ORDER BY name
"""


UPDATE_AUTHOR = """-- name: update_author \\:exec
UPDATE authors
set name = ?,
bio = ?
WHERE id = ?
"""


class AsyncQuerier:
def __init__(self, conn: sqlalchemy.ext.asyncio.AsyncConnection):
self._conn = conn

async def create_author(self, *, name: Any, bio: Optional[Any]) -> Optional[models.Author]:
row = (await self._conn.execute(sqlalchemy.text(CREATE_AUTHOR), {"p1": name, "p2": bio})).first()
if row is None:
return None
return models.Author(id=row[0], name=row[1], bio=row[2])

async def delete_author(self, *, id: Any) -> None:
await self._conn.execute(sqlalchemy.text(DELETE_AUTHOR), {"p1": id})

async def get_author(self, *, id: Any) -> Optional[models.Author]:
row = (await self._conn.execute(sqlalchemy.text(GET_AUTHOR), {"p1": id})).first()
if row is None:
return None
return models.Author(id=row[0], name=row[1], bio=row[2])

async def list_authors(self) -> AsyncIterator[models.Author]:
result = await self._conn.stream(sqlalchemy.text(LIST_AUTHORS))
async for row in result:
yield models.Author(id=row[0], name=row[1], bio=row[2])

async def update_author(self, *, name: Any, bio: Optional[Any], id: Any) -> None:
await self._conn.execute(sqlalchemy.text(UPDATE_AUTHOR), {"p1": name, "p2": bio, "p3": id})
27 changes: 27 additions & 0 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading