Skip to content

Commit

Permalink
Merge branch 'main' into sqla-conf-create-engine
Browse files Browse the repository at this point in the history
  • Loading branch information
cofin authored Sep 30, 2023
2 parents 3d1b551 + 2756f7e commit 1dce0e7
Show file tree
Hide file tree
Showing 14 changed files with 565 additions and 402 deletions.
8 changes: 8 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# [Choice] Python version (use -bookworm or -bullseye variants on local arm64/Apple Silicon): 3, 3.11, 3.10, 3.9, 3.8, 3-bookworm, 3.11-bookworm, 3.10-bookworm, 3.9-bookworm, 3.8-bookworm, 3-bullseye, 3.11-bullseye, 3.10-bullseye, 3.9-bullseye, 3.8-bullseye, 3-buster, 3.11-buster, 3.10-buster, 3.9-buster, 3.8-buster
ARG VARIANT=3-bookworm
FROM python:${VARIANT}

RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
&& apt-get purge -y fish

RUN python3 -m pip install --upgrade setuptools cython pip poetry
70 changes: 70 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{
"name": "litestar-org/litestar",
"build": {
"dockerfile": "./Dockerfile",
"context": "."
},
"features": {
"ghcr.io/devcontainers/features/common-utils:2": {
"installZsh": "true",
"username": "vscode",
"userUid": "1000",
"userGid": "1000",
"upgradePackages": "true"
},
"ghcr.io/devcontainers/features/github-cli:1": {},
"ghcr.io/devcontainers-contrib/features/pre-commit:2": {},
"ghcr.io/devcontainers/features/python:1": "none",
"ghcr.io/devcontainers/features/git:1": {
"version": "latest",
"ppa": "false"
}
},
"customizations": {
"codespaces": {
"openFiles": ["CONTRIBUTING.rst"]
},
"vscode": {
"extensions": [
"mhutchie.git-graph",
"eamodio.gitlens",
"github.vscode-github-actions",
"ms-python.black-formatter",
"ms-python.mypy-type-checker",
"charliermarsh.ruff"
],
"settings": {
"python.editor.defaultFormatter": "ms-python.black-formatter",
"python.defaultInterpreterPath": "${workspaceFolder}/.venv",
"python.terminal.activateEnvInCurrentTerminal": true,
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true,
"python.testing.pytestArgs": ["."],
"python.terminal.launchArgs": ["-X", "dev"],
"terminal.integrated.shell.linux": "/bin/bash",
"terminal.integrated.profiles.linux": {
"bash": {
"path": "bash",
"icon": "terminal-bash"
},
"zsh": {
"path": "zsh"
},
"fish": {
"path": "fish"
}
}
}
}
},
"forwardPorts": [8000],
"postCreateCommand": [
"poetry",
"install",
"--extras",
"full",
"--with",
"docs,lint"
],
"remoteUser": "vscode"
}
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ repos:
sqlalchemy>=2.0.12,
starlette,
structlog,
advanced-alchemy==0.2.1,
advanced-alchemy==0.2.2,
time-machine,
types-beautifulsoup4,
types-python-jose,
Expand Down Expand Up @@ -176,7 +176,7 @@ repos:
rich,
rich-click,
sqlalchemy>=2.0.12,
advanced-alchemy==0.2.1,
advanced-alchemy==0.2.2,
starlette,
structlog,
time-machine,
Expand Down
2 changes: 2 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@
(PY_CLASS, "advanced_alchemy.types.BigIntIdentity"),
(PY_FUNC, "sqlalchemy.get_engine"),
(PY_ATTR, "advanced_alchemy.repository.AbstractAsyncRepository.id_attribute"),
("py:exc", "RepositoryError"),
]

nitpick_ignore_regex = [
Expand All @@ -180,6 +181,7 @@
(PY_RE, r"litestar\.connection\.base\.UserT"),
(PY_RE, r"litestar\.pagination\.C"),
(PY_RE, r"multidict\..*"),
(PY_RE, r"advanced_alchemy.*\.T"),
]

# Warnings about missing references to those targets in the specified location will be ignored.
Expand Down
3 changes: 1 addition & 2 deletions docs/reference/repository/exceptions.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
exceptions
==========

.. automodule:: litestar.repository.exceptions
:members:
This page has moved to :doc:`advanced-alchemy:reference/filters`
3 changes: 1 addition & 2 deletions docs/reference/repository/filters.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
filters
=======

.. automodule:: litestar.repository.filters
:members:
This page has moved to :doc:`advanced-alchemy:reference/filters`
3 changes: 2 additions & 1 deletion litestar/_openapi/schema_generation/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
create_numerical_constrained_field_schema,
create_string_constrained_field_schema,
)
from litestar._openapi.schema_generation.examples import create_examples_for_field
from litestar._openapi.schema_generation.utils import sort_schemas_and_references
from litestar.datastructures import UploadFile
from litestar.exceptions import ImproperlyConfiguredException
Expand Down Expand Up @@ -586,6 +585,8 @@ def process_schema_result(self, field: FieldDefinition, schema: Schema) -> Schem
setattr(schema, schema_key, value)

