Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: deprecate litestar.contrib.sqlalchemy #3755

Merged
merged 19 commits into from
Sep 23, 2024
Merged
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,4 @@ __pypackages__/
# test certificates
certs/
pdm.toml
.zed
10 changes: 8 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@
(PY_CLASS, "litestar.response.RedirectResponse"),
(PY_CLASS, "litestar.response_containers.Redirect"),
(PY_CLASS, "litestar.response_containers.Template"),
(PY_CLASS, "litestar.contrib.sqlalchemy.plugins.SQLAlchemyPlugin"),
(PY_CLASS, "litestar.contrib.sqlalchemy.plugins.SQLAlchemySerializationPlugin"),
(PY_CLASS, "litestar.contrib.sqlalchemy.plugins.SQLAlchemyInitPlugin"),
(PY_CLASS, "litestar.contrib.sqlalchemy.dto.SQLAlchemyDTO"),
(PY_CLASS, "litestar.contrib.sqlalchemy.types.BigIntIdentity"),
(PY_CLASS, "litestar.contrib.sqlalchemy.types.JsonB"),
(PY_CLASS, "litestar.typing.ParsedType"),
Expand All @@ -165,6 +169,8 @@
(PY_CLASS, "advanced_alchemy.extensions.litestar.plugins._slots_base.SlotsBase"),
(PY_CLASS, "advanced_alchemy.config.EngineConfig"),
(PY_CLASS, "advanced_alchemy.config.common.GenericAlembicConfig"),
(PY_CLASS, "advanced_alchemy.extensions.litestar.SQLAlchemyDTO"),
(PY_CLASS, "advanced_alchemy.extensions.litestar.dto.SQLAlchemyDTO"),
(PY_CLASS, "advanced_alchemy.extensions.litestar.plugins.SQLAlchemyPlugin"),
(PY_CLASS, "advanced_alchemy.extensions.litestar.plugins.SQLAlchemySerializationPlugin"),
(PY_CLASS, "advanced_alchemy.extensions.litestar.plugins.SQLAlchemyInitPlugin"),
Expand Down Expand Up @@ -349,11 +355,11 @@ def delayed_setup(app: Sphinx) -> None:
return

app.setup_extension("pydata_sphinx_theme")
app.connect("html-page-context", update_html_context)
app.connect("html-page-context", update_html_context) # type: ignore


def setup(app: Sphinx) -> dict[str, bool]:
app.connect("builder-inited", delayed_setup, priority=0)
app.connect("builder-inited", delayed_setup, priority=0) # type: ignore

app.setup_extension("litestar_sphinx_theme")

Expand Down
26 changes: 15 additions & 11 deletions docs/examples/contrib/sqlalchemy/sqlalchemy_async_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,19 @@
from sqlalchemy.orm import Mapped, mapped_column, relationship, selectinload

from litestar import Litestar, get
from litestar.contrib.sqlalchemy.base import UUIDAuditBase, UUIDBase
from litestar.contrib.sqlalchemy.plugins import AsyncSessionConfig, SQLAlchemyAsyncConfig, SQLAlchemyInitPlugin
from litestar.contrib.sqlalchemy.repository import SQLAlchemyAsyncRepository
from litestar.controller import Controller
from litestar.di import Provide
from litestar.handlers.http_handlers.decorators import delete, patch, post
from litestar.pagination import OffsetPagination
from litestar.params import Parameter
from litestar.repository.filters import LimitOffset
from litestar.plugins.sqlalchemy import (
AsyncSessionConfig,
SQLAlchemyAsyncConfig,
SQLAlchemyInitPlugin,
base,
filters,
repository,
)

if TYPE_CHECKING:
from sqlalchemy.ext.asyncio import AsyncSession
Expand All @@ -32,7 +36,7 @@ class BaseModel(_BaseModel):

# the SQLAlchemy base includes a declarative model for you to use in your models.
# The `Base` class includes a `UUID` based primary key (`id`)
class AuthorModel(UUIDBase):
class AuthorModel(base.UUIDBase):
# we can optionally provide the table name instead of auto-generating it
__tablename__ = "author" # type: ignore[assignment]
name: Mapped[str]
Expand All @@ -43,7 +47,7 @@ class AuthorModel(UUIDBase):
# The `AuditBase` class includes the same UUID` based primary key (`id`) and 2
# additional columns: `created` and `updated`. `created` is a timestamp of when the
# record created, and `updated` is the last time the record was modified.
class BookModel(UUIDAuditBase):
class BookModel(base.UUIDAuditBase):
__tablename__ = "book" # type: ignore[assignment]
title: Mapped[str]
author_id: Mapped[UUID] = mapped_column(ForeignKey("author.id"))
Expand All @@ -69,7 +73,7 @@ class AuthorUpdate(BaseModel):
dob: date | None = None


