Skip to content

Commit 1cf35db

Browse files
authored
feat: move full litestar plugin (#17)
1 parent b6adda3 commit 1cf35db

41 files changed

Lines changed: 3247 additions & 221 deletions

Some content is hidden

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

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ coverage.xml
5050
.hypothesis/
5151
.pytest_cache/
5252
cover/
53+
test.sqlite
5354

5455
# Translations
5556
*.mo

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ repos:
1717
- id: mixed-line-ending
1818
- id: trailing-whitespace
1919
- repo: https://github.com/provinzkraut/unasyncd
20-
rev: "v0.6.0"
20+
rev: "v0.6.1"
2121
hooks:
2222
- id: unasyncd
2323
additional_dependencies: ["ruff"]
2424
- repo: https://github.com/charliermarsh/ruff-pre-commit
25-
rev: "v0.0.289"
25+
rev: "v0.0.290"
2626
hooks:
2727
- id: ruff
2828
args: ["--fix"]

README.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,26 @@ offering features such as:
3131
- Tested support for multiple database backends including:
3232

3333
- SQLite via [aiosqlite](https://aiosqlite.omnilib.dev/en/stable/) or [sqlite](https://docs.python.org/3/library/sqlite3.html)
34-
- Postgres via [asyncpg](https://magicstack.github.io/asyncpg/current/)\_ or [psycopg3 (async or sync)](https://www.psycopg.org/psycopg3/)
34+
- Postgres via [asyncpg](https://magicstack.github.io/asyncpg/current/) or [psycopg3 (async or sync)](https://www.psycopg.org/psycopg3/)
3535
- MySQL via [asyncmy](https://github.com/long2ice/asyncmy)
3636
- Oracle via [oracledb](https://oracle.github.io/python-oracledb/)
3737
- Google Spanner via [spanner-sqlalchemy](https://github.com/googleapis/python-spanner-sqlalchemy/)
3838
- DuckDB via [duckdb_engine](https://github.com/Mause/duckdb_engine>)
3939

4040
## Usage
4141

42+
### Litestar
43+
44+
> [!NOTE]\
45+
> This section has not been completed (yet!)
46+
47+
### Starlette/FastAPI
48+
49+
> [!NOTE]\
50+
> This section has not been completed (yet!)
51+
52+
### Sanic
53+
4254
> [!NOTE]\
4355
> This section has not been completed (yet!)
4456

advanced_alchemy/alembic/templates/asyncio/env.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,7 @@ async def run_migrations_online() -> None:
119119
connectable = cast(
120120
"AsyncEngine",
121121
config.engine
122-
if config.engine
123-
else async_engine_from_config(
122+
or async_engine_from_config(
124123
configuration,
125124
prefix="sqlalchemy.",
126125
poolclass=pool.NullPool,

advanced_alchemy/base.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
"""Application ORM configuration."""
2+
23
from __future__ import annotations
34

5+
import contextlib
46
import re
57
from datetime import date, datetime, timezone
68
from typing import TYPE_CHECKING, Any, ClassVar, Protocol, TypeVar, runtime_checkable
@@ -18,7 +20,7 @@
1820
registry,
1921
)
2022

21-
from .types import GUID, BigIntIdentity, DateTimeUTC, JsonB
23+
from advanced_alchemy.types import GUID, BigIntIdentity, DateTimeUTC, JsonB
2224

2325
if TYPE_CHECKING:
2426
from sqlalchemy.sql import FromClause
@@ -160,13 +162,10 @@ def create_registry() -> registry:
160162
date: Date,
161163
dict: JsonB,
162164
}
163-
try:
165+
with contextlib.suppress(ImportError):
164166
from pydantic import AnyHttpUrl, AnyUrl, EmailStr
165167

166168
type_annotation_map.update({EmailStr: String, AnyUrl: String, AnyHttpUrl: String})
167-
except ImportError:
168-
pass
169-
170169
return registry(metadata=meta, type_annotation_map=type_annotation_map)
171170

172171

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +0,0 @@
1-
from .plugin import AdvancedAlchemyPlugin
2-
3-
__all__ = ["AdvancedAlchemyPlugin"]
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from contextlib import suppress
2+
3+
from litestar import Litestar
4+
5+
from advanced_alchemy.alembic.commands import AlembicCommands as _AlembicCommands
6+
from advanced_alchemy.exceptions import ImproperConfigurationError
7+
from advanced_alchemy.extensions.litestar.plugins import SQLAlchemyInitPlugin
8+
9+
10+
def get_database_migration_plugin(app: Litestar) -> SQLAlchemyInitPlugin:
11+
"""Retrieve a database migration plugin from the Litestar application's plugins.
12+
13+
This function attempts to find and return either the SQLAlchemyPlugin or SQLAlchemyInitPlugin.
14+
If neither plugin is found, it raises an ImproperlyConfiguredException.
15+
"""
16+
17+
with suppress(KeyError):
18+
return app.plugins.get(SQLAlchemyInitPlugin)
19+
msg = "Failed to initialize database migrations. The required plugin (SQLAlchemyPlugin or SQLAlchemyInitPlugin) is missing."
20+
raise ImproperConfigurationError(
21+
msg,
22+
)
23+
24+
25+
class AlembicCommands(_AlembicCommands):
26+
def __init__(self, app: Litestar) -> None:
27+
self._app = app
28+
self.plugin_config = get_database_migration_plugin(self._app)._config # noqa: SLF001
29+
self.config = self._get_alembic_command_config()

advanced_alchemy/extensions/litestar/cli.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22

33
from typing import TYPE_CHECKING, cast
44

5+
from click import argument, group, option
56
from litestar.cli._utils import LitestarGroup, console
67
from rich.prompt import Confirm, Prompt
78

8-
from advanced_alchemy.extensions.litestar.plugin import AlembicCommands, _get_advanced_alchemy_plugin
9+
from advanced_alchemy.extensions.litestar.alembic import AlembicCommands, get_database_migration_plugin
910

1011
if TYPE_CHECKING:
1112
from litestar import Litestar
@@ -14,9 +15,6 @@
1415
from alembic.operations.ops import MigrationScript, UpgradeOps
1516

1617

17-
from click import argument, group, option
18-
19-
2018
@group(cls=LitestarGroup, name="database")
2119
def database_group() -> None:
2220
"""Manage SQLAlchemy database components."""
@@ -130,16 +128,16 @@ def upgrade_database(app: Litestar, revision: str, sql: bool, tag: str | None, n
130128
def init_alembic(app: Litestar, directory: str | None, multidb: bool, package: bool, no_prompt: bool) -> None:
131129
"""Upgrade the database to the latest revision."""
132130
console.rule("[yellow]Initializing database migrations.", align="left")
133-
plugin = _get_advanced_alchemy_plugin(app)
131+
plugin = get_database_migration_plugin(app)
134132
if directory is None:
135-
directory = plugin._config.script_location # noqa: SLF001
133+
directory = plugin._alembic_config.script_location # noqa: SLF001
136134
input_confirmed = (
137135
True
138136
if no_prompt
139137
else Confirm.ask("[bold]Are you sure you you want initialize the project in `{directory}`?[/]")
140138
)
141139
if input_confirmed:
142-
alembic_commands = AlembicCommands(app=app)
140+
alembic_commands = AlembicCommands(app)
143141
alembic_commands.init(directory=directory, multidb=multidb, package=package)
144142

145143

@@ -207,6 +205,7 @@ def process_revision_directives(
207205
console.rule("[yellow]Starting database upgrade process[/]", align="left")
208206
if message is None:
209207
message = "autogenerated" if no_prompt else Prompt.ask("Please enter a message describing this revision")
208+
210209
alembic_commands = AlembicCommands(app=app)
211210
alembic_commands.revision(
212211
message=message,

0 commit comments

Comments
 (0)