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: adds a granian optional installation group #4051

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
6 changes: 3 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ default_language_version:
python: "3.12"
repos:
- repo: https://github.com/compilerla/conventional-pre-commit
rev: v3.6.0
rev: v4.0.0
hooks:
- id: conventional-pre-commit
stages: [commit-msg]
Expand All @@ -24,13 +24,13 @@ repos:
- id: unasyncd
additional_dependencies: ["ruff"]
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.8.1"
rev: "v0.9.10"
hooks:
- id: ruff
args: ["--fix"]
- id: ruff-format
- repo: https://github.com/codespell-project/codespell
rev: v2.3.0
rev: v2.4.1
hooks:
- id: codespell
exclude: "tests/openapi/typescript_converter/test_converter|README.md"
Expand Down
Binary file added docs/_static/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 31 additions & 0 deletions docs/_static/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class SlugKey:
slug: Mapped[str] = mapped_column(String(length=100), nullable=False, unique=True, sort_order=-9)


# this class can be re-used with any model that has the `SlugKey` Mixin
# this class can be reused with any model that has the `SlugKey` Mixin
class SQLAlchemyAsyncSlugRepository(SQLAlchemyAsyncRepository[ModelT]):
"""Extends the repository to include slug model features.."""

Expand Down
2 changes: 1 addition & 1 deletion docs/release-notes/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2876,7 +2876,7 @@
.. changelog:: 2.3.2
:date: 2023/11/06

.. change:: Fix recursion error when re-using the path of a route handler for static files
.. change:: Fix recursion error when reusing the path of a route handler for static files
:type: bugfix
:pr: 2630
:issue: 2629
Expand Down
2 changes: 1 addition & 1 deletion docs/usage/stores.rst
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ with minimal boilerplate:


Without any extra configuration, every call to ``app.stores.get`` with a unique name will return a namespace for this
name only, while re-using the underlying Redis instance.
name only, while reusing the underlying Redis instance.