class AuthorRepository(SQLAlchemyAsyncRepository[AuthorModel]):
class AuthorRepository(repository.SQLAlchemyAsyncRepository[AuthorModel]):
"""Author repository."""

model_type = AuthorModel
Expand Down Expand Up @@ -98,7 +102,7 @@ def provide_limit_offset_pagination(
default=10,
required=False,
),
) -> LimitOffset:
) -> filters.LimitOffset:
"""Add offset/limit pagination.

Return type consumed by `Repository.apply_limit_offset_pagination()`.
Expand All @@ -110,7 +114,7 @@ def provide_limit_offset_pagination(
page_size : int
OFFSET to apply to select.
"""
return LimitOffset(page_size, page_size * (current_page - 1))
return filters.LimitOffset(page_size, page_size * (current_page - 1))


class AuthorController(Controller):
Expand All @@ -122,7 +126,7 @@ class AuthorController(Controller):
async def list_authors(
self,
authors_repo: AuthorRepository,
limit_offset: LimitOffset,
limit_offset: filters.LimitOffset,
) -> OffsetPagination[Author]:
"""List authors."""
results, total = await authors_repo.list_and_count(limit_offset)
Expand Down Expand Up @@ -205,7 +209,7 @@ async def delete_author(
async def on_startup() -> None:
"""Initializes the database."""
async with sqlalchemy_config.get_engine().begin() as conn:
await conn.run_sync(UUIDBase.metadata.create_all)
await conn.run_sync(base.UUIDBase.metadata.create_all)


app = Litestar(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
from sqlalchemy.orm import Mapped, mapped_column, relationship, selectinload

from litestar import Litestar, get
from litestar.contrib.sqlalchemy import SQLAlchemyInitPlugin, SQLAlchemySyncConfig
from litestar.contrib.sqlalchemy.base import UUIDAuditBase, UUIDBase
from litestar.contrib.sqlalchemy.plugins.init import SQLAlchemyInitPlugin, SQLAlchemySyncConfig
from litestar.contrib.sqlalchemy.repository import SQLAlchemySyncRepository
from litestar.controller import Controller
from litestar.di import Provide
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
from sqlalchemy.orm import Mapped

from litestar import Litestar, get
from litestar.contrib.sqlalchemy.dto import SQLAlchemyDTO
from litestar.dto import DTOConfig
from litestar.plugins.sqlalchemy import SQLAlchemyDTO

from .my_lib import Base

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
from typing_extensions import Annotated

from litestar import Litestar, post
from litestar.contrib.sqlalchemy.dto import SQLAlchemyDTO
from litestar.dto import DTOConfig, dto_field
from litestar.plugins.sqlalchemy import SQLAlchemyDTO

from .my_lib import Base

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
from typing_extensions import Annotated

from litestar import Litestar, post
from litestar.contrib.sqlalchemy.dto import SQLAlchemyDTO
from litestar.dto import DTOConfig, dto_field
from litestar.plugins.sqlalchemy import SQLAlchemyDTO

from .my_lib import Base

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
from sqlalchemy.orm import Mapped, mapped_column

from litestar import Litestar, post
from litestar.contrib.sqlalchemy.dto import SQLAlchemyDTO
from litestar.dto import dto_field
from litestar.plugins.sqlalchemy import SQLAlchemyDTO

from .my_lib import Base

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
from sqlalchemy.orm import Mapped

from litestar import Litestar, get
from litestar.contrib.sqlalchemy.dto import SQLAlchemyDTO
from litestar.dto import DTOConfig
from litestar.pagination import ClassicPagination
from litestar.plugins.sqlalchemy import SQLAlchemyDTO

from .my_lib import Base

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
from typing_extensions import Annotated

from litestar import Litestar, put
from litestar.contrib.sqlalchemy.dto import SQLAlchemyDTO
from litestar.dto import DTOConfig
from litestar.plugins.sqlalchemy import SQLAlchemyDTO

from .my_lib import Base

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
from typing_extensions import Annotated

from litestar import Litestar, post
from litestar.contrib.sqlalchemy.dto import SQLAlchemyDTO
from litestar.dto import DTOConfig, dto_field
from litestar.plugins.sqlalchemy import SQLAlchemyDTO

from .my_lib import Base

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
from typing_extensions import Annotated

from litestar import Litestar, post
from litestar.contrib.sqlalchemy.dto import SQLAlchemyDTO
from litestar.dto import DTOConfig, dto_field
from litestar.plugins.sqlalchemy import SQLAlchemyDTO

from .my_lib import Base

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
from sqlalchemy.orm import Mapped

from litestar import Litestar, Response, get
from litestar.contrib.sqlalchemy.dto import SQLAlchemyDTO
from litestar.dto import DTOConfig
from litestar.plugins.sqlalchemy import SQLAlchemyDTO

from .my_lib import Base

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from sqlalchemy.orm import Mapped

from litestar import Litestar, post
from litestar.contrib.sqlalchemy.dto import SQLAlchemyDTO
from litestar.plugins.sqlalchemy import SQLAlchemyDTO

from .my_lib import Base

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
from sqlalchemy.orm import Mapped, mapped_column

from litestar import Litestar, post
from litestar.contrib.sqlalchemy.dto import SQLAlchemyDTO
from litestar.dto import dto_field
from litestar.plugins.sqlalchemy import SQLAlchemyDTO

from .my_lib import Base

Expand Down
5 changes: 2 additions & 3 deletions docs/examples/websockets/with_dto.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
from sqlalchemy.orm import Mapped

from litestar import Litestar, websocket_listener
from litestar.contrib.sqlalchemy.base import UUIDBase
from litestar.contrib.sqlalchemy.dto import SQLAlchemyDTO
from litestar.plugins.sqlalchemy import SQLAlchemyDTO, base


class User(UUIDBase):
class User(base.UUIDBase):
name: Mapped[str]


Expand Down
2 changes: 1 addition & 1 deletion litestar/contrib/pydantic/pydantic_init_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def _dec_pydantic_v1(model_type: type[pydantic_v1.BaseModel], value: Any) -> pyd
raise ExtendedMsgSpecValidationError(errors=cast("list[dict[str, Any]]", e.errors())) from e


def _dec_pydantic_v2(model_type: type[pydantic_v2.BaseModel], value: Any, strict: bool) -> pydantic_v2.BaseModel:
def _dec_pydantic_v2(model_type: type[pydantic_v2.BaseModel], value: Any, strict: bool) -> pydantic_v2.BaseModel: # pyright: ignore[reportInvalidTypeForm]
try:
return model_type.model_validate(value, strict=strict)
except pydantic_v2.ValidationError as e:
Expand Down
54 changes: 54 additions & 0 deletions litestar/contrib/sqlalchemy/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# ruff: noqa: TCH004, F401
from __future__ import annotations

from typing import TYPE_CHECKING

from litestar.utils import warn_deprecation

__all__ = (
"SQLAlchemyAsyncRepository",
"SQLAlchemySyncRepository",
"ModelT",
"wrap_sqlalchemy_exception",
)


def __getattr__(attr_name: str) -> object:
if attr_name in __all__:
if attr_name in ("SQLAlchemyAsyncRepository", "SQLAlchemySyncRepository", "ModelT"):
module = "litestar.plugins.sqlalchemy.repository"
from advanced_alchemy.extensions.litestar import (
repository, # type: ignore[import-not-found] # pyright: ignore[reportMissingImports]
)

value = globals()[attr_name] = getattr(repository, attr_name)
elif attr_name == "wrap_sqlalchemy_exception":
module = "litestar.plugins.sqlalchemy.exceptions"
from advanced_alchemy.extensions.litestar import (
exceptions, # type: ignore[import-not-found] # pyright: ignore[reportMissingImports]
)

value = globals()[attr_name] = getattr(exceptions, attr_name)
warn_deprecation(
deprecated_name=f"litestar.contrib.sqlalchemy.{attr_name}",
version="2.12",
kind="import",
removal_in="3.0",
info=f"importing {attr_name} from 'litestar.contrib.sqlalchemy' is deprecated, please "
f"import it from '{module}' instead",
)

return value

raise AttributeError(f"module {__name__!r} has no attribute {attr_name!r}") # pragma: no cover


if TYPE_CHECKING:
from advanced_alchemy.exceptions import ( # type: ignore[import-not-found] # pyright: ignore[reportMissingImports]
wrap_sqlalchemy_exception,
)
from advanced_alchemy.repository import ( # type: ignore[import-not-found] # pyright: ignore[reportMissingImports]
ModelT,
SQLAlchemyAsyncRepository,
SQLAlchemySyncRepository,
)
Loading
Loading