Skip to content

Commit 3315826

Browse files
authored
feat(litestar): server side session backend (#429)
Implements a server side session backend using SQLAlchemy. Works with an Async or Sync configuration.
1 parent 07ed2cc commit 3315826

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+13047
-3060
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ coverage.xml
5252
.pytest_cache/
5353
cover/
5454
test.sqlite
55+
*.db
5556

5657
# Translations
5758
*.mo

.pre-commit-config.yaml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,11 @@ repos:
3131
# Run the formatter.
3232
- id: ruff-format
3333
types_or: [python, pyi]
34-
- repo: https://github.com/crate-ci/typos
35-
rev: "v1"
34+
- repo: https://github.com/codespell-project/codespell
35+
rev: v2.4.1
3636
hooks:
37-
- id: typos
37+
- id: codespell
38+
additional_dependencies: [tomli]
3839
- repo: https://github.com/sphinx-contrib/sphinx-lint
3940
rev: "v1.0.0"
4041
hooks:

Makefile

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,15 +119,14 @@ clean: ## Cleanup temporary build a
119119
.PHONY: test
120120
test: ## Run the tests
121121
@echo "${INFO} Running test cases... 🧪"
122-
@uv run pytest -n 2 --quiet
122+
@uv run pytest --dist "loadgroup" -m "" tests -n 2 --quiet
123123
@echo "${OK} Tests passed ✨"
124124

125125
.PHONY: coverage
126126
coverage: ## Run tests with coverage report
127127
@echo "${INFO} Running tests with coverage... 📊"
128-
@uv run pytest --cov -n auto --quiet
128+
@uv run pytest tests --dist "loadgroup" -m "" --cov=advanced_alchemy --cov-report=xml -n 2 --quiet
129129
@uv run coverage html >/dev/null 2>&1
130-
@uv run coverage xml >/dev/null 2>&1
131130
@echo "${OK} Coverage report generated ✨"
132131

133132
# -----------------------------------------------------------------------------

advanced_alchemy/alembic/utils.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from pathlib import Path
33
from typing import TYPE_CHECKING, Union
44

5-
from sqlalchemy import Engine, MetaData, Table
5+
from sqlalchemy import Column, Engine, MetaData, String, Table
66
from typing_extensions import TypeIs
77

88
from advanced_alchemy.exceptions import MissingDependencyError
@@ -42,7 +42,15 @@ def _drop_tables_sync(engine: Engine) -> None:
4242
console.rule("[bold red]Dropping the db", align="left")
4343
metadata.drop_all(db)
4444
console.rule("[bold red]Dropping the version table", align="left")
45-
Table(version_table_name, metadata).drop(db, checkfirst=True)
45+
# Create a properly defined Alembic version table with required column structure
46+
# Using a temporary metadata instance prevents modifying the shared metadata object
47+
temp_metadata = MetaData()
48+
alembic_version_table = Table(
49+
version_table_name,
50+
temp_metadata,
51+
Column("version_num", String(32), primary_key=True, nullable=False),
52+
)
53+
alembic_version_table.drop(db, checkfirst=True)
4654
console.rule("[bold yellow]Successfully dropped all objects", align="left")
4755

4856
async def _drop_tables_async(engine: "AsyncEngine") -> None:
@@ -51,7 +59,15 @@ async def _drop_tables_async(engine: "AsyncEngine") -> None:
5159
console.rule("[bold red]Dropping the db", align="left")
5260
await db.run_sync(metadata.drop_all)
5361
console.rule("[bold red]Dropping the version table", align="left")
54-
await db.run_sync(Table(version_table_name, metadata).drop, checkfirst=True)
62+
# Create a properly defined Alembic version table with required column structure
63+
# Using a temporary metadata instance prevents modifying the shared metadata object
64+
temp_metadata = MetaData()
65+
alembic_version_table = Table(
66+
version_table_name,
67+
temp_metadata,
68+
Column("version_num", String(32), primary_key=True, nullable=False),
69+
)
70+
await db.run_sync(alembic_version_table.drop, checkfirst=True)
5571
console.rule("[bold yellow]Successfully dropped all objects", align="left")
5672

5773
if _is_sync(engine):

advanced_alchemy/extensions/litestar/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from advanced_alchemy import base, exceptions, filters, mixins, operations, repository, service, types, utils
22
from advanced_alchemy.alembic.commands import AlembicCommands
33
from advanced_alchemy.config import AlembicAsyncConfig, AlembicSyncConfig, AsyncSessionConfig, SyncSessionConfig
4-
from advanced_alchemy.extensions.litestar import providers
4+
from advanced_alchemy.extensions.litestar import providers, session, store
55
from advanced_alchemy.extensions.litestar.cli import get_database_migration_plugin
66
from advanced_alchemy.extensions.litestar.dto import SQLAlchemyDTO, SQLAlchemyDTOConfig
77
from advanced_alchemy.extensions.litestar.plugins import (
@@ -64,6 +64,8 @@
6464
"providers",
6565
"repository",
6666
"service",
67+
"session",
68+
"store",
6769
"sync_autocommit_before_send_handler",
6870
"sync_autocommit_handler_maker",
6971
"sync_default_before_send_handler",

advanced_alchemy/extensions/litestar/plugins/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ def on_app_init(self, app_config: AppConfig) -> AppConfig:
4141
4242
Args:
4343
app_config: The :class:`AppConfig <.config.app.AppConfig>` instance.
44+
45+
Returns:
46+
The :class:`AppConfig <.config.app.AppConfig>` instance.
4447
"""
4548
app_config.plugins.extend([SQLAlchemyInitPlugin(config=self._config), SQLAlchemySerializationPlugin()])
4649
return app_config

0 commit comments

Comments
 (0)