Store lifetime
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def create_string_constrained_field_schema(
schema.max_length = kwarg_definition.max_length
if kwarg_definition.pattern:
schema.pattern = (
kwarg_definition.pattern.pattern # type: ignore[attr-defined]
kwarg_definition.pattern.pattern # type: ignore[attr-defined,unused-ignore]
if isinstance(kwarg_definition.pattern, Pattern) # type: ignore[unreachable]
else kwarg_definition.pattern
)
Expand Down
2 changes: 1 addition & 1 deletion litestar/cli/commands/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ def _handle_http_route(self, route: HTTPRoute) -> None:
else:
handler_info.append("[yellow]sync[/yellow]")

handler_info.append(f'[cyan]{", ".join(sorted(handler.http_methods))}[/cyan]')
handler_info.append(f"[cyan]{', '.join(sorted(handler.http_methods))}[/cyan]")

if len(handler.paths) > 1:
for path in handler.paths:
Expand Down
2 changes: 1 addition & 1 deletion litestar/contrib/htmx/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from litestar.utils import warn_deprecation

if TYPE_CHECKING:
from litestar_htmx._utils import ( # noqa: TC004
from litestar_htmx._utils import (
HTMXHeaders,
get_headers,
get_location_headers,
Expand Down
2 changes: 1 addition & 1 deletion litestar/contrib/htmx/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from litestar.utils import warn_deprecation

if TYPE_CHECKING:
from litestar_htmx import ( # noqa: TC004
from litestar_htmx import (
HTMXDetails,
HTMXRequest,
)
Expand Down
2 changes: 1 addition & 1 deletion litestar/contrib/htmx/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from litestar.utils import warn_deprecation

if TYPE_CHECKING:
from litestar_htmx import ( # noqa: TC004
from litestar_htmx import (
ClientRedirect,
ClientRefresh,
HTMXTemplate,
Expand Down
2 changes: 1 addition & 1 deletion litestar/contrib/htmx/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from litestar.utils import warn_deprecation

if TYPE_CHECKING:
from litestar_htmx import HtmxHeaderType, LocationType, TriggerEventType # noqa: TC004
from litestar_htmx import HtmxHeaderType, LocationType, TriggerEventType
__all__ = (
"HtmxHeaderType",
"LocationType",
Expand Down
2 changes: 1 addition & 1 deletion litestar/contrib/piccolo.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def _parse_piccolo_type(column: Column, extra: dict[str, Any]) -> FieldDefinitio
if is_optional:
meta = Meta(extra=extra)
warnings.warn(
f"Dropping max_length constraint for column {column!r} because the " "column is optional",
f"Dropping max_length constraint for column {column!r} because the column is optional",
category=LitestarWarning,
stacklevel=2,
)
Expand Down
2 changes: 1 addition & 1 deletion litestar/openapi/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ def render_swagger_ui(self, request: Request[Any, Any, Any]) -> bytes:
SwaggerUIBundle.SwaggerUIStandalonePreset
],
}})
ui.initOAuth({encode_json(self.swagger_ui_init_oauth).decode('utf-8')})
ui.initOAuth({encode_json(self.swagger_ui_init_oauth).decode("utf-8")})
</script>
</body>
"""
Expand Down
2 changes: 1 addition & 1 deletion litestar/utils/sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class AsyncCallable:
def __init__(self, fn: Callable[P, T]) -> None: # pyright: ignore
self.func = fn

def __call__(self, *args: P.args, **kwargs: P.kwargs) -> Awaitable[T]: # pyright: ignore
def __call__(self, *args: P.args, **kwargs: P.kwargs) -> Awaitable[T]: # type: ignore[valid-type,unused-ignore] # pyright: ignore
return sync_to_thread(self.func, *args, **kwargs) # type: ignore[arg-type]


Expand Down
6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ full = [
"litestar[annotated-types,attrs,brotli,cli,cryptography,jinja,jwt,mako,minijinja,opentelemetry,piccolo,picologging,prometheus,pydantic,redis,sqlalchemy,standard,structlog,valkey]; python_version < \"3.13\"",
"litestar[annotated-types,attrs,brotli,cli,cryptography,jinja,jwt,mako,minijinja,opentelemetry,piccolo,prometheus,pydantic,redis,sqlalchemy,standard,structlog,valkey]; python_version >= \"3.13\"",
]
granian = ["litestar-granian", "uvloop>=0.18.0; sys_platform != 'win32'", "python-dotenv", "websockets"]
jinja = ["jinja2>=3.1.2"]
jwt = ["cryptography", "pyjwt>=2.9.0"]
mako = ["mako>=1.2.4"]
Expand Down Expand Up @@ -138,9 +139,7 @@ dev = [
"trio",
"aiosqlite",
"asyncpg>=0.29.0",
"psycopg[pool,binary]>=3.1.10,<3.2; python_version < \"3.13\"",
"psycopg[pool,c]; python_version >= \"3.13\" and sys_platform == 'linux'",
"psycopg[pool]; python_version >= \"3.13\" and sys_platform != 'linux'",
"psycopg[pool,binary]",
"psycopg2-binary",
"psutil>=5.9.8",
"hypercorn>=0.16.0",
Expand Down Expand Up @@ -422,6 +421,7 @@ lint.ignore = [
"RUF012", # Ruff-specific rule - annotated with classvar
"ISC001", # Ruff formatter incompatible
"CPY001", # ruff - copyright notice at the top of the file
"A005", # Module shadows a Python standard-library module
]
src = ["litestar", "tests", "docs/examples"]
target-version = "py38"
Expand Down
8 changes: 4 additions & 4 deletions tests/e2e/test_pydantic.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,15 @@ async def test(data: TestDto) -> str:
"responses": {
"201": {
"content": {"text/plain": {"schema": {"type": "string"}}},
"description": "Document " "created, " "URL " "follows",
"description": "Document created, URL follows",
"headers": {},
},
"400": {
"content": {
"application/json": {
"schema": {
"description": "Validation " "Exception",
"examples": [{"detail": "Bad " "Request", "extra": {}, "status_code": 400}],
"description": "Validation Exception",
"examples": [{"detail": "Bad Request", "extra": {}, "status_code": 400}],
"properties": {
"detail": {"type": "string"},
"extra": {
Expand All @@ -91,7 +91,7 @@ async def test(data: TestDto) -> str:
}
}
},
"description": "Bad " "request " "syntax or " "unsupported " "method",
"description": "Bad request syntax or unsupported method",
},
},
"summary": "Test",
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/test_openapi/test_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ def test_create_schema_for_dataclass_with_annotated_model_attribute(
"""Test that a model with an annotated attribute is correctly handled."""
module = create_module(
f"""
{'from __future__ import annotations' if with_future_annotations else ''}
{"from __future__ import annotations" if with_future_annotations else ""}
from typing_extensions import Annotated
from dataclasses import dataclass

Expand All @@ -277,7 +277,7 @@ def test_create_schema_for_typedict_with_annotated_required_and_not_required_mod
"""Test that a model with an annotated attribute is correctly handled."""
module = create_module(
f"""
{'from __future__ import annotations' if with_future_annotations else ''}
{"from __future__ import annotations" if with_future_annotations else ""}
from typing_extensions import Annotated, Required, NotRequired
from typing import TypedDict

Expand Down
4 changes: 2 additions & 2 deletions tests/unit/test_plugins/test_pydantic/test_openapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -744,9 +744,9 @@ def test_create_schema_for_pydantic_model_with_annotated_model_attribute(
"""Test that a model with an annotated attribute is correctly handled."""
module = create_module(
f"""
{'from __future__ import annotations' if with_future_annotations else ''}
{"from __future__ import annotations" if with_future_annotations else ""}
from typing_extensions import Annotated
{'from pydantic import BaseModel' if pydantic_version == 'v2' else 'from pydantic.v1 import BaseModel'}
{"from pydantic import BaseModel" if pydantic_version == "v2" else "from pydantic.v1 import BaseModel"}

class Foo(BaseModel):
foo: Annotated[int, "Foo description"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ def test_decode_json_raises_serialization_exception(model: ModelV1 | ModelV2, de
def test_decode_json_typed(model: ModelV1 | ModelV2, prefer_alias: bool, model_type: type[ModelV1 | ModelV2]) -> None:
dumped_model = _model_dump_json(model, by_alias=prefer_alias)
decoded_model = decode_json(value=dumped_model, target_type=model_type, type_decoders=PydanticInitPlugin.decoders())
assert _model_dump_json(decoded_model, by_alias=prefer_alias) == dumped_model # type: ignore[arg-type]
assert _model_dump_json(decoded_model, by_alias=prefer_alias) == dumped_model # type: ignore[arg-type,unused-ignore]


@pytest.mark.parametrize("prefer_alias", [False, True])
Expand All @@ -257,6 +257,6 @@ def test_decode_msgpack_typed(
encode_msgpack(model, serializer=get_serializer(PydanticInitPlugin.encoders(prefer_alias=prefer_alias))),
model_type,
type_decoders=PydanticInitPlugin.decoders(),
).json() # type: ignore[attr-defined]
).json() # type: ignore[attr-defined,unused-ignore]
== model_json
)
2 changes: 1 addition & 1 deletion tests/unit/test_template/test_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def index() -> Template:
res = client.get("/")
assert res.status_code == 200
assert res.headers["content-type"].startswith(
media_type if isinstance(media_type, str) else media_type.value, # type: ignore[union-attr]
media_type if isinstance(media_type, str) else media_type.value, # type: ignore[union-attr,unused-ignore]
)


Expand Down
Loading
Loading