if not schema.examples and self.generate_examples:
from litestar._openapi.schema_generation.examples import create_examples_for_field

schema.examples = create_examples_for_field(field)

if schema.title and schema.type in (OpenAPIType.OBJECT, OpenAPIType.ARRAY):
Expand Down
15 changes: 15 additions & 0 deletions litestar/repository/_exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from __future__ import annotations

__all__ = ("ConflictError", "NotFoundError", "RepositoryError")


class RepositoryError(Exception):
"""Base repository exception type."""


class ConflictError(RepositoryError):
"""Data integrity error."""


class NotFoundError(RepositoryError):
"""An identity does not exist."""
116 changes: 116 additions & 0 deletions litestar/repository/_filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
"""Collection filter datastructures."""
from __future__ import annotations

from collections import abc # noqa: TCH003
from dataclasses import dataclass
from datetime import datetime # noqa: TCH003
from typing import TYPE_CHECKING, Any, Generic, Literal, TypeVar

if TYPE_CHECKING:
from typing_extensions import TypeAlias

T = TypeVar("T")

__all__ = (
"BeforeAfter",
"CollectionFilter",
"FilterTypes",
"LimitOffset",
"OrderBy",
"SearchFilter",
"NotInCollectionFilter",
"OnBeforeAfter",
"NotInSearchFilter",
)


FilterTypes: TypeAlias = "BeforeAfter | OnBeforeAfter | CollectionFilter[Any] | LimitOffset | OrderBy | SearchFilter | NotInCollectionFilter[Any] | NotInSearchFilter"
"""Aggregate type alias of the types supported for collection filtering."""


@dataclass
class BeforeAfter:
"""Data required to filter a query on a ``datetime`` column."""

field_name: str
"""Name of the model attribute to filter on."""
before: datetime | None
"""Filter results where field earlier than this."""
after: datetime | None
"""Filter results where field later than this."""


@dataclass
class OnBeforeAfter:
"""Data required to filter a query on a ``datetime`` column."""

field_name: str
"""Name of the model attribute to filter on."""
on_or_before: datetime | None
"""Filter results where field is on or earlier than this."""
on_or_after: datetime | None
"""Filter results where field on or later than this."""


@dataclass
class CollectionFilter(Generic[T]):
"""Data required to construct a ``WHERE ... IN (...)`` clause."""

field_name: str
"""Name of the model attribute to filter on."""
values: abc.Collection[T]
"""Values for ``IN`` clause."""


@dataclass
class NotInCollectionFilter(Generic[T]):
"""Data required to construct a ``WHERE ... NOT IN (...)`` clause."""

field_name: str
"""Name of the model attribute to filter on."""
values: abc.Collection[T]
"""Values for ``NOT IN`` clause."""


@dataclass
class LimitOffset:
"""Data required to add limit/offset filtering to a query."""

limit: int
"""Value for ``LIMIT`` clause of query."""
offset: int
"""Value for ``OFFSET`` clause of query."""


@dataclass
class OrderBy:
"""Data required to construct a ``ORDER BY ...`` clause."""

field_name: str
"""Name of the model attribute to sort on."""
sort_order: Literal["asc", "desc"] = "asc"
"""Sort ascending or descending"""


@dataclass
class SearchFilter:
"""Data required to construct a ``WHERE field_name LIKE '%' || :value || '%'`` clause."""

field_name: str
"""Name of the model attribute to sort on."""
value: str
"""Values for ``LIKE`` clause."""
ignore_case: bool | None = False
"""Should the search be case insensitive."""


@dataclass
class NotInSearchFilter:
"""Data required to construct a ``WHERE field_name NOT LIKE '%' || :value || '%'`` clause."""

field_name: str
"""Name of the model attribute to search on."""
value: str
"""Values for ``NOT LIKE`` clause."""
ignore_case: bool | None = False
"""Should the search be case insensitive."""
17 changes: 4 additions & 13 deletions litestar/repository/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,6 @@
from __future__ import annotations
try:
from advanced_alchemy.exceptions import ConflictError, NotFoundError, RepositoryError
except ImportError:
from ._exceptions import ConflictError, NotFoundError, RepositoryError # type: ignore[assignment]

__all__ = ("ConflictError", "NotFoundError", "RepositoryError")


class RepositoryError(Exception):
"""Base repository exception type."""


class ConflictError(RepositoryError):
"""Data integrity error."""


class NotFoundError(RepositoryError):
"""An identity does not exist."""
Loading

0 comments on commit 1dce0e7

Please sign in to comment.