2.x Changelog#

2.13.0#

Released: 2024-11-20

Features#

Add request_max_body_size layered parameter#

Add a new request_max_body_size layered parameter, which limits the maximum size of a request body before returning a 413 - Request Entity Too Large.

See also

Limits

References:

Send CSRF request header in OpenAPI plugins#

Supported OpenAPI UI clients will extract the CSRF cookie value and attach it to the request headers if CSRF is enabled on the application.

References: litestar-org/litestar#3754

deprecate litestar.contrib.sqlalchemy#

Deprecate the litestar.contrib.sqlalchemy module in favor of litestar.plugins.sqlalchemy

References: litestar-org/litestar#3755

implement HTMX plugin using litestar-htmx#

This plugin migrates the HTMX integration to litestar.plugins.htmx.

This logic has been moved to it’s own repository named litestar-htmx

References: litestar-org/litestar#3837

Pydantic: honor hide_input_in_errors in throwing validation exceptions#

Pydantic’s BaseModel supports configuration to hide data values when throwing exceptions, via setting hide_input_in_errors – see https://docs.pydantic.dev/2.0/api/config/#pydantic.config.ConfigDict.hide_input_in_errors and https://docs.pydantic.dev/latest/usage/model_config/#hide-input-in-errors

Litestar will now honour this setting

References: litestar-org/litestar#3843

deprecate``litestar.contrib.pydantic``#

## Description

Deprecate litestar.contrib.pydantic in favor of litestar.plugins.pydantic

References: litestar-org/litestar#3787, litestar-org/litestar#3852

Bugfixes#

Fix sign bug in rate limit middelware#

Fix a bug in the rate limit middleware, that would cause the response header fields RateLimit-Remaining and RateLimit-Reset to have negative values.

References: litestar-org/litestar#3776

OpenAPI: map JSONSchema spec naming convention to snake_case when names from schema_extra are not found#

Address rejection of schema_extra values using JSONSchema spec-compliant key names by mapping between the relevant naming conventions.

References: litestar-org/litestar#3766, litestar-org/litestar#3767

Use correct path template for routes without path parameters#

Fix a but where, when using PrometheusConfig.group_path=True, the metrics exporter response content would ignore all paths with no path parameters.

References: litestar-org/litestar#3784

Fix a dangling anyio stream in TestClient#

Fix a dangling anyio stream in TestClient that would cause a resource warning

Closes #3834.

References: litestar-org/litestar#3834, litestar-org/litestar#3836

Fix bug in handling of missing more_body key in ASGI response#

Some frameworks do not include the more_body key in the “http.response.body” ASGI event. According to the ASGI specification, this key should be set to False when there is no additional body content. Litestar expects more_body to be explicitly defined, but others might not.

This leads to failures when an ASGI framework mounted on Litestar throws error if this key is missing.

References: litestar-org/litestar#3845

Fix duplicate RateLimit-* headers with caching#

Fix a bug where RateLimitMiddleware duplicate all RateLimit-* headers when handler cache is enabled.

References: litestar-org/litestar#3625, litestar-org/litestar#3855

2.12.1#

Released: 2024-09-21

Bugfixes#

Fix base package requiring annotated_types dependency#

Fix a bug introduced in #3721 that was released with 2.12.0 caused an ImportError when the annotated_types package was not installed.

References: litestar-org/litestar#3749, litestar-org/litestar#3750

2.12.0#

Released: 2024-09-21

Features#

Support strings in media_type for ResponseSpec#

Accept strings for the media_type parameter of ResponseSpec, making it behave the same way as media_type.

References: litestar-org/litestar#3728, litestar-org/litestar#3729

OpenAPI: Allow customizing schema component keys#

Allow customizing the schema key used for a component in the OpenAPI schema. The supplied keys are enforced to be unique, and it is checked that they won’t be reused across different types.

The keys can be set with the newly introduced schema_component_key parameter, which is available on KwargDefinition, Body() and Parameter().

Two components will be generated: Data and not_data#
@dataclass
class Data:
    pass

@post("/")
def handler(
    data: Annotated[Data, Parameter(schema_component_key="not_data")],
) -> Data:
    return Data()

@get("/")
def handler_2() -> Annotated[Data, Parameter(schema_component_key="not_data")]:
    return Data()

References: litestar-org/litestar#3738

Raise exception when body parameter is annotated with non-bytes type#

Add an informative error message to help avoid the common mistake of attempting to use the body parameter to receive validated / structured data by annotating it with a type such as list[str], instead of bytes.

References: litestar-org/litestar#3740

OpenAPI: Default to latest scalar version#

Change the default version of the scalar OpenAPI renderer to latest

References: litestar-org/litestar#3747

Bugfixes#

Fix overzealous warning for greedy middleware exclude pattern#

Fix a bug introduced in 2.11.0 (litestar-org/litestar#3700), where the added warning for a greedy pattern use for the middleware exclude parameter was itself greedy, and would warn for non-greedy patterns, e.g. ^/$.

References: litestar-org/litestar#3712

Fix dangling coroutines in request extraction handling cleanup#

Fix a bug where, when a required header parameter was defined for a request that also expects a request body, failing to provide the header resulted in a RuntimeWarning.

@post()
async def handler(data: str, secret: Annotated[str, Parameter(header="x-secret")]) -> None:
    return None

If the x-secret header was not provided, warning like this would be seen:

RuntimeWarning: coroutine 'json_extractor' was never awaited

References: litestar-org/litestar#3734, litestar-org/litestar#3735

OpenAPI: Correctly handle type keyword#

Fix a bug where a type alias created with the type keyword would create an empty OpenAPI schema entry for that parameter

References: litestar-org/litestar#3714, litestar-org/litestar#3715

OpenAPI: Ensure valid schema keys#

Ensure that generated schema component keys are always valid according to § 4.8.7.1 of the OpenAPI specification.

References: litestar-org/litestar#3630, litestar-org/litestar#3635

OpenAPI: Correctly handle msgspec.Struct tagged unions#

Fix a bug where the OpenAPI schema would not include the struct fields implicitly generated by msgspec for its tagged union support.

The tag field of the struct will now be added as a const of the appropriate type to the schema.

References: litestar-org/litestar#3659, litestar-org/litestar#3742

OpenAPI: Fix Pydantic 1 constrained string with default factory#

Fix a bug where using a Pydantic model with a default_factory set for a constrained string field would raise a SerializationException.

class Model(BaseModel):
    field: str = Field(default_factory=str, max_length=600)

References: litestar-org/litestar#3710, litestar-org/litestar#3721

OpenAPI/DTO: Fix missing Pydantic 2 computed fields#

Fix a bug that would lead to Pydantic computed fields to be ignored during schema generation when the model was using a PydanticDTO.

Only the foo field would be included in the schema#
class MyModel(BaseModel):
    foo: int

    @computed_field
    def bar(self) -> int:
        return 123

@get(path="/", return_dto=PydanticDTO[MyModel])
async def test() -> MyModel:
    return MyModel.model_validate({"foo": 1})

References: litestar-org/litestar#3656, litestar-org/litestar#3721

OpenAPI: Fix Pydantic json_schema_extra overrides only being merged partially#

Fix a bug where json_schema_extra were not reliably extracted from Pydantic models and included in the OpenAPI schema.

Only the title set directly on the field would be used for the schema#
class Model(pydantic.BaseModel):
    with_title: str = pydantic.Field(title="new_title")
    with_extra_title: str = pydantic.Field(json_schema_extra={"title": "more_new_title"})


@get("/example")
async def example_route() -> Model:
    return Model(with_title="1", with_extra_title="2")

References: litestar-org/litestar#3656, litestar-org/litestar#3721

2.11.0#

Released: 2024-08-27

Features#

Use PyJWT instead of python-jose#

The functionality in litestar.security.jwt is now backed by PyJWT instead of python-jose, due to the unclear maintenance status of the latter.

References: litestar-org/litestar#3684

DTO: Introduce forbid_unknown_fields config#

Add a new config option to DTOConfig: forbid_unknown_fields When set to True, a validation error response will be returned if the source data contains fields not defined on the model.

References: litestar-org/litestar#3690

DTO: Support extra="forbid" model config for PydanticDTO#

For Pydantic models with extra=”forbid” in their configuration:

class User(BaseModel):
    model_config = ConfigDict(extra='ignore')
    name: str
class User(BaseModel):
    class Config:
        extra = "ignore"
    name: str

forbid_unknown_fields will be set to True by default.

Note

It’s still possible to override this configuration at the DTO level

To facilitate this feature, get_config_for_model_type() has been added to AbstractDTO, allowing the customization of the base config defined on the DTO factory for a specific model type. It will be called on DTO factory initialization, and receives the concrete DTO model type along side the DTOConfig defined on the base DTO, which it can alter and return a new version to be used within the DTO instance.

References: litestar-org/litestar#3691

Custom JWT payload classes#

Support extending the default Token class used by the JWT backends decode the payload into.

  • Add new token_cls field on the JWT auth config classes

  • Add new token_cls parameter to JWT auth middlewares

  • Switch to using msgspec to convert the JWT payload into instances of the token class

import dataclasses
import secrets
from typing import Any, Dict

from litestar import Request, get
from litestar.connection import ASGIConnection
from litestar.security.jwt import JWTAuth, Token

@dataclasses.dataclass
class CustomToken(Token):
    token_flag: bool = False

@dataclasses.dataclass
class User:
    id: str

async def retrieve_user_handler(token: CustomToken, connection: ASGIConnection) -> User:
    return User(id=token.sub)

TOKEN_SECRET = secrets.token_hex()

jwt_auth = JWTAuth[User](
    token_secret=TOKEN_SECRET,
    retrieve_user_handler=retrieve_user_handler,
    token_cls=CustomToken,
)

@get("/")
def handler(request: Request[User, CustomToken, Any]) -> Dict[str, Any]:
    return {"id": request.user.id, "token_flag": request.auth.token_flag}
import dataclasses
import secrets
from typing import Any

from litestar import Request, get
from litestar.connection import ASGIConnection
from litestar.security.jwt import JWTAuth, Token

@dataclasses.dataclass
class CustomToken(Token):
    token_flag: bool = False

@dataclasses.dataclass
class User:
    id: str

async def retrieve_user_handler(token: CustomToken, connection: ASGIConnection) -> User:
    return User(id=token.sub)

TOKEN_SECRET = secrets.token_hex()

jwt_auth = JWTAuth[User](
    token_secret=TOKEN_SECRET,
    retrieve_user_handler=retrieve_user_handler,
    token_cls=CustomToken,
)

@get("/")
def handler(request: Request[User, CustomToken, Any]) -> dict[str, Any]:
    return {"id": request.user.id, "token_flag": request.auth.token_flag}

References: litestar-org/litestar#3692

Extended JWT configuration options#

New JWT backend fields

New JWT middleware parameters

New ``Token.decode`` parameters

Other changes

:meth`Token.decode_payload <~litestar.security.jwt.Token.decode_payload>` has been added to make customization of payload decoding / verification easier without having to re-implement the functionality of the base class method.

References: litestar-org/litestar#3695

Warn about greedy exclude patterns in middlewares#

Raise a warning when a middlewares exclude pattern greedily matches all paths.

from litestar.middlewares

class MyMiddleware(AbstractMiddleware):
    exclude = ["/", "/home"]

    async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
        await self.app(scope, receive, send)

Middleware like this would silently be disabled for every route, since the exclude pattern / matches all paths. If a configuration like this is detected, a warning will now be raised at application startup.

References: litestar-org/litestar#3700

RFC 9457 Problem Details plugin#

Add a plugin to support RFC 9457 Problem Details responses for error response.

ProblemDetailsPlugin enables to selectively or collectively turn responses with an error status code into Problem Detail responses.

See also

Problem Details

References: litestar-org/litestar#3199, litestar-org/litestar#3323

Bugfixes#

Fix creation of FormMultiDict in Request.form to properly handle multi-keys#

Fix litestar-org/litestar#3627 by properly handling the creation of FormMultiDict where multiple values are given for a single key, to make form() match the behaviour of receiving form data via the data kwarg inside a route handler.

Before

@post("/")
async def handler(request: Request) -> Any:
    return (await request.form()).getall("foo")

with create_test_client(handler) as client:
    print(client.post("/", data={"foo": ["1", "2"]}).json()) # [["1", "2"]]

After

@post("/")
async def handler(request: Request) -> Any:
    return (await request.form()).getall("foo")

with create_test_client(handler) as client:
    print(client.post("/", data={"foo": ["1", "2"]}).json()) # ["1", "2"]

References: litestar-org/litestar#3627, litestar-org/litestar#3639

DTO: Fix inconsistent use of strict decoding mode#

Fix inconsistent usage of msgspec’s strict mode in the base DTO backend.

strict=False was being used when transferring from builtins, while strict=True was used transferring from raw data, causing an unwanted discrepancy in behaviour.

References: litestar-org/litestar#3685

Use path template for prometheus metrics#

Changed previous 1-by-1 replacement logic for PrometheusMiddleware.group_path=true with a more robust and slightly faster solution.

References: litestar-org/litestar#3687

Ensure OpenTelemetry captures exceptions in the outermost application layers#

A bug was fixed that resulted in exception occurring in the outermost application layer not being captured under the current request span, which led to incomplete traces.

References: litestar-org/litestar#3663, litestar-org/litestar#3689

Fix CSRFMiddleware sometimes setting cookies for excluded paths#

Fix a bug that would cause CSRFMiddleware to set a cookie (which would not be used subsequently) on routes it had been excluded from via a path pattern.

References: litestar-org/litestar#3688, litestar-org/litestar#3698

Make override behaviour consistent between signature_namespace and signature_types#

Ensure that adding signature types to signature_namespace and signature_types behaves the same way when a name was already present in the namespace.

Both will now issue a warning if a name is being overwritten with a different type. If a name is registered again for the same type, no warning will be given.

Note

You can disable this warning globally by setting LITESTAR_WARN_SIGNATURE_NAMESPACE_OVERRIDE=0 in your environment

References: litestar-org/litestar#3681, litestar-org/litestar#3696

2.10.0#

Released: 2024-07-26

Features#

Allow creating parent directories for a file store#

Allow mkdir True when creating a file store.

References: litestar-org/litestar#3526

Add logging_module parameter to LoggingConfig#

Provide a way in the logging_module to switch easily from logging to picologging.

References: litestar-org/litestar#3536, litestar-org/litestar#3578

Add handler name to exceptions in handler validation#

Add handler name to exceptions raise by _validate_handler_function.

References: litestar-org/litestar#3575

Add strict validation support for Pydantic plugin#

Adds parameters in pydantic plugin to support strict validation and all the model_dump args

References: litestar-org/litestar#3572, litestar-org/litestar#3608

Bugfixes#

Fix signature model signatures clash#

Ensures that the functions used by the signature model itself do not interfere with the signature model created.

References: litestar-org/litestar#3593, litestar-org/litestar#3605

Correctly handle Annotated NewType#

Resolves infinite loop in schema generation when a model has an Annotated NewType.

References: litestar-org/litestar#3614, litestar-org/litestar#3615

Use ASGIConnection instead of Request for flash#

Currently, the FlashPlugin expects the request parameter to be a type of Request. However, there’s no reason it can’t use the parent class ASGIConnection.

Doing this, allows for flash to be called in guards that expect an ASGIConnection instead of Request:

def requires_active_user(connection: ASGIConnection, _: BaseRouteHandler) -> None:
    if connection.user.is_active:
        return
    msg = "Your user account is inactive."
    flash(connection, msg, category="error")
    raise PermissionDeniedException(msg)

References: litestar-org/litestar#3626

Allow returning Response[None] from head route handlers#

Fix a bug where the validation of the return annotation for the head route handler was too strict and would not allow returning a Response[None].

References: litestar-org/litestar#3640, litestar-org/litestar#3641

2.9.1#

Released: 2024-06-21

Bugfixes#

Add OPTIONS to the default safe methods for CSRFConfig#

Add OPTIONS to the default safe methods for CSRFConfig

References: litestar-org/litestar#3538

Prometheus: Capture templated route name for metrics#

Adding new extraction function for prometheus metrics to avoid high cardinality issue in prometheus, eg having metrics GET /v1/users/{id} is preferable over GET /v1/users/1, GET /v1/users/2,GET /v1/users/3

More info about prometheus high cardinality https://grafana.com/blog/2022/02/15/what-are-cardinality-spikes-and-why-do-they-matter/

References: litestar-org/litestar#3533

Respect base_url in .websocket_connect#

Fix a bug that caused websocket_connect() / websocket_connect() to not respect the base_url set in the client’s constructor, and instead would use the static ws://testerver URL as a base.

Also removes most of the test client code as it was unneeded and in the way of this fix :)

Explanation for the last part: All the extra code we had was just proxying method calls to the httpx.Client / httpx.AsyncClient, while altering the base URL. Since we already set the base URL on the httpx Client’s superclass instance, which in turn does this merging internally, this step isn’t needed at all.

References: litestar-org/litestar#3567

Fix deprecation warning for subclassing route handler decorators#

Fix an issue where there was a deprecation warning emitted by all route handler decorators. This warning was introduced in 2.9.0 to warn about the upcoming deprecation, but should have only applied to user subclasses of the handler classes, and not the built-in ones (get, post, etc.)

References: litestar-org/litestar#3552, litestar-org/litestar#3569

CLI: Don’t call rich_click.patch if rich_click is installed#

Don’t call rich_click.patch if rich_click is installed. As this monkey patches click globally, it can introduce unwanted side effects. Instead, use conditional imports to refer to the correct library.

External libraries will still be able to make use of rich_click implicitly when it’s installed by inheriting from LitestarGroup / LitestarExtensionGroup, which they will by default.

References: litestar-org/litestar#3534, litestar-org/litestar#3570

Correctly handle typing.NewType#

When encountering a typing.NewType during OpenAPI schema generation, we currently treat it as an opaque type. This PR changes the behaviour such that :class`typing.NewType`s are always unwrapped during schema generation.

References: litestar-org/litestar#3580

Encode response content object returned from an exception handler.#

When an handler raises an exception and exception handler returns a Response with a model (e.g. pydantic) object, ensure that object can be encoded as when returning data from a regular handler.

References: litestar-org/litestar#3585

2.9.0#

Released: 2024-06-02

Features#

Add async websocket_connect to AsyncTestClient#

Add async websocket_connect to AsyncTestClient

References: litestar-org/litestar#3133, litestar-org/litestar#3328

add SecretString and SecretBytes datastructures#

Implement SecretString and SecretBytes data structures to hide sensitive data in tracebacks, etc.

References: litestar-org/litestar#1312,, litestar-org/litestar#3248, litestar-org/litestar#3322

Deprecate subclassing route handler decorators#

Deprecation for the 2.x release line of the semantic route handler classes removed in #3436.

References: litestar-org/litestar#3439

Bugfixes#

asgi lifespan msg after lifespan context exception#

An exception raised within an asgi lifespan context manager would result in a “lifespan.startup.failed” message being sent after we’ve already sent a “lifespan.startup.complete” message. This would cause uvicorn to raise a STATE_TRANSITION_ERROR assertion error due to their check for that condition , if asgi lifespan is forced (i.e., with $ uvicorn test_apps.test_app:app --lifespan on).

E.g.,

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/peter/.local/share/pdm/venvs/litestar-dj-FOhMr-3.8/lib/python3.8/site-packages/uvicorn/lifespan/on.py", line 86, in main
    await app(scope, self.receive, self.send)
  File "/home/peter/.local/share/pdm/venvs/litestar-dj-FOhMr-3.8/lib/python3.8/site-packages/uvicorn/middleware/proxy_headers.py", line 69, in __call__
    return await self.app(scope, receive, send)
  File "/home/peter/PycharmProjects/litestar/litestar/app.py", line 568, in __call__
    await self.asgi_router.lifespan(receive=receive, send=send)  # type: ignore[arg-type]
  File "/home/peter/PycharmProjects/litestar/litestar/_asgi/asgi_router.py", line 180, in lifespan
    await send(failure_message)
  File "/home/peter/.local/share/pdm/venvs/litestar-dj-FOhMr-3.8/lib/python3.8/site-packages/uvicorn/lifespan/on.py", line 116, in send
    assert not self.startup_event.is_set(), STATE_TRANSITION_ERROR
AssertionError: Got invalid state transition on lifespan protocol.

This PR modifies ASGIRouter.lifespan() so that it sends a shutdown failure message if we’ve already confirmed startup.

References: litestar-org/litestar#3315

bug when pydantic==1.10 is installed#

Fix a bug introduced in #3296 where it failed to take into account that the pydantic_v2 variable could be Empty.

References: litestar-org/litestar#3334, litestar-org/litestar#3335

OpenAPI router and controller on same app.#

Fixes an :exc`ImproperlyConfiguredException` where an app that explicitly registers an OpenAPIController on the application, and implicitly uses the OpenAPI router via the OpenAPIConfig object. This was caused by the two different handlers being given the same name as defined in litestar.constants.

PR adds a distinct name for use by the handler that serves openapi.json on the controller.

References: litestar-org/litestar#3337, litestar-org/litestar#3338

pydantic v2 import tests for pydantic v1.10.15#

Fixes bug with Pydantic V1 environment test where the test was run against v2. Adds assertion for version to the test.

Fixes a bug exposed by above that relied on pydantic not having v1 in the package namespace if v1 is installed. This doesn’t hold true after pydantic’s 1.10.15 release.

References: litestar-org/litestar#3348, litestar-org/litestar#3347

schema for generic wrapped return types with DTO#

Fix schema generated for DTOs where the supported type is wrapped in a generic outer type.

Prior behavior of using the backend.annotation as the basis for generating the openapi schema for the represented type is not applicable for the case where the DTO supported type is wrapped in a generic outer object. In that case backend.annotation only represents the type of the attribute on the generic type that holds the DTO supported type annotation.

This change detects the case where we unwrap an outer generic type, and rebuilds the generic annotation in a manner appropriate for schema generation, before generating the schema for the annotation. It does this by substituting the DTOs transfer model for the original model in the original annotations type arguments.

References: litestar-org/litestar#2929, litestar-org/litestar#3371

Ambiguous default warning for no signature default#

We now only issue a single warning for the case where a default value is supplied via Parameter() and not via a regular signature default.

References: litestar-org/litestar#3372, litestar-org/litestar#3378

Path param consumed by dependency treated as unconsumed#

Consider parameters defined in handler dependencies in order to determine if a path parameter has been consumed for openapi generation purposes.

Fixes an issue where path parameters not consumed by the handler, but consumed by dependencies would cause an :exc`ImproperlyConfiguredException`.

References: litestar-org/litestar#3369, litestar-org/litestar#3380

“name” and “in” should not be included in openapi headers#

Exclude the “name” and “in” fields from openapi schema generated for headers.

Add BaseSchemaObject._iter_fields() method that allows schema types to define the fields that should be included in their openapi schema representation and override that method for OpenAPIHeader.

References: litestar-org/litestar#3416, litestar-org/litestar#3417

top-level import of optional package#

Fix import from contrib.minijinja without handling for case where dependency is not installed.

References: litestar-org/litestar#3415, litestar-org/litestar#3418

regular handler under mounted app#

Fix an issue where a regular handler under a mounted asgi app would prevent a request from routing through the mounted application if the request path contained the path of the regular handler as a substring.

References: litestar-org/litestar#3429, litestar-org/litestar#3430

logging to file with structlog#

Fix and issue with converting StructLoggingConfig to dict during call to configure() when the config object has a custom logger factory that references a TextIO object, which cannot be pickled.

References: litestar-org/litestar#3425

clear session cookie if new session exceeds CHUNK_SIZE#

Fix an issue where the connection session cookie is not cleared if the response session is stored across multiple cookies.

References: litestar-org/litestar#3441, litestar-org/litestar#3446

flash messages were not displayed on Redirect#

Fix an issue where flashed messages were not shown after a redirect

References: litestar-org/litestar#3325, litestar-org/litestar#3420

Validation of optional sequence in multipart data with one value#

A Sequence[UploadFile] | None would not pass validation when a single value was provided for a structured type, e.g. dataclass.

References: litestar-org/litestar#3407, litestar-org/litestar#3408

field not optional if default value#

Fix issue where a pydantic v1 field annotation is wrapped with Optional if it is marked not required, but has a default value.

References: litestar-org/litestar#3471, litestar-org/litestar#3476

prevent starting multiple responses#

Prevent the app’s exception handler middleware from starting a response after one has already started.

When something in the middleware stack raises an exception after a “http.response.start” message has already been sent, we end up with long exception chains that obfuscate the original exception.

This change implements tracking of when a response has started, and if so, we immediately raise the exception instead of sending it through the usual exception handling code path.

References: litestar-org/litestar#3479

logging middleware with multi-body response#

Prevent logging middleware from failing with a KeyError when a response sends multiple “http.response.body” messages.

References: litestar-org/litestar#3477, litestar-org/litestar#3478

handle dto type nested in mapping#

Added handling for transferring data from a transfer model, to a DTO supported instance when the DTO supported type is nested in a mapping.

I.e, handles this case:

@dataclass
class NestedDC:
    a: int
    b: str

@dataclass
class DC:
    nested_mapping: Dict[str, NestedDC]

References: litestar-org/litestar#3463, litestar-org/litestar#3486

examples omitted in schema produced by dto#

Fixes issue where a BodyKwarg instance provided as metadata to a data type annotation was ignored for OpenAPI schema generation when the data type is managed by a DTO.

References: litestar-org/litestar#3505, litestar-org/litestar#3510

fix handling validation of subscribed generics#

Fix a bug that would lead to a TypeError when subscribed generics were used in a route handler signature and subject to validation.

from typing import Generic, TypeVar
from litestar import get
from litestar.testing import create_test_client

T = TypeVar("T")

class Foo(Generic[T]):
    pass

async def provide_foo() -> Foo[str]:
    return Foo()

@get("/", dependencies={"foo": provide_foo})
async def something(foo: Foo[str]) -> None:
    return None

with create_test_client([something]) as client:
    client.get("/")

References: litestar-org/litestar#3519

exclude static file from schema#

Exclude static file routes created with create_static_files_router from the OpenAPI schema by default

References: litestar-org/litestar#3374, litestar-org/litestar#3509

use re.match instead of re.search for mounted app path (#3501)#

When mounting an app, path resolution uses re.search instead or re.match, thus mounted app matches any path which contains mount path.

References: litestar-org/litestar#3501, litestar-org/litestar#3511

do not log exceptions twice, deprecate traceback_line_limit and fix pretty_print_tty#
  • The wording of the log message, when logging an exception, has been updated.

  • For structlog, the traceback field in the log message (which contained a truncated stacktrace) has been removed. The exception field is still around and contains the full stacktrace.

  • The option traceback_line_limit has been deprecated. The value is now ignored, the full stacktrace will be logged.

References: litestar-org/litestar#3228, litestar-org/litestar#3507

YAML schema dump#

Fix an issue in the OpenAPI YAML schema dump logic of OpenAPIController where the endpoint for the OpenAPI YAML schema file returns an empty response if a request has been made to the OpenAPI JSON schema previously due to an incorrect variable check.

References: litestar-org/litestar#3537

2.8.3#

Released: 2024-05-06

Bugfixes#

Fix improper limitation of a pathname to a restricted directory#

Fix a path traversal vulnerability disclosed in litestar-org/litestar

References:

Remove use of asserts for control flow.#

#3347 introduced a new pattern to differentiate between Pydantic v1 and v2 installs, however it relies on using assert which is an issue as can optimised away.

This PR changes the approach to manually throw an ImportError instead.

References: litestar-org/litestar#3354, litestar-org/litestar#3359

schema for generic wrapped return types with DTO#

Fix schema generated for DTOs where the supported type is wrapped in a generic outer type.

References: litestar-org/litestar#2929, litestar-org/litestar#3371

Ambiguous default warning for no signature default#

We now only issue a single warning for the case where a default value is supplied via Parameter() and not via a regular signature default.

References: litestar-org/litestar#3372, litestar-org/litestar#3378

Path param consumed by dependency treated as unconsumed#

Consider parameters defined in handler dependencies in order to determine if a path parameter has been consumed for openapi generation purposes.

Fixes an issue where path parameters not consumed by the handler, but consumed by dependencies would cause an ImproperlyConfiguredException.

References: litestar-org/litestar#3369, litestar-org/litestar#3380

Solve a caching issue in CacheControlHeader#

Fixes an issue causing return of invalid values from cache.

References: litestar-org/litestar#3383

“name” and “in” should not be included in openapi headers#

Exclude the “name” and “in” fields from openapi schema generated for headers.

References: litestar-org/litestar#3416, litestar-org/litestar#3417

top-level import of optional package#

Fix import from contrib.minijinja without handling for case where dependency is not installed.

References: litestar-org/litestar#3415, litestar-org/litestar#3418

regular handler under mounted app#

Fix an issue where a regular handler under a mounted asgi app would prevent a request from routing through the mounted application if the request path contained the path of the regular handler as a substring.

References: litestar-org/litestar#3429, litestar-org/litestar#3430

logging to file with structlog#

PR fixes issue with converting StructLoggingConfig to dict during call to configure() when the config object has a custom logger factory that references a TextIO object, which cannot be pickled.

References: litestar-org/litestar#3425

clear session cookie if new session gt CHUNK_SIZE#

Fix an issue where the connection session cookie is not cleared if the response session is stored across multiple cookies.

References: litestar-org/litestar#3441, litestar-org/litestar#3446

flash messages were not displayed on Redirect#

Fixes issue where flash messages were not displayed on redirect.

References: litestar-org/litestar#3325, litestar-org/litestar#3420

Validation of optional sequence in multipart data with one value#

A Sequence[UploadFile] | None would not pass validation when a single value was provided for a structured type, e.g. dataclass.

References: litestar-org/litestar#3407, litestar-org/litestar#3408

2.8.2#

Released: 2024-04-09

Bugfixes#

pydantic v2 import tests for pydantic v1.10.15#

Fixes bug with Pydantic v1 environment test causing the test to run against v2. Adds assertion for version to the test.

Fixes a bug exposed by above that relied on Pydantic not having v1 in the package namespace if v1 is installed. This doesn’t hold true after Pydantic’s 1.10.15 release.

Moves application environment tests from the release job into the normal CI run.

References: litestar-org/litestar#3348, litestar-org/litestar#3347

2.8.1#

Released: 2024-04-08

Bugfixes#

ASGI lifespan msg after lifespan context exception#

An exception raised within an asgi lifespan context manager would result in a “lifespan.startup.failed” message

This PR modifies ASGIRouter.lifespan() so that it sends a shutdown failure message if we’ve already confirmed startup.

References: litestar-org/litestar#3315

Fix when pydantic==1.10 is installed#

This PR fixes a bug introduced in #3296 where it failed to take into account that the pydantic_v2 variable could be Empty.

References: litestar-org/litestar#3334, litestar-org/litestar#3335

OpenAPI router and controller on same app.#

Fixes an ImproperlyConfiguredException where an app that explicitly registers an OpenAPIController on the application, and implicitly uses the OpenAPI router via the OpenAPIConfig object. This was caused by the two different handlers being given the same name as defined in litestar.constants.

PR adds a distinct name for use by the handler that serves openapi.json on the controller.

References: litestar-org/litestar#3337, litestar-org/litestar#3338

2.8.0#

Released: 2024-04-05

Features#

Add path parameter to Litestar application class#

Exposes parameter at Litestar application class level

References: litestar-org/litestar#3314

Allow for console output to be silenced#

Introduces optional environment variables that allow customizing the “Application” name displayed in the console output and suppressing the initial from_env or the Rich info table at startup.

Provides flexibility in tailoring the console output to better integrate Litestar into larger applications or CLIs.

References: litestar-org/litestar#3180

Add flash plugin#

Adds a flash plugin akin to Django or Flask that uses the request state

References: litestar-org/litestar#1455, litestar-org/litestar#3145

Use memoized request_class and response_class values#

Uses memoized request_class and response_class values

References: litestar-org/litestar#3205

Enable codegen backend by default#

Enables the codegen backend for DTOs introduced in litestar-org/litestar#2388 by default.

References: litestar-org/litestar#3215

Added precedence of CLI parameters over envs#

Adds precedence of CLI parameters over environment variables. Before this change, environment variables would take precedence over CLI parameters.

Since CLI parameters are more explicit and are set by the user, they should take precedence over environment variables.

References: litestar-org/litestar#3188, litestar-org/litestar#3190

Only print when terminal is TTY enabled#

Sets LITESTAR_QUIET_CONSOLE and LITESTAR_APP_NAME in the autodiscovery function. Also prevents the tabular console output from printing when the terminal is not TTY

References: litestar-org/litestar#3219

Support schema_extra in Parameter and Body#

Introduces a way to modify the generated OpenAPI spec by adding a schema_extra parameter to the Parameter and Body classes. The schema_extra parameter accepts a dict[str, Any] where the keys correspond to the keyword parameter names in Schema, and the values are used to override items in the generated Schema object.

Provides a convenient way to customize the OpenAPI documentation for inbound parameters.

References: litestar-org/litestar#3204

Add typing.TypeVar expansion#

Adds a method for TypeVar expansion on registration This allows the use of generic route handler and generic controller without relying on forward references.

References: litestar-org/litestar#3242

Add LITESTAR_ prefix before WEB_CONCURRENCY env option#

Adds LITESTAR_ prefix before the WEB_CONCURRENCY environment option

References: litestar-org/litestar#3227

Warn about ambiguous default values in parameter specifications#

As discussed in litestar-org/litestar#3280, we want to warn about, and eventually disallow specifying parameter defaults in two places.

To achieve this, 2 warnings are added:

  • A deprecation warning if a default is specified when using Annotated: param: Annotated[int, Parameter(..., default=1)] instead of param: Annotated[int, Parameter(...)] = 1

  • An additional warning in the above case if two default values are specified which do not match in value: param: Annotated[int, Parameter(..., default=1)] = 2

In a future version, the first one should result in an exception at startup, preventing both of these scenarios.

References: litestar-org/litestar#3283

Support declaring DTOField via Annotated#

Deprecates passing DTOField via [pydantic] extra.

References: litestar-org/litestar#2351, litestar-org/litestar#3289

Add “TRACE” to HttpMethod enum#

Adds the TRACE HTTP method to HttpMethod enum

References: litestar-org/litestar#3294

Pydantic DTO non-instantiable types#

Simplifies the type that is applied to DTO transfer models for certain Pydantic field types. It addresses JsonValue, EmailStr, IPvAnyAddress/IPvAnyNetwork/IPvAnyInterface types by using appropriate type annotations on the transfer models to ensure compatibility with msgspec serialization and deserialization.

References: litestar-org/litestar#3296

Bugfixes#

Unique schema names for nested models (#3134)#

Fixes an issue where nested models beyond the max_nested_depth would not have unique schema names in the OpenAPI documentation. The fix appends the nested model’s name to the unique_name to differentiate it from the parent model.

References: litestar-org/litestar#3134, litestar-org/litestar#3136

Remove duplicate rich-click config options#

Removes duplicate config options from click cli

References: litestar-org/litestar#3274

Fix Pydantic json_schema_extra examples.#

Fixes a regression introduced in 2.7.0 where an example for a field provided in Pydantic’s Field.json_schema_extra would cause an error.

References: litestar-org/litestar#3277, litestar-org/litestar#3281

Set default on schema from FieldDefinition#

Consider the following:

def get_foo(foo_id: int = 10) -> None:
    ...

In such cases, no KwargDefinition is created since there is no metadata provided via Annotated. The default is still parsed, and set on the generated FieldDefinition, however the SchemaCreator currently only considers defaults that are set on KwargDefinition.

So in such cases, we should fallback to the default set on the FieldDefinition if there is a valid default value.

References: litestar-org/litestar#3278, litestar-org/litestar#3280

Custom types cause serialisation error in exception response with non-JSON media-type#

Fixes a bug when using a non-JSON media type (e.g., text/plain), ValidationException’s would not get serialized properly because they would ignore custom type_encoders.

References: litestar-org/litestar#3192, litestar-org/litestar#3284

Ensure default values are always represented in schema for dataclasses and msgspec.Structs#

Fixes a bug that would prevent default values for dataclasses and msgspec.Struct s to be included in the OpenAPI schema.

References: litestar-org/litestar#3201, litestar-org/litestar#3285

Pydantic v2 error handling/serialization when for non-Pydantic exceptions#

Fixes a bug that would cause a TypeError when non-Pydantic errors are raised during Pydantic’s validation process while using DTOs.

References: litestar-org/litestar#2365, litestar-org/litestar#3286

Fix OpenAPI schema generation for paths with path parameters of different types on the same path#

Fixes a bug that would cause no OpenAPI schema to be generated for paths with path parameters that only differ on the path parameter type, such as /{param:int} and /{param:str}. This was caused by an internal representation issue in Litestar’s routing system.

References: litestar-org/litestar#2700, litestar-org/litestar#3293

Document unconsumed path parameters#

Fixes a bug where path parameters not consumed by route handlers would not be included in the OpenAPI schema.

This could/would not include the {param} in the schema, yet it is still required to be passed when calling the path.

References: litestar-org/litestar#3290, litestar-org/litestar#3295

2.7.1#

Released: 2024-03-22

Bugfixes#

replace TestClient.__enter__ return type with Self#

TestClient.__enter__ and AsyncTestClient.__enter__ return Self. If you inherit TestClient, its __enter__ method should return derived class’s instance unless override the method. Self is a more flexible return type.

References: litestar-org/litestar#3194

use the full path for fetching openapi.json#

This specifies the spec-url and apiDescriptionUrl of Rapidoc, and Stoplight Elements as absolute paths relative to the root of the site.

This ensures that both of the send the request for the JSON of the OpenAPI schema to the right endpoint.

References: litestar-org/litestar#3047, litestar-org/litestar#3196

JSON schema examples were OpenAPI formatted#

The generated examples in JSON schema objects were formatted as:

 "examples": {
   "some-id": {
     "description": "Lorem ipsum",
     "value": "the real beef"
   }
}

However, above is OpenAPI example format, and must not be used in JSON schema objects. Schema objects follow different formatting:

 "examples": [
   "the real beef"
]

This is referenced at least from parameters, media types and components.

The technical change here is to define Schema.examples as list[Any] instead of list[Example]. Examples can and must still be defined as list[Example] for OpenAPI objects (e.g. Parameter, Body) but for JSON schema examples the code now internally generates/converts list[Any] format instead.

Extra confusion here comes from the OpenAPI 3.0 vs OpenAPI 3.1 difference. OpenAPI 3.0 only allowed example (singular) field in schema objects. OpenAPI 3.1 supports the full JSON schema 2020-12 spec and so examples array in schema objects.

Both example and examples seem to be supported, though the former is marked as deprecated in the latest specs.

This can be tested over at https://editor-next.swagger.io by loading up the OpenAPI 3.1 Pet store example. Then add examples in components.schemas.Pet using the both ways and see the Swagger UI only render the example once it’s properly formatted (it ignores is otherwise).

References: litestar-org/litestar#2849, litestar-org/litestar#3224

queue_listener handler for Python >= 3.12#
  • Fix the queue_listener handler for Python 3.12

Python 3.12 introduced a new way to configure QueueHandler and QueueListener via logging.config.dictConfig(). As described in the logging documentation.

The listener still needs to be started & stopped, as previously. To do so, we’ve introduced LoggingQueueListener.

And as stated in the doc: * Any custom queue handler and listener classes will need to be defined with the same initialization signatures as QueueHandler and QueueListener.

References: litestar-org/litestar#2954, litestar-org/litestar#3185

extend openapi meta collected from domain models#

FieldDefinition s pack any OpenAPI metadata onto a KwargDefinition instance when types are parsed from domain models.

When we produce a DTO type, we transfer this meta from the KwargDefinition to a msgspec.Meta instance, however so far this has only included constraints, not attributes such as descriptions, examples and title.

This change ensures that we transfer the openapi meta for the complete intersection of fields that exist on b oth KwargDefinition and Meta.

References: litestar-org/litestar#3232, litestar-org/litestar#3237

kwarg ambiguity exc msg for path params#

Fixes the way we construct the exception message when there is a kwarg ambiguity detected for path parameters.

References: litestar-org/litestar#3261

2.7.0#

Released: 2024-03-10

Features#

Support ResponseSpec(..., examples=[...])#

Allow defining custom examples for the responses via ResponseSpec. The examples set this way are always generated locally, for each response: Examples that go within the schema definition cannot be set by this.

{
"paths": {
    "/": {
    "get": {
        "responses": {
        "200": {
            "content": {
            "application/json": {
                "schema": {},
                "examples": "..."}}
            }}
        }}
    }
}

References: litestar-org/litestar#3068, litestar-org/litestar#3100

support “+json”-suffixed response media types#

Automatically encode responses with media type of the form application/<something>+json as json.

References: litestar-org/litestar#3088, litestar-org/litestar#3096

Allow reusable Router instances#

It was not possible to re-attach a router instance once it was attached. This makes that possible.

The router instance now gets deepcopied when it’s registered to another router.

The application startup performance gets a hit here, but the same approach is already used for controllers and handlers, so this only harmonizes the implementation.

References: litestar-org/litestar#3012, litestar-org/litestar#3103

only display path in ValidationExceptions#

Fix an issue where ValidationException exposes the full URL in the error response, leaking internal IP(s) or other similar infra related information.

References: litestar-org/litestar#3061, litestar-org/litestar#3064

expose request_class to other layers#

Expose request_class to other layers

References: litestar-org/litestar#3125

expose websocket_class#

Expose websocket_class to other layers

References: litestar-org/litestar#3152

Add type_decoders to Router and route handlers#

Add type_decoders to __init__ method for handler, routers and decorators to keep consistency with type_encoders parameter

References: litestar-org/litestar#3153

Pass type_decoders in WebsocketListenerRouteHandler#

Pass type_decoders to parent’s __init__ in WebsocketListenerRouteHandler init, otherwise type_decoders will be None replace params order in docs, __init__ (decoders before encoders)

References: litestar-org/litestar#3162

3116 enhancement session middleware#

For server side sessions, the session id is now generated before the route handler. Thus, on first visit, a session id will be available inside the route handler’s scope instead of afterwards A new abstract method get_session_id was added to BaseSessionBackend since this method will be called for both ClientSideSessions and ServerSideSessions. Only for ServerSideSessions it will return an actual id. Using request.set_session(...) will return the session id for ServerSideSessions and None for ClientSideSessions The session auth MiddlewareWrapper now refers to the Session Middleware via the configured backend, instead of it being hardcoded

References: litestar-org/litestar#3116, litestar-org/litestar#3127

make random seed for openapi example generation configurable#

Allow random seed used for generating the examples in the OpenAPI schema (when create_examples is set to True) to be configured by the user. This is related to litestar-org/litestar#3059 however whether this change is enough to close that issue or not is not confirmed.

References: litestar-org/litestar#3166

generate openapi components schemas in a deterministic order#

Ensure that the insertion into the Components.schemas dictionary of the OpenAPI spec will be in alphabetical order (based on the normalized name of the Schema).

References: litestar-org/litestar#3172

Bugfixes#

missing cors headers in response#

Set CORS Middleware headers as per spec. Addresses issues outlined on litestar-org/litestar#3178

References: litestar-org/litestar#3178, litestar-org/litestar#3179

sending empty data in sse in js client#

Fix an issue with SSE where JavaScript clients fail to receive an event without data. The spec is not clear in whether or not an event without data is ok. Considering the EventSource “client” is not ok with it, and that it’s so easy DX-wise to make the mistake not explicitly sending it, this change fixes it by defaulting to the empty-string

References: litestar-org/litestar#3176

2.6.3#

Released: 2024-03-04

Bugfixes#

Pydantic V1 schema generation for PrivateAttr in GenericModel#

Fixes a bug that caused a NameError when a Pydantic V1 GenericModel has a private attribute of which the type annotation cannot be resolved at the time of schema generation.

References: litestar-org/litestar#3150, litestar-org/litestar#3161

2.6.2#

Released: 2024/03/02

Bugfixes#

DTO msgspec meta constraints not being included in transfer model#

Fix an issue where msgspec constraints set in msgspec.Meta would not be honoured by the DTO.

In the given example, the min_length=3 constraint would be ignored by the model generated by MsgspecDTO.

from typing import Annotated

import msgspec
from litestar import post
from litestar.dto import MsgspecDTO

class Request(msgspec.Struct):
    foo: Annotated[str, msgspec.Meta(min_length=3)]

@post("/example/", dto=MsgspecDTO[Request])
async def example(data: Request) -> Request:
    return data

Constraints like these are now transferred.

Two things to note are:

  • For DTOs with DTOConfig(partial=True) we cannot transfer the length constraints as they are only supported on fields that as subtypes of str, bytes or a collection type, but partial=True sets all fields as T | UNSET

  • For the PiccoloDTO, fields which are not required will also drop the length constraints. A warning about this will be raised here.

References: litestar-org/litestar#3026, litestar-org/litestar#3113

Missing control header for static files#

Fix an issue where a cache_control that is set on a router created by create_static_files_router wasn’t passed to the generated handler

References: litestar-org/litestar#3129, litestar-org/litestar#3131

Fix OpenAPI schema generation for Pydantic v2 constrained Secret types#

Fix schema generation for pydantic.SecretStr and pydantic.SecretBytes which, when constrained, would not be recognised as such with Pydantic V2 since they’re not subtypes of their respective bases anymore.

References: litestar-org/litestar#3148, litestar-org/litestar#3149

Fix OpenAPI schema generation for Pydantic private attributes#

Fix a bug that caused a NameError when trying to resolve forward references in Pydantic private fields.

Although private fields were respected excluded from the schema, it was still attempted to extract their type annotation. This was fixed by not relying on typing.get_type_hints to get the type information, but instead using Pydantic’s own APIs, allowing us to only extract information about the types of relevant fields.

References: litestar-org/litestar#3150, litestar-org/litestar#3151

OpenAPI description not set for UUID based path parameters in OpenAPI#

Resolved a bug where the description was not set for UUID-based path parameters in OpenAPI due to the reason mentioned in the issue.

References: litestar-org/litestar#2967, litestar-org/litestar#3118

Fix RedisStore client created with with_client unclosed#

Fix a bug where, when a RedisStore was created with the with_client() method, that client wasn’t closed explicitly

References: litestar-org/litestar#3083, litestar-org/litestar#3111

2.6.1#

Released: 2024/02/14

Bugfixes#

SQLAlchemy: Use IntegrityError instead of deprecated ConflictError#

Updated the repository to return IntegrityError instead of the now deprecated ConflictError

References: litestar-org/litestar#3094

Remove usage of deprecated static_files property#

Remove the usage of the deprecated Litestar.static_files_config in Litestar.__init__.

References: litestar-org/litestar#3087

Sessions: Fix cookie naming for short cookies#

Previously, cookie names always had a suffix of the form "-{i}" appended to them. With this change, the suffix is omitted if the cookie is short enough (< 4 KB) to not be split into multiple chunks.

References: litestar-org/litestar#3090, litestar-org/litestar#3095

Static files: Fix path resolution for windows#

Fix an issue with the path resolution on Windows introduced in litestar-org/litestar#2960 that would lead to 404s

References: litestar-org/litestar#3102

Fix logging middleware with structlog causes application to return a 500 when request body is malformed#

Gracefully handle malformed request bodies during parsing when using structlog; Instead of erroring out and returning a 500, the raw body is now being used when an error occurs during parsing

References: litestar-org/litestar#3063, litestar-org/litestar#3109

OpenAPI: Generate correct response schema for ResponseSpec(None)#

Explicitly declaring responses={...: ResponseSpec(None)} used to generate OpenAPI a content property, when it should be omitted.

References: litestar-org/litestar#3069, litestar-org/litestar#3098

Prevent exception handlers from extracting details from non-Litestar exceptions#

Fix a bug where exception classes that had a status_code attribute would be treated as Litestar exceptions and details from them would be extracted and added to the exception response.

References: litestar-org/litestar#3082, litestar-org/litestar#3106

2.6.0#

Released: 2024/02/06

Features#

Enable disabling configuring root logger within LoggingConfig#

The option configure_root_logger was added to LoggingConfig attribute. It is enabled by default to not implement a breaking change.

When set to False the root logger will not be modified for logging or picologging loggers.

References: litestar-org/litestar#2969

Simplified static file handling and enhancements#

Static file serving has been implemented with regular route handlers instead of a specialised ASGI app. At the moment, this is complementary to the usage of StaticFilesConfig to maintain backwards compatibility.

This achieves a few things:

  • Fixes litestar-org/litestar#2629

  • Circumvents special casing needed in the routing logic for the static files app

  • Removes the need for a static_files_config attribute on the app

  • Removes the need for a special url_for_static_asset() method on the app since route_reverse can be used instead

Additionally:

  • Most router options can now be passed to the create_static_files_router(), allowing further customisation

  • A new resolve_symlinks flag has been added, defaulting to True to keep backwards compatibility

Usage

Instead of

app = Litestar(
    static_files_config=[StaticFilesConfig(path="/static", directories=["some_dir"])]
)

You can now simply use

app = Litestar(
    route_handlers=[
        create_static_files_router(path="/static", directories=["some_dir"])
    ]
)

See also

Static files

References: litestar-org/litestar#2629, litestar-org/litestar#2960

Exclude Piccolo ORM columns with secret=True from PydanticDTO output#

For Piccolo columns with secret=True set, corresponding PydanticDTO attributes will be marked as WRITE_ONLY to prevent the column being included in return_dto

References: litestar-org/litestar#3030

Allow discovering registered plugins by their fully qualified name#

PluginRegistryPluginRegistry` now supports retrieving a plugin by its fully qualified name.

References: litestar-org/litestar#3027

Support externally typed classes as dependency providers#
  • Implement a new DIPlugin class that allows the generation of signatures for arbitrary types where their signature cannot be extracted from the type’s __init__ method

  • Implement DIPlugins for Pydantic and Msgspec to allow using their respective modelled types as dependency providers. These plugins will be registered by default

References: litestar-org/litestar#2979, litestar-org/litestar#3066

Add structlog plugin#

A Structlog plugin to make it easier to configure structlog in a single place.

The plugin:

  • Detects if a logger has setLevel before calling

  • Set even message name to be init-cap

  • Add set_level interface to config

  • Allows structlog printer to detect if console is TTY enabled. If so, a Struglog color formatter with Rich traceback printer is used

  • Auto-configures stdlib logger to use the structlog logger

References: litestar-org/litestar#2943

Add reload-include and reload-exclude to CLI run command#

The options reload-exclude and reload-include were added to the CLI run command to explicitly in-/exclude specific paths from the reloading watcher.

References: litestar-org/litestar#2875, litestar-org/litestar#2973

2.5.5#

Released: 2024/02/04

Bugfixes#

Fix scope state key handling#

Fix a regression introduced in #2751 that would wrongfully assume the state key is always present within the ASGI Scope. This is only the case when the Litestar root application is invoked first, since we enforce such a key there, but the presence of that key is not actually guaranteed by the ASGI spec and some servers, such as hypercorn, do not provide it.

References: litestar-org/litestar#3070

2.5.4#

Released: 2024/01/31

Bugfixes#

Handle KeyError when root_path is not present in ASGI scope#

Nginx Unit ASGI server does not set “root_path” in the ASGI scope, which is expected as part of the changes done in #3039. This PR fixes the assumption that the key is always present and instead tries to optionally retrieve it.

KeyError on GET /
'root_path'

References: litestar-org/litestar#3051

ServerSentEvent typing error#

fixes small typing error:

error: Argument 1 to "ServerSentEvent" has incompatible type "AsyncIterable[ServerSentEventMessage]"; expected "str | bytes | Iterable[str | bytes] | Iterator[str | bytes] | AsyncIterable[str | bytes] | AsyncIterator[str | bytes]"  [arg-type]

inside test_sse there was a Any I changed to trigger the test then solved it.

References: litestar-org/litestar#3048

2.5.3#

Released: 2024/01/29

Bugfixes#

Handle diverging ASGI root_path behaviour#

Uvicorn 0.26.0 introduced a breaking change in its handling of the ASGI root_path behaviour, which, while adhering to the spec, diverges from the interpretation of other ASGI servers of this aspect of the spec (e.g. hypercorn and daphne do not follow uvicorn’s interpretation as of today). A fix was introduced that ensures consistent behaviour of applications in any case.

References: litestar-org/litestar#3041, litestar-org/litestar#3039

2.5.2#

Released: 2024/01/27

Bugfixes#

Ensure MultiDict and ImmutableMultiDict copy methods return the instance’s type#

Ensure MultiDict and ImmutableMultiDict copy methods return a new instance of MultiDict and ImmutableMultiDict. Previously, these would return a multidict.MultiDict instance.

References: litestar-org/litestar#2549, litestar-org/litestar#3009

Ensure exceptiongroup is installed on Python 3.11#

Add the exceptiongroup package as a required dependency on Python <3.11 (previously <3.10) as a backport of Exception Groups

References: litestar-org/litestar#3029, litestar-org/litestar#3035

2.5.1#

Released: 2024/01/18

Bugfixes#

Fix OpenAPI schema generation for Union of multiple msgspec.Structs and None#

The following code would raise a TypeError

import msgspec

from litestar import get


class StructA(msgspec.Struct):
    pass


class StructB(msgspec.Struct):
    pass


@get("/")
async def handler() -> StructA | StructB | None:
    return StructA()

References: litestar-org/litestar#2971, litestar-org/litestar#2982

Fix misleading error message for missing dependencies provide by a package extra#

Ensure that MissingDependencyException includes the correct name of the package to install if the package name differs from the Litestar package extra. (e.g. pip install litestar[jinja] vs pip install jinja2). Previously the exception assumed the same name for both the package and package-extra name.

References: litestar-org/litestar#2921

Fix OpenAPI schema file upload schema types for swagger#
  • Always set format as binary

  • Fix schema for swagger with multiple files, which requires the type of the request body schema to be object with properties instead of a schema of type array and items.

References: litestar-org/litestar#2628, litestar-org/litestar#2745

2.5.0#

Released: 2024/01/06

Features#

Postgres channels backends#

Two new channel backends were added to bring Postgres support:

AsyncPgChannelsBackend, using the asyncpg driver and PsycoPgChannelsBackend using the psycopg3 async driver.

See also

Channels

References: litestar-org/litestar#2803

Add --schema and --exclude option to litestar route CLI command#

Two new options were added to the litestar route CLI command:

  • --schema, to include the routes serving OpenAPI schema and docs

  • --exclude to exclude routes matching a specified pattern

See also

Read more in the CLI cli section.

References: litestar-org/litestar#2886

Bugfixes#

Fix serialization of custom types in exception responses#

Fix a bug that would lead to a SerializationException when custom types were present in an exception response handled by the built-in exception handlers.

class Foo:
    pass


@get()
def handler() -> None:
    raise ValidationException(extra={"foo": Foo("bar")})


app = Litestar(route_handlers=[handler], type_encoders={Foo: lambda foo: "foo"})

The cause was that, in examples like the one shown above, type_encoders were not resolved properly from all layers by the exception handling middleware, causing the serializer to throw an exception for an unknown type.

References: litestar-org/litestar#2867, litestar-org/litestar#2941

Fix SSE reverting to default event_type after 1st message#

The event_type set within an SSE returned from a handler would revert back to a default after the first message sent:

@get("/stream")
async def stream(self) -> ServerSentEvent:
    async def gen() -> AsyncGenerator[str, None]:
        c = 0
        while True:
            yield f"<div>{c}</div>\n"
            c += 1

    return ServerSentEvent(gen(), event_type="my_event")

In this example, the event type would only be my_event for the first message, and fall back to a default afterwards. The implementation has been fixed and will now continue sending the set event type for all messages.

References: litestar-org/litestar#2877, litestar-org/litestar#2888

Correctly handle single file upload validation when multiple files are specified#

Uploading a single file when the validation target allowed multiple would cause a ValidationException:

class FileUpload(Struct):
    files: list[UploadFile]


@post(path="/")
async def upload_files_object(
    data: Annotated[FileUpload, Body(media_type=RequestEncodingType.MULTI_PART)]
) -> list[str]:
    pass

This could would only allow for 2 or more files to be sent, and otherwise throw an exception.

References: litestar-org/litestar#2939, litestar-org/litestar#2950

Fix trailing messages after unsubscribe in channels#

Fix a bug that would allow some channels backend to receive messages from a channel it just unsubscribed from, for a short period of time, due to how the different brokers handle unsubscribes.

await backend.subscribe(["foo", "bar"])  # subscribe to two channels
await backend.publish(
    b"something", ["foo"]
)  # publish a message to a channel we're subscribed to

# start the stream after publishing. Depending on the backend
# the previously published message might be in the stream
event_generator = backend.stream_events()

# unsubscribe from the channel we previously published to
await backend.unsubscribe(["foo"])

# this should block, as we expect messages from channels
# we unsubscribed from to not appear in the stream anymore
print(anext(event_generator))

Backends affected by this were in-memory, Redis PubSub and asyncpg. The Redis stream and psycopg backends were not affected.

References: litestar-org/litestar#2894

Other changes#

Improve performance of threaded synchronous execution#

Performance of threaded synchronous code was improved by using the async library’s native threading helpers instead of anyio. On asyncio, asyncio.loop.run_in_executor() is now used and on trio trio.to_thread.run_sync().

Beneficiaries of these performance improvements are:

  • Synchronous route handlers making use of sync_to_thread=True

  • Synchronous dependency providers making use of sync_to_thread=True

  • Synchronous SSE generators

  • FileStore

  • Large file uploads where the max_spool_size is exceeded and the spooled temporary file has been rolled to disk

  • File and ASGIFileResponse

References: litestar-org/litestar#2937

2.4.5#

Released: 2023/12/23

Bugfixes#

Fix validation of empty payload data with default values#

Prior to this fix, a handler like:

@post(path="/", sync_to_thread=False)
def test(data: str = "abc") -> dict:
    return {"foo": data}

$ curl localhost:8000 -X POST

would return a client error like:

{"status_code":400,"detail":"Validation failed for POST http://localhost:8000/","extra":[{"message":"Expected `str`, got `null`","key":"data","source":"body"}]}

References: litestar-org/litestar#2902, litestar-org/litestar#2903

Support for returning Response[None] with a 204 status code from a handler#

Returning a Response[None] from a route handler for a response with a 204 now works as expected without resulting in an ImproperlyConfiguredException

References: litestar-org/litestar#2914, litestar-org/litestar#2915

Fix error message of get_logger_placeholder()#

Using a method on Request.logger when not setting a logging_config on the application would result in a non-descriptive TypeError. An ImproperlyConfiguredException with an explanation is now raised instead.

References: litestar-org/litestar#2919

2.4.4#

Released: 2023/12/13

Bugfixes#

Support non-valid identifier as serialization target name#

Fix a bug where DTOs would raise a TypeError: __slots__ must be identifiers during serialization, if a non-valid identifier (such as field-name)was used for field renaming.

References: litestar-org/litestar#2845, litestar-org/litestar#2850

Fix regression signature validation for DTO validated types#

Fix a regression introduced in 2.0.0rc1 that would cause data validated by the DTO to be validated again by the signature model.

References: litestar-org/litestar#2149, litestar-org/litestar#2854

Fix regression in OpenAPI schema key names#

Fix a regression introduced in 2.4.0 regarding the naming of OpenAPI schema keys, in which a change was introduced to the way that keys for the OpenAPI components/schemas objects were calculated to address the possibility of name collisions.

This behaviour was reverted for the case where a name has no collision, and now only introduces extended keys for the case where there are multiple objects with the same name, a case which would previously result in an exception.

References: litestar-org/litestar#2804, litestar-org/litestar#2841

Fix regression in OpenAPI handling of routes with multiple handlers#

Fix a regression introduced in 2.4.3 causing two routes registered with the same path, but different methods to break OpenAPI schema generation due to both of them having the same value for operation ID.

References: litestar-org/litestar#2863, litestar-org/litestar#2864

Fix OpenAPI schema generation for recursive models#

Fix an issue that would lead to a RecursionError when including nested models in the OpenAPI schema.

References: litestar-org/litestar#2429, litestar-org/litestar#2869

2.4.3#

Released: 2023/12/07

Bugfixes#

Fix OpenAPI schema for Literal | None unions#

Fix a bug where an incorrect OpenAPI schema was generated generated when any Literal | None-union was present in an annotation.

For example

type: Literal["sink", "source"] | None

would generate

{
  "name": "type",
  "in": "query",
  "schema": {
    "type": "string",
    "enum": [ "sink", "source", null ]
  }
}

References: litestar-org/litestar#2812, litestar-org/litestar#2818

Fix advanced-alchemy 0.6.0 compatibility issue with touch_updated_timestamp#

Fix an incorrect import for touch_updated_timestamp of Advanced Alchemy, introduced in Advanced-Alchemy version 0.6.0.

References: litestar-org/litestar#2843

2.4.2#

Released: 2023/12/02

Bugfixes#

Fix OpenAPI handling of parameters with duplicated names#

Fix a bug where schema generation would consider two parameters with the same name but declared in different places (eg., header, cookie) as an error.

References: litestar-org/litestar#2662, litestar-org/litestar#2788

Fix late failure where DTOData is used without a DTO#

Fix an issue where a handler would be allowed to be registered with a DTOData annotation without having a DTO defined, which would result in a runtime exception. In cases like these, a configuration error is now raised during startup.

References: litestar-org/litestar#2779, litestar-org/litestar#2789

Correctly propagate camelCase names on OpenAPI schema#

Fix a bug where OpenAPI schema fields would be inappropriately propagated as camelCase where they should have been snake_case

References: litestar-org/litestar#2800

Fix error handling in event handler stream#

Fix a class of errors that could result in the event listener stream being terminated when an exception occurred within an event listener. Errors in event listeners are now not propagated anymore but handled by the backend and logged instead.

References: litestar-org/litestar#2810,, litestar-org/litestar#2814

Fix OpenAPI schema for Pydantic computed fields#

Add support for including computed fields in schemas generated from Pydantic models.

References: litestar-org/litestar#2792, litestar-org/litestar#2797

2.4.1#

Released: 2023/11/28

Bugfixes#

Fix circular import when importing from litestar.security.jwt#

An ImportError was raised when trying to import from litestar.security.jwt. This was fixed by removing the imports from the deprecated litestar.contrib.jwt within litesetar.security.jwt.

References: litestar-org/litestar#2782, litestar-org/litestar#2784

Raise config error when generator dependencies are cached#

Previously, an InternalServerError was raised when attempting to use use_cache=True with generator dependencies. This will now raise a configuration error during application startup.

References: litestar-org/litestar#2771, litestar-org/litestar#2780

2.4.0#

Released: 2023/11/27

Features#

Add server_lifespan hook#

A new server_lifespan hook is now available on Litestar. This hook works similar to the regular lifespan context manager, with the difference being is that it is only called once for the entire server lifespan, not for each application startup phase. Note that these only differ when running with an ASGI server that’s using multiple worker processes.

References: litestar-org/litestar#2658

Allow rendering templates directly from strings#

A new template_string parameter was added to Template, allowing to render templates directly from strings.

References: litestar-org/litestar#2687, litestar-org/litestar#2689

Support nested DTO field renaming#

Using similar semantics as for exclusion/inclusion, nested DTO fields can now also be renamed:

from dataclasses import dataclass


@dataclass
class Bar:
    id: str


@dataclass
class Foo:
    id: str
    bars: list[Bar]


FooDTO = DataclassDTO[Annotated[Foo, DTOConfig(rename_fields={"bars.0.id": "bar_id"})]]

References: litestar-org/litestar#2721, litestar-org/litestar#2764

Bugfixes#

Fix HTTPException handling during concurrent dependency resolving#

An issue was fixed that would lead to HTTPExceptions not being re-raised properly when they occurred within the resolution of nested dependencies during the request lifecycle.

References: litestar-org/litestar#2594, litestar-org/litestar#2596

Fix OpenAPI examples format#

Fix the OpenAPI examples format by removing the wrapping object.

Before the change, for a given model

@dataclass
class Foo:
    foo: int

The following example would be generated:

{
    "description": "Example value",
    "value": {
        "foo": 7906
    }
}

After the fix, this is now:

{
    "foo": 7906
}

References: litestar-org/litestar#2272, litestar-org/litestar#2660

Fix CLI plugin commands not showing up in command list#

Fix a bug where commands registered by CLI plugins were available, but would not show up in the commands list

References: litestar-org/litestar#2441

Fix missing write-only mark in dto_field() signature#

Fix the missing write-only string literal in the mark parameter of dto_field()

References: litestar-org/litestar#2684

Fix OpenAPI schemas incorrectly flagged as duplicates#

Fix an issue that would lead to OpenAPI schemas being incorrectly considered duplicates, resulting in an ImproperlyConfiguredException being raised.

References: litestar-org/litestar#2471, litestar-org/litestar#2475

Fix Pydantic URL type support in OpenAPI and serialization#

Add missing support for Pydantic’s URL types (AnyUrl and its descendants) for both serialization and OpenAPI schema generation. These types were only partially supported previously; Serialization support was lacking for v1 and v2, and OpenAPI support was missing for v2.

References: litestar-org/litestar#2664, litestar-org/litestar#2701

Fix incorrect ValidationException message when multiple errors were encountered#

Fix a bug where ValidationException could contain duplicated messages in extra field, when multiple errors were encountered during validation

References: litestar-org/litestar#2714, litestar-org/litestar#2716

Fix DTO renaming renames all fields of the same name in nested DTOs#

Fix an issue with nested field renaming in DTOs that would lead to all fields with a given name to be renamed in a nested structure.

In the below example, both Foo.id and Bar.id would have been renamed to foo_id

from dataclasses import dataclass


@dataclass
class Bar:
    id: str


@dataclass
class Foo:
    id: str
    bar: Bar


FooDTO = DataclassDTO[Annotated[Foo, DTOConfig(rename_fields={"id": "foo_id"})]]

References: litestar-org/litestar#2721, litestar-org/litestar#2764

Fix handling of DTO objects nested in mappings#

Fix a bug where DTOs nested in a Mapping type would fail to serialize correctly.

References: litestar-org/litestar#2737, litestar-org/litestar#2775

Fix inconsistent sequence union parameter errors#

Fix a bug where unions of collection types would result in different errors depending on whether the union included None or not.

References: litestar-org/litestar#2600, litestar-org/litestar#2776

Fix graceful handling of WebSocket disconnect in channels WebSockets handlers#

Fix the behaviour of WebSocket disconnect handling within the WebSocket handlers provided by channels, that would sometimes lead to a RuntimeError: Unexpected ASGI message 'websocket.close', after sending 'websocket.close'. exception being raised upon the closing of a WebSocket connection.

References: litestar-org/litestar#2691

2.3.2#

Released: 2023/11/06

Bugfixes#

Fix recursion error when re-using the path of a route handler for static files#

A regression was fixed that would cause a recursion error when the path of a static files host was reused for a route handler with a different HTTP method.

from litestar import Litestar
from litestar import post
from litestar.static_files import StaticFilesConfig


@post("/uploads")
async def handler() -> None:
    pass


app = Litestar(
    [handler],
    static_files_config=[
        StaticFilesConfig(directories=["uploads"], path="/uploads"),
    ],
)

References: litestar-org/litestar#2629, litestar-org/litestar#2630

2.3.1#

Released: 2023/11/04

Bugfixes#

CLI: Fix not providing SSL certfiles breaks uvicorn command when using reload or multiple workers#

Fix an issue where not providing the --ssl-certfile and --ssl-keyfile options to the litestar run command would cause a FileNotFoundError in uvicorn, when used together with the --reload, --web-concurrency options.

References: litestar-org/litestar#2613, litestar-org/litestar#2616

2.3.0#

Released: 2023/11/02

Features#

Python 3.12 support#

Python 3.12 is now fully supported and tested.

References: litestar-org/litestar#1862, litestar-org/litestar#2396

New layered parameter signature_types#

Types in this collection are added to signature_namespace using the type’s __name__ attribute. This provides a nicer interface when adding names to the signature namespace w ithout modifying the type name, e.g.: signature_namespace={"Model": Model} is equivalent to signature_types=[Model].

The implementation makes it an error to supply a type in signature_types that has a value for __name__ already in the signature namespace.

It will also throw an error if an item in signature_types has no __name__ attribute.

References: litestar-org/litestar#2422

Added RapiDoc for OpenAPI schema visualisation#

Add support for using RapiDoc for OpenAPI schema visualisation.

References: litestar-org/litestar#2522

Support Pydantic 1 & 2 within the same application#

Added support for Pydantic 1 & 2 within the same application by integrating with Pydantic’s backwards compatibility layer:

from litestar import get
from pydantic.v1 import BaseModel as BaseModelV1
from pydantic import BaseModel


class V1Foo(BaseModelV1):
    bar: str


class V2Foo(BaseModel):
    bar: str


@get("/1")
def foo_v1(data: V1Foo) -> V1Foo:
    return data


@get("/2")
def foo_v2(data: V2Foo) -> V2Foo:
    return data

References: litestar-org/litestar#2487

Add ResponseCacheConfig.cache_response_filter to allow filtering responses eligible for caching#

ResponseCacheConfig.cache_response_filter is predicate called by the response cache middleware that discriminates whether a response should be cached, or not.

References: litestar-org/litestar#2501, litestar-org/litestar#2537

SSL support and self-signed certificates for CLI#

Add support for SSL and generating self-signed certificates to the CLI.

For this, three new arguments were added to the CLI’s run command:

  • --ssl-certfile

  • --ssl-keyfile

  • --create-self-signed-cert

The --ssl-certfile and –ssl-keyfile flags are passed to uvicorn when using litestar run. Uvicorn requires both to be passed (or neither) but additional validation was added to generate a more user friendly CLI errors.

The other SSL-related flags (like password or CA) were not added (yet). See uvicorn CLI docs

Generating of a self-signed certificate

One more CLI flag was added (--create-devcert) that uses the cryptography module to generate a self-signed development certificate. Both of the previous flags must be passed when using this flag. Then the following logic is used:

  • If both files already exists, they are used and nothing is generated

  • If neither file exists, the dev cert and key are generated

  • If only one file exists, it is ambiguous what to do so an exception is raised

References: litestar-org/litestar#2335, litestar-org/litestar#2554

Bugfixes#

Use custom request class when given during exception handling#

When a custom request_class is provided, it will now be used while returning an error response

References: litestar-org/litestar#2399, litestar-org/litestar#2444

Fix missing OpenAPI schema for generic response type annotations#

OpenAPI schemas are now correctly generated when a response type annotation contains a generic type such as

from msgspec import Struct
from litestar import get, Response
from typing import TypeVar, Generic, Optional

T = TypeVar("T")


class ResponseStruct(Struct, Generic[T]):
    code: int
    data: Optional[T]


@get("/")
def test_handler() -> Response[ResponseStruct[str]]:
    return Response(
        ResponseStruct(code=200, data="Hello World"),
    )
from msgspec import Struct
from litestar import get, Response
from typing import TypeVar, Generic

T = TypeVar("T")


class ResponseStruct(Struct, Generic[T]):
    code: int
    data: T | None


@get("/")
def test_handler() -> Response[ResponseStruct[str]]:
    return Response(
        ResponseStruct(code=200, data="Hello World"),
    )

References: litestar-org/litestar#2383, litestar-org/litestar#2463

Fix rendering of OpenAPI examples#

An issue was fixed where OpenAPI examples would be rendered as

{
  "parameters": [
    {
      "schema": {
        "type": "string",
        "examples": [
          {
            "summary": "example summary",
            "value": "example value"
          }
        ]
      }
    }
  ]
}

instead of

{
  "parameters": [
    {
      "schema": {
        "type": "string"
      },
      "examples": {
        "example1": {
          "summary": "example summary"
          "value": "example value"
        }
      }
    }
  ]
}

References: litestar-org/litestar#2494, litestar-org/litestar#2509

Fix non UTF-8 handling when logging requests#

When structlog is not installed, the request body would not get parsed and shown as a byte sequence. Instead, it was serialized into a string with the assumption that it is valid UTF-8. This was fixed by decoding the bytes with backslashreplace before displaying them.

References: litestar-org/litestar#2529, litestar-org/litestar#2530

Fix ExceptionHandler typing to properly support Exception subclasses#

Fix the typing for ExceptionHandler to support subclasses of Exception, such that code like this will type check properly:

from litestar import Request, Response


class CustomException(Exception): ...


def handle_exc(req: Request, exc: CustomException) -> Response: ...

References: litestar-org/litestar#2520, litestar-org/litestar#2533

Fix OpenAPI schema generation for variable length tuples#

Fix a bug where an annotation such as tuple[str, ...] would cause a TypeError: '<' not supported between instances of 'NoneType' and 'OpenAPIType').

References: litestar-org/litestar#2460, litestar-org/litestar#2552

Fix channels performance issue when polling with no subscribers in arbitrary_channels_allowed mode#

Fix a bug that would cause high CPU loads while idling when using a ChannelsPlugin with the arbitrary_channels_allowed enabled and while no subscriptions for any channel were active.

References: litestar-org/litestar#2547

Fix CLI schema export for non-serializable types when using create_examples=True#

When trying to export a schema via the litestar schema openapi --output schema.json making use of a non-JSON serializable type, would result in an encoding error because the standard library JSON serializer was used. This has been fixed by using Litestar’s own JSON encoder, enabling the serialization of all types supplied by the schema.

References: litestar-org/litestar#2575, litestar-org/litestar#2581

Fix OpenAPI schema generation for Literal and Enum unions with None#

Existing behavior was to make the schema for every type that is a union with None a "one_of" schema, that includes OpenAPIType.NULL in the "one_of" types.

When a Literal or Enum type is in a union with None, this behavior is not desirable, as we want to have null available in the list of available options on the type’s schema.

This was fixed by modifying Literal and Enum schema generation so that i t can be identified that the types are in a union with None, allowing null to be included in Schema.enum values.

References: litestar-org/litestar#2546, litestar-org/litestar#2550

Fix cache overrides when using same route with different handlers#

A bug was fixed that would cause the cache for routes being overwritten by a route handler on that same route with a different HTTP method.

References: litestar-org/litestar#2573,, litestar-org/litestar#2588, litestar-org/litestar#2592

2.2.0#

Released: 2023/10/12

Features#

CLI enabled by default#

The CLI and all its dependencies are now included by default, to enable a better and more consistent developer experience out of the box.

The previous litestar[cli] extra is still available for backwards compatibility, but as of 2.2.0 it is without effect.

References: litestar-org/litestar#2318, litestar-org/litestar#2346

Customization of Pydantic integration via PydanticPlugin#

A new PydanticPlugin has been added, which can be used to configure Pydantic behaviour. Currently it supports setting a prefer_alias option, which will pass the by_alias=True flag to Pydantic when exporting models, as well as generate schemas accordingly.

References: litestar-org/litestar#2373, litestar-org/litestar#2404

Add /schema/openapi.yml to the available schema paths#

The YAML version of the OpenAPI schema is now available under /schema/openapi.yml in addition to /schema/openapi.yaml.

References: litestar-org/litestar#2411

Add experimental DTO codegen backend#

A new DTO backend was introduced which speeds up the transfer process by generating optimized Python code ahead of time. Testing shows that the new backend is between 2.5 and 5 times faster depending on the operation and data provided.

The new backend can be enabled globally for all DTOs by passing the appropriate feature flag to the Litestar application:

from litestar import Litestar
from litestar.config.app import ExperimentalFeatures

app = Litestar(experimental_features=[ExperimentalFeatures.DTO_CODEGEN])

See also

For more information see Improving performance with the codegen backend

References: litestar-org/litestar#2388

Improved error messages for missing required parameters#

Error messages for missing required parameters will now also contain the source of the expected parameter:

Before:

{
  "status_code": 400,
  "detail": "Missing required parameter foo for url http://testerver.local"
}

After:

{
  "status_code": 400,
  "detail": "Missing required header parameter 'foo' for url http://testerver.local"
}

References: litestar-org/litestar#2418

Bugfixes#

Fix implicit conversion of objects to bool in debug response#

The exception handler middleware would, when in debug mode, implicitly call an object’s __bool__, which would lead to errors if that object overloaded the operator, for example if the object in question was a SQLAlchemy element.

References: litestar-org/litestar#2381, litestar-org/litestar#2384

Correctly re-export filters and exceptions from advanced-alchemy#

Some re-exports of filter and exception types from advanced-alchemy were missing, causing various issues when advanced-alchemy was installed, but Litestar would still use its own version of these classes.

References: litestar-org/litestar#2358, litestar-org/litestar#2360

Re-add create_engine method to SQLAlchemy configs#

The create_engine method was removed in an advanced-alchemy releases. This was addresses by re-adding it to the versions provided by Litestar.

References: litestar-org/litestar#2382

Fix before_request modifies route handler signature#

The before_request would modify the return annotation of associated route handlers to conform with its own return type annotation, which would cause issues and unexpected behaviour when that annotation was not compatible with the original one.

This was fixed by not having the before_request handler modify the route handler’s signature. Users are now expected to ensure that values returned from a before_request handler conform to the return type annotation of the route handler.

References: litestar-org/litestar#2368, litestar-org/litestar#2391

Ensure compression is applied before caching when using compression middleware#

A previous limitation was removed that would apply compression from the CompressionMiddleware only after a response was restored from the cache, resulting in unnecessary repeated computation and increased size of the stored response.

This was due to caching being handled on the response layer, where a response object would be pickled, restored upon a cache hit and then re-sent, including all middlewares.

The new implementation now instead applies caching on the ASGI level; Individual messages sent to the send callable are cached, and later re-sent. This process ensures that the compression middleware has been applied before, and will be skipped when re-sending a cached response.

In addition, this increases performance and reduces storage size even in cases where no compression is applied because the slow and inefficient pickle format can be avoided.

References: litestar-org/litestar#1301, litestar-org/litestar#2393

Fix implicit JSON parsing of URL encoded data#

A process was removed where Litestar would implicitly attempt to parse parts of URL encoded data as JSON. This was originally added to provide some performance boosts when that data was in fact meant to be JSON, but turned out to be too fragile.

Regular data conversion / validation is unaffected by this.

References: litestar-org/litestar#2394

2.1.1#

Released: 2023/09/24

Bugfixes#

Fix DeprecationWarning raised by Response.to_asgi_response#

to_asgi_response() was passing a non-None default value ([]) to ASGIResponse for encoded_headers, resulting in a DeprecationWarning being raised. This was fixed by leaving the default value as None.

References: litestar-org/litestar#2364

2.1.0#

Released: 2023/09/23

View the full changelog

Features#

Make 302 the default status_code for redirect responses#

Make 302 the default status_code for redirect responses

References: litestar-org/litestar#2138, litestar-org/litestar#2189

Add include_in_schema() option for all layers#

Adds the include_in_schema() option to all layers, allowing to include/exclude specific routes from the generated OpenAPI schema.

References: litestar-org/litestar#2267, litestar-org/litestar#2295

Deprecate parameter app of Response.to_asgi_response#

Adds deprecation warning for unused app parameter of to_asgi_response as it is unused and redundant due to request.app being available.

References: litestar-org/litestar#2217, litestar-org/litestar#2268

Authentication: Add parameters to set the JWT extras field#

Adds token_extras to both BaseJWTAuth.login() and BaseJWTAuth.create_token() methods, to allow the definition of the extras JWT field.

References: litestar-org/litestar#2313

Templating: Add possibility to customize Jinja environment#

Adds the ability to pass a custom Jinja2 Environment or Mako TemplateLookup by providing a dedicated class method.

References: litestar-org/litestar#965, litestar-org/litestar#2195

Add support for minjinja#

Adds support for MiniJinja, a minimal Jinja2 implementation.

See also

Templating

References: litestar-org/litestar#2250

SQLAlchemy: Exclude implicit fields for SQLAlchemy DTO#

SQLAlchemyDTO (Advanced Alchemy) can now be configured using a separate config object. This can be set using both class inheritance and Annotated:

SQLAlchemyDTO (Advanced Alchemy) can now be configured using a separate config object using config object.#
class MyModelDTO(SQLAlchemyDTO[MyModel]):
    config = SQLAlchemyDTOConfig()

or

SQLAlchemyDTO (Advanced Alchemy) can now be configured using a separate config object using Annotated.#
 MyModelDTO = SQLAlchemyDTO[Annotated[MyModel, SQLAlchemyDTOConfig()]]

The new configuration currently accepts a single attribute which is include_implicit_fields that has a default value of True. If set to to False, all implicitly mapped columns will be hidden from the DTO. If set to hybrid-only, then hybrid properties will be shown but not other implicit columns.

Finally, implicit columns that are marked with Mark.READ_ONLY or Mark.WRITE_ONLY will always be shown regardless of the value of include_implicit_fields.

References: litestar-org/litestar#2170

SQLAlchemy: Allow repository functions to be filtered by expressions#

Enhances the SQLALchemy repository so that you can more easily pass in complex where expressions into the repository functions.

Tip

Without this, you have to override the statement parameter and it separates the where conditions from the filters and the kwargs.

Allows usage of this syntax:

locations, total_count = await model_service.list_and_count(
    ST_DWithin(UniqueLocation.location, geog, 1000), account_id=str(account_id)
)

instead of the previous method of overriding the statement:

locations, total_count = await model_service.list_and_count(
    statement=select(Model).where(ST_DWithin(UniqueLocation.location, geog, 1000)),
    account_id=str(account_id),
)

References: litestar-org/litestar#2265

SQLAlchemy: Use lambda_stmt in the repository#

Converts the repository to use lambda_stmt instead of the normal select

References: litestar-org/litestar#2179

SQLAlchemy: Swap to the advanced_alchemy implementations#

Swaps the internal SQLAlchemy repository to use the external advanced_alchemy library implementations

References: litestar-org/litestar#2312

Bugfixes#

Remove usages of deprecated ExceptionHandlerMiddleware debug parameter#

Removes leftover usages of deprecated ExceptionHandlerMiddleware debug parameter.

References: litestar-org/litestar#2192

DTOs: Raise ValidationException when Pydantic validation fails#

Ensures that when the Pydantic validation fails in the Pydantic DTO, a ValidationException is raised with the extras set to the errors given by Pydantic.

References: litestar-org/litestar#2190, litestar-org/litestar#2204

Set the max width of the console to 80#

Sets the max width of the console to 80, to prevent the output from being wrapped.

References: litestar-org/litestar#2244

Handling of optional path parameters#

Resolves an issue where optional path parameters caused a 500 error to be raised.

References: litestar-org/litestar#2222, litestar-org/litestar#2224

Use os.replace instead of shutil.move for renaming files#

Change to using os.replace() instead of shutil.move() for renaming files, to ensure atomicity.

References: litestar-org/litestar#2223

Exception detail attribute#

Set correctly the detail attribute on LitestarException and HTTPException regardless of whether it’s passed positionally or by name.

References: litestar-org/litestar#2231

Filters not available in exists()#

Fixes exists() method for SQLAlchemy sync and async.

References: litestar-org/litestar#2221, litestar-org/litestar#2228

Add Pydantic types to SQLAlchemy registry only if Pydantic is installed#

Allows importing from litestar.contrib.sqlalchemy.base even if Pydantic is not installed.

References: litestar-org/litestar#2252

Don’t add content type for responses that don’t have a body#

Ensures that the content-type header is not added for responses that do not have a body such as responses with status code 204 (No Content).

References: litestar-org/litestar#2106, litestar-org/litestar#2263

SQLAlchemyPlugin refactored#

Changes the way the SQLAlchemyPlugin to now append the other plugins instead of the inheritance that was previously used. This makes using the plugins.get function work as expected.

References: litestar-org/litestar#2269

Ensure app-dir is appended to path during autodiscovery#

Fixes a bug which caused the --app-dir option to the Litestar CLI to not be propagated during autodiscovery.

References: litestar-org/litestar#2266, litestar-org/litestar#2277

Set content length header by default#

Sets the content-length header by default even if the length of the body is 0.

References: litestar-org/litestar#2271

Incorrect handling of mutable headers in ASGIResponse#

Update ASGIResponse, Response and friends to address a few issues related to headers:

  • If encoded_headers were passed in at any point, they were mutated within responses, leading to a growing list of headers with every response

  • While mutating encoded_headers, the checks performed to assert a value was (not) already present, headers were not treated case-insensitive

  • Unnecessary work was performed while converting cookies / headers into an encoded headers list

This was fixed by:

  • Removing the use of and deprecate encoded_headers

  • Handling headers on ASGIResponse with MutableScopeHeaders, which allows for case-insensitive membership tests, .setdefault operations, etc.

References: litestar-org/litestar#2196, litestar-org/litestar#2308

Adds missing ORM registry export#

Adds an export that was overlooked for the base repo

References: litestar-org/litestar#2316

Discrepancy in attrs, msgspec and Pydantic for multi-part forms#

Resolves issue in attrs, msgspec and Pydantic for multi-part forms

References: litestar-org/litestar#2278, litestar-org/litestar#2280

Set proper default for exclude_http_methods in auth middleware#

Sets OPTIONS as the default value for exclude_http_methods in the base authentication middleware class.

References: litestar-org/litestar#2205, litestar-org/litestar#2325

2.0.0#

Released: 2023/08/19

Bugfixes#

Regression | Missing media_type information to error responses#

Fixed a regression that caused error responses to be sent using a mismatched media type, e.g. an error response from a text/html endpoint would be sent as JSON.

References: litestar-org/litestar#2024, litestar-org/litestar#2131

Regression | Litestar.debug does not propagate to exception handling middleware#

Fixed a regression where setting Litestar.debug would not propagate to the exception handler middleware, resulting in exception responses always being sent using the initial debug value.

References: litestar-org/litestar#2147, litestar-org/litestar#2153

Static files not being served if a route handler with the same base path was registered#

Fixed a bug that would result in a 404 - Not Found when requesting a static file where the path was also used by a route handler.

References: litestar-org/litestar#2154

HTMX: Missing default values for receive and send parameters of HTMXRequest#

Add missing default values for the receive and send parameters of HTMXRequest.

References: litestar-org/litestar#2145

DTO: Excluded attributes accessed during transfer#

Fix the behaviour of DTOs such that they will no longer access fields that have been included. This behaviour would previously cause issues when these attributes were either costly or impossible to access (e.g. lazy loaded relationships of a SQLAlchemy model).

References: litestar-org/litestar#2125, litestar-org/litestar#2127

DTO | Regression: DTOData.create_instance ignores renaming#

Fix a regression where calling create_instance() would ignore the renaming settings of fields.

References: litestar-org/litestar#2144

OpenAPI | Regression: Response schema for files and streams set application/octet-stream as contentEncoding instead of contentMediaType#

Fix a regression that would set application/octet-stream as the contentEncoding instead of contentMediaType in the response schema of File Stream.

References: litestar-org/litestar#2130

OpenAPI | Regression: Response schema diverges from prefer_alias setting for Pydantic models#

Fix a regression that made the response schema use prefer_alias=True, diverging from how Pydantic models are exported by default.

References: litestar-org/litestar#2150

OpenAPI | Regression: Examples not being generated deterministically#

Fix a regression that made generated examples non-deterministic, caused by a misconfiguration of the random seeding.

References: litestar-org/litestar#2161

SQLAlchemy repository: Handling of dialects not supporting JSON#

Fix a bug where SQLAlchemy would raise a TypeError when using a dialect that does not support JSON with the SQLAlchemy repositories.

References: litestar-org/litestar#2137, litestar-org/litestar#2139

JWT | Regression: OPTIONS and HEAD being authenticated by default#

Fix a regression that would make litestar.contrib.jwt.JWTAuthenticationMiddleware authenticate OPTIONS and HEAD requests by default.

References: litestar-org/litestar#2160

SessionAuth | Regression: OPTIONS and HEAD being authenticated by default#

Fix a regression that would make SessionAuthMiddleware authenticate OPTIONS and HEAD requests by default.

References: litestar-org/litestar#2182

2.0.0rc1#

Released: 2023/08/05

Features#

Support for server-sent-events#

Support for Server-sent events <https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events> has been added with the ServerSentEvent:

async def my_generator() -> AsyncGenerator[bytes, None]:
    count = 0
    while count < 10:
        await sleep(0.01)
        count += 1
        yield str(count)


@get(path="/count")
def sse_handler() -> ServerSentEvent:
    return ServerSentEvent(my_generator())

References: litestar-org/litestar#1185, litestar-org/litestar#2035

SQLAlchemy repository: allow specifying id_attribute per method#

The following methods now accept an id_attribute argument, allowing to specify an alternative value to the models primary key:

  • ~litestar.contrib.sqlalchemy.repository.SQLAlchemyAsyncRepository.delete

  • ~litestar.contrib.sqlalchemy.repository.SQLAlchemyAsyncRepository.delete_many

  • ~litestar.contrib.sqlalchemy.repository.SQLAlchemyAsyncRepository.get

  • ~litestar.contrib.sqlalchemy.repository.SQLAlchemyAsyncRepository.update

  • ~litestar.contrib.sqlalchemy.repository.SQLAlchemySyncRepository.delete

  • ~litestar.contrib.sqlalchemy.repository.SQLAlchemySyncRepository.delete_many

  • ~litestar.contrib.sqlalchemy.repository.SQLAlchemySyncRepository.get

  • ~litestar.contrib.sqlalchemy.repository.SQLAlchemySyncRepository.update

References: litestar-org/litestar#2052

SQLAlchemy repository: New upsert_many method#

A new method upsert_many has been added to the SQLAlchemy repositories, providing equivalent functionality to the upsert method for multiple model instances.

See also

~litestar.contrib.sqlalchemy.repository.SQLAlchemyAsyncRepository.upsert_many ~litestar.contrib.sqlalchemy.repository.SQLAlchemySyncRepository.upsert_many

References: litestar-org/litestar#2056

SQLAlchemy repository: New filters: OnBeforeAfter, NotInCollectionFilter and NotInSearchFilter#

The following filters have been added to the SQLAlchemy repositories:

litestar.contrib.repository.filters.OnBeforeAfter

Allowing to filter datetime.datetime columns

litestar.contrib.repository.filters.NotInCollectionFilter

Allowing to filter using a WHERE ... NOT IN (...) clause

litestar.contrib.repository.filters.NotInSearchFilter

Allowing to filter using a WHERE field_name NOT LIKE ‘%’ || :value || ‘%’` clause

References: litestar-org/litestar#2057

SQLAlchemy repository: Configurable chunk sizing for delete_many#

The repository now accepts a chunk_size parameter, determining the maximum amount of parameters in an IN statement before it gets chunked.

This is currently only used in the delete_many method.

References: litestar-org/litestar#2061

SQLAlchemy repository: Support InstrumentedAttribute for attribute columns#

Support InstrumentedAttribute for in the repository’s id_attribute, and the following methods:

  • ~litestar.contrib.sqlalchemy.repository.SQLAlchemyAsyncRepository.delete

  • ~litestar.contrib.sqlalchemy.repository.SQLAlchemyAsyncRepository.delete_many

  • ~litestar.contrib.sqlalchemy.repository.SQLAlchemyAsyncRepository.get

  • ~litestar.contrib.sqlalchemy.repository.SQLAlchemyAsyncRepository.update

  • ~litestar.contrib.sqlalchemy.repository.SQLAlchemySyncRepository.delete

  • ~litestar.contrib.sqlalchemy.repository.SQLAlchemySyncRepository.delete_many

  • ~litestar.contrib.sqlalchemy.repository.SQLAlchemySyncRepository.get

  • ~litestar.contrib.sqlalchemy.repository.SQLAlchemySyncRepository.update

References: litestar-org/litestar#2054

OpenAPI: Support callable operation_id on route handlers#

Route handlers may be passed a callable to operation_id to create the OpenAPI operation ID.

References: litestar-org/litestar#2078

Run event listeners concurrently#

Events now run concurrently inside a task group.

References: litestar-org/litestar#2096

Support extending the CLI with plugins#

A new plugin protocol CLIPluginProtocol has been added that can be used to extend the Litestar CLI.

See also

Using a plugin

References: litestar-org/litestar#2066

Bugfixes#

DTO: Support renamed fields in DTOData and create_instance#

A bug was fixed that would cause field renaming to be skipped within DTOData and create_instance().

References: litestar-org/litestar#2065

SQLAlchemy repository: Fix health_check for oracle#

The emitted statement for oracle has been changed to SELECT 1 FROM DUAL.

References: litestar-org/litestar#2060

Fix serialization of empty strings in multipart form#

A bug was fixed that would cause a validation error to be raised for empty strings during multipart form decoding.

References: litestar-org/litestar#2044

Other changes#

Use debug mode by default in test clients#

The test clients will now default to debug=True instead of debug=None.

References: litestar-org/litestar#2113

Removal of deprecated partial module#breaking

The deprecated litestar.partial has been removed. It can be replaced with DTOs, making use of the DTOConfig option partial=True.

References: litestar-org/litestar#2113

Removal of deprecated dto/factory module#breaking

The deprecated module litestar.dto.factory has been removed.

References: litestar-org/litestar#2114

Removal of deprecated contrib/msgspec module#breaking

The deprecated module litestar.contrib.msgspec has been removed.

References: litestar-org/litestar#2114

2.0.0beta4#

Released: 2023/07/21

Bugfixes#

Fix extra package dependencies#

A workaround for a bug in poetry that caused development / extra dependencies to be installed alongside the package has been added.

References: litestar-org/litestar#2029

2.0.0beta3#

Released: 2023/07/20

Features#

SQLAlchemyDTO (Advanced Alchemy): column/relationship type inference#

If type annotations aren’t available for a given column/relationship, they may be inferred from the mapped object.

For columns, the type‘s python_type will be used as the type of the column, and the nullable property to determine if the field should have a None union.

For relationships, where the RelationshipProperty.direction is ONETOMANY or MANYTOMANY, RelationshipProperty.collection_class and RelationshipProperty.mapper.class_ are used to construct an annotation for the collection.

For one-to-one relationships, RelationshipProperty.mapper.class_ is used to get the type annotation, and will be made a union with None if all of the foreign key columns are nullable.

References: litestar-org/litestar#1853, litestar-org/litestar#1879

DTO: Piccolo ORM#

Add support for piccolo ORM with the PiccoloDTO.

References: litestar-org/litestar#1896

OpenAPI: Allow setting OpenAPIController.path from `OpenAPIConfig#

path has been added, which can be used to set the path for OpenAPIController directly, without needing to create a custom instance of it.

If path is set in both OpenAPIConfig and OpenAPIController, the path set on the controller will take precedence.

References: litestar-org/litestar#1886

SQLAlchemy repository: auto_commit, auto_expunge and auto_refresh options#

Three new parameters have been added to the repository and various methods:

auto_commit

When this True, the session will commit() instead of flush() before returning.

Available in:

  • ~SQLAlchemyAsyncRepository.add

  • ~SQLAlchemyAsyncRepository.add_many

  • ~SQLAlchemyAsyncRepository.delete

  • ~SQLAlchemyAsyncRepository.delete_many

  • ~SQLAlchemyAsyncRepository.get_or_create

  • ~SQLAlchemyAsyncRepository.update

  • ~SQLAlchemyAsyncRepository.update_many

  • ~SQLAlchemyAsyncRepository.upsert

(and their sync equivalents)

auto_refresh

When True, the session will execute refresh() objects before returning.

Available in:

  • ~SQLAlchemyAsyncRepository.add

  • ~SQLAlchemyAsyncRepository.get_or_create

  • ~SQLAlchemyAsyncRepository.update

  • ~SQLAlchemyAsyncRepository.upsert

(and their sync equivalents)

auto_expunge

When this is True, the session will execute expunge() all objects before returning.

Available in:

  • ~SQLAlchemyAsyncRepository.add

  • ~SQLAlchemyAsyncRepository.add_many

  • ~SQLAlchemyAsyncRepository.delete

  • ~SQLAlchemyAsyncRepository.delete_many

  • ~SQLAlchemyAsyncRepository.get

  • ~SQLAlchemyAsyncRepository.get_one

  • ~SQLAlchemyAsyncRepository.get_one_or_none

  • ~SQLAlchemyAsyncRepository.get_or_create

  • ~SQLAlchemyAsyncRepository.update

  • ~SQLAlchemyAsyncRepository.update_many

  • ~SQLAlchemyAsyncRepository.list

  • ~SQLAlchemyAsyncRepository.upsert

(and their sync equivalents)

References: litestar-org/litestar#1900

Include path name in ImproperlyConfiguredException message for missing param types#

The message of a ImproperlyConfiguredException raised when a path parameter is missing a type now contains the name of the path.

References: litestar-org/litestar#1935

DTO: New include parameter added to DTOConfig#

include has been added to DTOConfig, providing a counterpart to exclude.

If include is provided, only those fields specified within it will be included.

References: litestar-org/litestar#1950

Pydantic 2 support#

Pydantic 2 is now supported alongside Pydantic 1.

References: litestar-org/litestar#1956

Bugfixes#

SQLAlchemy repository: Fix audit columns defaulting to app startup time#

A bug was fixed where ~litestar.contrib.sqlalchemy.base.AuditColumns.created_at and ~litestar.contrib.sqlalchemy.base.AuditColumns.updated_at would default to the datetime at initialization time, instead of the time of the update.

References: litestar-org/litestar#1894

SQLAlchemyDTO (Advanced Alchemy): Fix handling of Sequence with defaults#

Fixes handling of columns defined with Sequence default values.

The SQLAlchemy default value for a Column will be ignored when it is a Sequence object. This is because the SQLAlchemy sequence types represent server generated values, and there is no way for us to generate a reasonable default value for that field from it without making a database query, which is not possible deserialization.

References: litestar-org/litestar#1851, litestar-org/litestar#1883

Allow JSON as redirect response#

Enables using redirect responses with a JSON media type.

References: litestar-org/litestar#1908

DTO / OpenAPI: Fix detection of required fields for Pydantic and msgspec DTOs#

A bug was fixed that would lead to fields of a Pydantic model or msgspec Structs being marked as “not required” in the generated OpenAPI schema when used with DTOs.

References: litestar-org/litestar#1946

Other changes#

AbstractDTOFactory moved to dto.factory.base#breaking

AbstractDTOFactory has moved from litestar.dto.factory.abc to litestar.dto.factory.base.

References: litestar-org/litestar#1950

SQLAlchemy repository: Rename _sentinel column to sa_orm_sentinel#breaking

The _sentinel column of ~litestar.contrib.sqlalchemy.base.UUIDPrimaryKey has been renamed to sa_orm_sentinel, to support Spanner, which does not support tables starting with _.

References: litestar-org/litestar#1933

Replace Header, CacheControlHeader and ETag Pydantic models with dataclasses#breaking

As part of the removal of Pydantic as a hard dependency, the header models Header, CacheControlHeader and ETag have been replaced with dataclasses.

Note

Although marked breaking, this change should not affect usage unless you relied on these being Pydantic models in some way.

References: litestar-org/litestar#1917

Pydantic as an optional dependency#breaking

As of this release, Pydantic is no longer a required dependency of Litestar. It is still supported in the same capacity as before, but Litestar itself does not depend on it anymore in its internals.

References: litestar-org/litestar#1963

Deprecation of partial module#

The litestar.partial and litestar.partial.Partial have been deprecated and will be removed in a future release. Users are advised to upgrade to DTOs, making use of the DTOConfig option partial=True.

References: litestar-org/litestar#2002

2.0.0beta2#

Released: 2023/06/24

Features#

Support annotated-types#

Extended support for the annotated-types library is now available.

References: litestar-org/litestar#1847

Increased verbosity of validation error response keys#breaking

The keys in validation error responses now include the full path to the field where the originated.

An optional source key has been added, signifying whether the value is from the body, a cookie, a header, or a query param.

before#
{
  "status_code": 400,
  "detail": "Validation failed for POST http://localhost:8000/some-route",
  "extra": [
    {"key": "int_param", "message": "value is not a valid integer"},
    {"key": "int_header", "message": "value is not a valid integer"},
    {"key": "int_cookie", "message": "value is not a valid integer"},
    {"key": "my_value", "message": "value is not a valid integer"}
  ]
}
after#
{
  "status_code": 400,
  "detail": "Validation failed for POST http://localhost:8000/some-route",
  "extra": [
    {"key": "child.my_value", "message": "value is not a valid integer", "source": "body"},
    {"key": "int_param", "message": "value is not a valid integer", "source": "query"},
    {"key": "int_header", "message": "value is not a valid integer", "source": "header"},
    {"key": "int_cookie", "message": "value is not a valid integer", "source": "cookie"},
  ]
}

References: litestar-org/litestar#1774

TestClient default timeout#breaking

A timeout parameter was added to

The value is passed down to the underlying HTTPX client and serves as a default timeout for all requests.

References: litestar-org/litestar#1840

SQLAlchemy DTO: Explicit error messages when type annotations for a column are missing#

Replace the nondescript KeyError raised when a SQLAlchemy DTO is constructed from a model that is missing a type annotation for an included column with an ImproperlyConfiguredException, including an explicit error message, pointing at the potential cause.

References: litestar-org/litestar#1852

Bugfixes#

Remove exception details from Internal Server Error responses#

Error responses with a 500 status code will now always use “Internal Server Error” as default detail.

References: litestar-org/litestar#1856, litestar-org/litestar#1857

Pydantic v1 regex validation#

A regression has been fixed in the Pydantic signature model logic, which was caused by the renaming of regex to pattern, which would lead to the pattern not being validated.

References: litestar-org/litestar#1860, litestar-org/litestar#1865

2.0.0beta1#

Released: 2023/06/16

Features#

Expose ParsedType as public API#

Expose the previously private litestar.typing.ParsedType. This is mainly indented for usage with litestar.plugins.SerializationPluginProtocol.supports_type()

References: litestar-org/litestar#1677, litestar-org/litestar#1567

Improved debugging capabilities#
  • A new pdb_on_exception parameter was added to Litestar. When set to True, Litestar will drop into a the Python debugger when an exception occurs. It defaults to None

  • When pdb_on_exception is None, setting the environment variable LITESTAR_PDB=1 can be used to enable this behaviour

  • When using the CLI, passing the --pdb flag to the run command will temporarily set the environment variable LITESTAR_PDB=1

References: litestar-org/litestar#1742

OpenAPI: Add operation_class argument to HTTP route handlers#

The operation_class argument was added to HTTPRouteHandler and the corresponding decorators, allowing to override the Operation class, to enable further customization of the generated OpenAPI schema.

References: litestar-org/litestar#1732

OpenAPI: Support nested Literal annotations#

Support nested typing.Literal annotations by flattening them into a single Literal.

References: litestar-org/litestar#1829

CLI: Add --reload-dir option to run command#

A new --reload-dir option was added to the litestar run command. When used, --reload is implied, and the server will watch for changes in the given directory.

References: litestar-org/litestar#1689

Allow extra attributes on JWTs via extras attribute#

Add the litestar.contrib.jwt.Token.extras attribute, containing extra attributes found on the JWT.

References: litestar-org/litestar#1695

Add default modes for Websocket.iter_json and WebSocket.iter_data#

Add a default mode for iter_json() and iter_data(), with a value of text.

References: litestar-org/litestar#1733

SQLAlchemy repository: Synchronous repositories#

Add a new synchronous repository base class: litestar.contrib.sqlalchemy.repository.SQLAlchemySyncRepository, which offer the same functionality as its asynchronous counterpart while operating on a synchronous sqlalchemy.orm.Session.

References: litestar-org/litestar#1683

SQLAlchemy repository: Oracle Database support#

Add support for Oracle Database via oracledb.

References: litestar-org/litestar#1694

SQLAlchemy repository: DuckDB support#

Add support for DuckDB.

References: litestar-org/litestar#1744

SQLAlchemy repository: Google Spanner support#

Add support for Google Spanner.

References: litestar-org/litestar#1744

SQLAlchemy repository: JSON check constraint for Oracle Database#

When using the litestar.contrib.sqlalchemy.types.JsonB type with an Oracle Database engine, a JSON check constraint will be created for that column.

References: litestar-org/litestar#1780

SQLAlchemy repository: Remove created and updated columns#breaking

The created and updated columns have been superseded by created_at and updated_at respectively, to prevent name clashes.

References: litestar-org/litestar#1816

SQLAlchemy repository: Add timezone aware type#breaking

A new timezone aware type litestar.contrib.sqlalchemy.types.DateTimeUTC has been added, which enforces UTC timestamps stored in the database.

References: litestar-org/litestar#1816

SQLAlchemy repository: Exclude unloaded columns in to_dict#

When exporting models using the ~litestar.contrib.sqlalchemy.base.CommonTableAttributes.to_dict method, unloaded columns will now always be excluded. This prevents implicit I/O via lazy loading, and errors when using an asynchronous session.

References: litestar-org/litestar#1802

DTOs: Nested keyword arguments in .create_instance()#

The DTOData.create_instance method now supports providing values for arbitrarily nested data via kwargs using a double-underscore syntax, for example data.create_instance(foo__bar="baz").

References: litestar-org/litestar#1727, litestar-org/litestar#1741

DTOs: Hybrid properties and association proxies in SQLAlchemyDTO (Advanced Alchemy)#

The SQLAlchemyDTO (Advanced Alchemy) now supports hybrid attribute and associationproxy.

The generated field will be marked read-only.

References: litestar-org/litestar#1754, litestar-org/litestar#1776

DTOs: Transfer to generic collection types#

DTOs can now be wrapped in generic collection types such as typing.Sequence. These will be substituted with a concrete and instantiable type at run time, e.g. in the case of Sequence a list.

References: litestar-org/litestar#1763, litestar-org/litestar#1764

DTOs: Data transfer for non-generic builtin collection annotations#

Non-parametrized generics in annotations (e.g. a: dict) will now be inferred as being parametrized with Any. a: dict is then equivalent to a: dict[Any, Any].

References: litestar-org/litestar#1799

DTOs: Exclude leading underscore fields by default#breaking

Leading underscore fields will not be excluded by default. This behaviour can be configured with the newly introduced underscore_fields_private configuration value, which defaults to True.

References: litestar-org/litestar#1768, litestar-org/litestar#1777

DTOs: Msgspec and Pydantic DTO factory implementation#

DTO factories for msgspec and Pydantic have been added:

  • MsgspecDTO

  • PydanticDTO

References: litestar-org/litestar#1531,, litestar-org/litestar#1532, litestar-org/litestar#1712

Bugfixes#

Store and reuse state deep_copy directive when copying state#

App state can be created using deep_copy=False, however state would still be deep copied for dependency injection.

This was fixed memoizing the value of deep_copy when state is created, and reusing it on subsequent copies.

References: litestar-org/litestar#1674, litestar-org/litestar#1678

ParsedType.is_subclass_of(X) True for union if all union types are subtypes of X#

When ParsedType was introduced, is_subclass_of() any union was deliberately left to return False with the intention of waiting for some use-cases to arrive.

This behaviour was changed to address an issue where a handler may be typed to return a union of multiple response types; If all response types are Response subtypes then the correct response handler will now be applied.

References: litestar-org/litestar#1652, litestar-org/litestar#1690

Inconsistent template autoescape behavior#

The mako template engine now defaults to autoescaping expressions, making it consistent with config of Jinja template engine.

References: litestar-org/litestar#1699, litestar-org/litestar#1718

Missing ChannelsPlugin in signature namespace population#

The ChannelsPlugin has been added to the signature namespace, fixing an issue where using from __future__ import annotations or stringized annotations would lead to a NameError, if the plugin was not added to the signatured namespace manually.

References: litestar-org/litestar#1691, litestar-org/litestar#1719

Gzip middleware not sending small streaming responses#

A bug was fixed that would cause smaller streaming responses to not be sent at all when the CompressionMiddleware was used with gzip.

References: litestar-org/litestar#1681, litestar-org/litestar#1723

Premature transfer to nested models with DTOData#

An issue was fixed where data that should be transferred to builtin types on instantiation of DTOData was being instantiated into a model type for nested models.

References: litestar-org/litestar#1726, litestar-org/litestar#1731

Incorrect sync_to_thread usage warnings for generator dependencies#

A bug was fixed that caused incorrect warnings about missing sync_to_thread usage were issues when asynchronous generators were being used as dependencies.

References: litestar-org/litestar#1711, litestar-org/litestar#1716, litestar-org/litestar#1740

Dependency injection custom dependencies in WebSocketListener#

An issue was resolved that would cause failures when dependency injection was being used with custom dependencies (that is, injection of things other than state, query, path parameters, etc.) within a WebsocketListener.

References: litestar-org/litestar#1762, litestar-org/litestar#1807

OpenAPI schema for Dict[K, V] ignores generic#

An issue with the OpenAPI schema generation was fixed that would lead to generic arguments to dict being ignored.

An type like dict[str, int] now correctly renders as {"type": "object", "additionalProperties": { "type": "integer" }}.

References: litestar-org/litestar#1795, litestar-org/litestar#1828

WebSocketTestSession not timing out without when connection is not accepted#

A bug was fixed that caused WebSocketTestSession to block indefinitely when if accept() was never called, ignoring the timeout parameter.

References: litestar-org/litestar#1696

SQLAlchemy repository: Fix alembic migrations generated for models using GUID#

Migrations generated for models with a ~litestar.contrib.sqlalchemy.types.GUID type would erroneously add a length=16 on the input. Since this parameter is not defined in the type’s the __init__ method. This was fixed by adding the appropriate parameter to the type’s signature.

References: litestar-org/litestar#1676

Other changes#

DTOs: Arbitrary generic wrappers#

When a handler returns a type that is not supported by the DTO, but:

  • the return type is generic

  • it has a generic type argument that is supported by the dto

  • the type argument maps to an attribute on the return type

the DTO operations will be performed on the data retrieved from that attribute of the instance returned from the handler, and return the instance.

The constraints are:

  • the type returned from the handler must be a type that litestar can natively encode

  • the annotation of the attribute that holds the data must be a type that DTOs can otherwise manage

from dataclasses import dataclass
from typing import Generic, List, TypeVar

from typing_extensions import Annotated

from litestar import Litestar, get
from litestar.dto import DTOConfig
from litestar.dto.factory.dataclass_factory import DataclassDTO


@dataclass
class User:
    name: str
    age: int


T = TypeVar("T")
V = TypeVar("V")


@dataclass
class Wrapped(Generic[T, V]):
    data: List[T]
    other: V


@get(dto=DataclassDTO[Annotated[User, DTOConfig(exclude={"age"})]])
def handler() -> Wrapped[User, int]:
    return Wrapped(
        data=[User(name="John", age=42), User(name="Jane", age=43)],
        other=2,
    )


app = Litestar(route_handlers=[handler])

# GET "/": {"data": [{"name": "John"}, {"name": "Jane"}], "other": 2}
from dataclasses import dataclass
from typing import Generic, TypeVar

from typing import Annotated

from litestar import Litestar, get
from litestar.dto import DTOConfig
from litestar.dto.factory.dataclass_factory import DataclassDTO


@dataclass
class User:
    name: str
    age: int


T = TypeVar("T")
V = TypeVar("V")


@dataclass
class Wrapped(Generic[T, V]):
    data: list[T]
    other: V


@get(dto=DataclassDTO[Annotated[User, DTOConfig(exclude={"age"})]])
def handler() -> Wrapped[User, int]:
    return Wrapped(
        data=[User(name="John", age=42), User(name="Jane", age=43)],
        other=2,
    )


app = Litestar(route_handlers=[handler])

# GET "/": {"data": [{"name": "John"}, {"name": "Jane"}], "other": 2}

References: litestar-org/litestar#1631,, litestar-org/litestar#1798, litestar-org/litestar#1801

Remove state parameter from AfterExceptionHookHandler and BeforeMessageSendHookHandler#breaking

Remove the state parameter from AfterExceptionHookHandler and BeforeMessageSendHookHandler.

AfterExceptionHookHandlers will have to be updated from

async def after_exception_handler(
    exc: Exception, scope: Scope, state: State
) -> None: ...

to

async def after_exception_handler(exc: Exception, scope: Scope) -> None: ...

The state can still be accessed like so:

async def after_exception_handler(exc: Exception, scope: Scope) -> None:
    state = scope["app"].state

BeforeMessageSendHookHandlers will have to be updated from

async def before_send_hook_handler(
    message: Message, state: State, scope: Scope
) -> None: ...

to

async def before_send_hook_handler(message: Message, scope: Scope) -> None: ...

where state can be accessed in the same manner:

async def before_send_hook_handler(message: Message, scope: Scope) -> None:
    state = scope["app"].state

References: litestar-org/litestar#1739

Removal of dto.exceptions module#breaking

The module dto.exceptions has been removed, since it was not used anymore internally by the DTO implementations, and superseded by standard exceptions.

References: litestar-org/litestar#1773

BaseRouteHandler no longer generic#breaking

BaseRouteHandler was originally made generic to support proper typing of the ownership_layers property, but the same effect can now be achieved using typing.Self.

References: litestar-org/litestar#1819

Deprecation of Litestar parameter preferred_validation_backend#breaking

The following changes have been made regarding the preferred_validation_backend:

  • The preferred_validation_backend parameter of Litestar has been renamed to _preferred_validation_backend and deprecated. It will be removed completely in a future version.

  • The Litestar.preferred_validation_backend attribute has been made private

  • The preferred_validation_backend attribute has been removed from AppConfig

In addition, the logic for selecting a signature validation backend has been simplified as follows: If the preferred backend is set to attrs, or the signature contains attrs types, attrs is selected. In all other cases, Pydantic will be used.

References: litestar-org/litestar#1810

Response.get_serializer moved to serialization.get_serializer#breaking

The Response.get_serializer() method has been removed in favor of the get_serializer() function.

In the previous Response implementation, get_serializer() was called on the response inside the response’s __init__, and the merging of class-level type_encoders with the Response‘s type_encoders occurred inside its get_serializer method.

In the current version of Response, the response body is not encoded until after the response object has been returned from the handler, and it is converted into a low-level ASGIResponse object. Due to this, there is still opportunity for the handler layer resolved type_encoders object to be merged with the Response defined type_encoders, making the merge inside the Response no longer necessary.

In addition, the separate get_serializer function greatly simplifies the interaction between middlewares and serializers, allowing to retrieve one independently from a Response.

References: litestar-org/litestar#1820

Remove response containers and introduce ASGIResponse#breaking

Response Containers were wrapper classes used to indicate the type of response returned by a handler, for example File, Redirect, Template and Stream types. These types abstracted the interface of responses from the underlying response itself.

Response containers have been removed and their functionality largely merged with that of Response. The predefined response containers still exist functionally, as subclasses of Response and are now located within the litestar.response module. In addition to the functionality of Response containers, they now also feature all of the response’s functionality, such as methods to add headers and cookies.

The Response class now only serves as a wrapper and context object, and does not handle the data sending part, which has been delegated to a newly introduced ASGIResponse. This type (and its subclasses) represent the response as an immutable object and are used internally by Litestar to perform the I/O operations of the response. These can be created and returned from handlers like any other ASGI application, however they are low-level, and lack the utility of the higher-level response types.

References: litestar-org/litestar#1790

2.0.0alpha7#

Released: 2023/05/14

Features#

Warn about sync callables in route handlers and dependencies without an explicit sync_to_thread value#

A warning will now be raised when a synchronous callable is being used in an HTTPRouteHandler or Provide, without setting sync_to_thread. This is to ensure that synchronous callables are handled properly, and to prevent accidentally using callables which might block the main thread.

This warning can be turned off globally by setting the environment variable LITESTAR_WARN_IMPLICIT_SYNC_TO_THREAD=0.

See also

Sync vs. Async

References: litestar-org/litestar#1648, litestar-org/litestar#1655

Warn about sync_to_thread with async callables#

A warning will be raised when sync_to_thread is being used in HTTPRouteHandler or Provide with an asynchronous callable, as this will have no effect.

This warning can be turned off globally by setting the environment variable LITESTAR_WARN_SYNC_TO_THREAD_WITH_ASYNC=0.

References: litestar-org/litestar#1664

WebSockets: Dependencies in listener hooks#

Dependencies can now be used in the websocket_listener hooks on_accept, on_disconnect and the connection_lifespan context manager. The socket parameter is therefore also not mandatory anymore in those callables.

References: litestar-org/litestar#1647

Declaring dependencies without Provide#

Dependencies can now be declared without using Provide. The callables can be passed directly to the dependencies dictionary.

References: litestar-org/litestar#1647

Add DTOData to receive unstructured but validated DTO data#

DTOData is a datastructure for interacting with DTO validated data in its unstructured form.

This utility is to support the case where the amount of data that is available from the client request is not complete enough to instantiate an instance of the model that would otherwise be injected.

References: litestar-org/litestar#1650

Partial DTOs#

Add a partial flag to DTOConfig, making all DTO fields options. Subsequently, any unset values will be filtered when extracting data from transfer models.

This allows for example to use a to handle PATCH requests more easily.

References: litestar-org/litestar#1651

SQLAlchemy repository: psycopg asyncio support#

Async psycopg is now officially supported and tested for the SQLAlchemy repository.

References: litestar-org/litestar#1657

SQLAlchemy repository: BigIntPrimaryKey mixin#

~litestar.contrib.sqlalchemy.base.BigIntPrimaryKey mixin, providing a BigInt primary key column, with a fallback to Integer for sqlite.

References: litestar-org/litestar#1657

SQLAlchemy repository: Store GUIDs as binary on databases that don’t have a native GUID type#

On databases without native support for GUIDs, ~litestar.contrib.sqlalchemy.types.GUID will now fall back to BINARY(16).

References: litestar-org/litestar#1657

Application lifespan context managers#

A new lifespan argument has been added to Litestar, accepting an asynchronous context manager, wrapping the lifespan of the application. It will be entered with the startup phase and exited on shutdown, providing functionality equal to the on_startup and on_shutdown hooks.

References: litestar-org/litestar#1635

Unify application lifespan hooks: Remove before_ and after_#breaking

The following application lifespan hooks have been removed:

  • before_startup

  • after_startup

  • before_shutdown

  • after_shutdown

The remaining hooks on_startup and on_shutdown will now receive as their optional first argument the Litestar application instead of the application’s state.

References: litestar-org/litestar#1663

Trio-compatible event emitter#

The default SimpleEventEmitter is now compatible with trio.

References: litestar-org/litestar#1666

OpenAPI: Support msgspec.Meta#

msgspec.Meta is now fully supported for OpenAPI schema generation.

References: litestar-org/litestar#1669

OpenAPI: Support Pydantic FieldInfo#

Pydantic’s FieldInfo (regex, gt, title, etc.) now have full support for OpenAPI schema generation.

References: litestar-org/litestar#1541, litestar-org/litestar#1670

Bugfixes#

OpenAPI: Fix name collision in DTO models#

A bug was fixed that would lead to name collisions in the OpenAPI schema when using DTOs with the same class name. DTOs now include a short 8 byte random string in their generated name to prevent this.

References: litestar-org/litestar#1643, litestar-org/litestar#1649

Fix validated attrs model being injected as a dictionary#

A bug was fixed that would lead to an attrs model used to validate a route handler’s data not being injected itself but as a dictionary representation.

References: litestar-org/litestar#1643, litestar-org/litestar#1668

Validate unknown media types#breaking

An unknown media type in places where Litestar can’t infer the type from the return annotation, an ImproperlyConfiguredException will now be raised.

References: litestar-org/litestar#1446, litestar-org/litestar#1671

2.0.0alpha6#

Released: 2023/05/09

Features#

Add connection_accept_handler to websocket_listener#

Add a new connection_accept_handler parameter to websocket_listener, which can be used to customize how a connection is accepted, for example to add headers or subprotocols

References: litestar-org/litestar#1571, litestar-org/litestar#1572

Testing: Add block and timeout parameters to WebSocketTestSession receive methods#

Two parameters, block and timeout have been added to the following methods:

References: litestar-org/litestar#1593

CLI: Add --app-dir option to root command#

The --app-dir option was added to the root CLI command, allowing to set the run applications from a path that’s not the current working directory.

References: litestar-org/litestar#1506

WebSockets: Data iterators#

Two new methods were added to the WebSocket connection, which allow to continuously receive data and iterate over it:

References: litestar-org/litestar#1626

WebSockets: MessagePack support#

Add support for MessagePack to the WebSocket connection.

Three new methods have been added for handling MessagePack:

In addition, two MessagePack related methods were added to WebSocketTestSession:

References: litestar-org/litestar#1626

SQLAlchemy repository: Add support for sentinel column#

This change adds support for sentinel column feature added in sqlalchemy 2.0.10. Without it, there are certain cases where add_many raises an exception.

The _sentinel value added to the declarative base should be excluded from normal select operations automatically and is excluded in the to_dict methods.

References: litestar-org/litestar#1603

DTO: Alias generator for field names#

A new argument rename_strategy has been added to the DTOConfig, allowing to remap field names with strategies such as “camelize”.

References: litestar-org/litestar#1590

DTO: Nested field exclusion#

This feature adds support for excluding nested model fields using dot-notation, e.g., "a.b" excludes field b from nested model field a

References: litestar-org/litestar#1197, litestar-org/litestar#1596

WebSockets: Managing a socket’s lifespan using a context manager in websocket listeners#

Changes the way a socket’s lifespan - accepting the connection and calling the appropriate event hooks - to use a context manager.

The connection_lifespan argument was added to the WebSocketListener, which accepts an asynchronous context manager, which can be used to handle the lifespan of the socket.

References: litestar-org/litestar#1625

New module: Channels#

A new module channels has been added: A general purpose event streaming library, which can for example be used to broadcast messages via WebSockets.

References: litestar-org/litestar#1587

Bugfixes#

Relax typing of **kwargs in ASGIConnection.url_for#

Change the typing of the **kwargs in ASGIConnection.url_for from dict[str, Any] to Any

References: litestar-org/litestar#1610

Fix: Using websocket_listener in controller causes TypeError#

A bug was fixed that would cause a type error when using a websocket_listener in a Controller

References: litestar-org/litestar#1615, litestar-org/litestar#1627

Other changes#

DTO: Undocumented dto.factory.backends has been made private#breaking

The undocumented dto.factory.backends module has been made private

References: litestar-org/litestar#1589

2.0.0alpha5#

Features#

Pass template context to HTMX template response#

Pass the template context to the Template returned by htmx.Response.

References: litestar-org/litestar#1488

OpenAPI support for attrs and msgspec classes#

Support OpenAPI schema generation for attrs classes and msgspec Structs.

References: litestar-org/litestar#1487

SQLAlchemy repository: Add ModelProtocol#

Add a new class contrib.sqlalchemy.base.ModelProtocol, serving as a generic model base type, allowing to specify custom base classes while preserving typing information

References: litestar-org/litestar#1503

SQLAlchemy repository: Support MySQL/MariaDB#

Add support for MySQL/MariaDB to the SQLAlchemy repository, using the asyncmy driver.

References: litestar-org/litestar#1345

SQLAlchemy repository: Support MySQL/MariaDB#

Add support for MySQL/MariaDB to the SQLAlchemy repository, using the asyncmy driver.

References: litestar-org/litestar#1345

SQLAlchemy repository: Add matching logic to get_or_create#

Add a match_fields argument to litestar.contrib.sqlalchemy.repository.SQLAlchemyAsyncRepository.get_or_create. This lets you lookup a model using a subset of the kwargs you’ve provided. If the remaining kwargs are different from the retrieved model’s stored values, an update is performed.

References: litestar-org/litestar#1345

Repository: Extend filter types#

Add new filters litestar.contrib.repository.filters.OrderBy and litestar.contrib.repository.filters.SearchFilter, providing ORDER BY ... and LIKE ... / ILIKE ... clauses respectively

References: litestar-org/litestar#1345

DTO: Add AbstractDTOFactory and backends#

An all-new DTO implementation was added, using AbstractDTOFactory as a base class, providing Pydantic and msgspec backends to facilitate (de)serialization and validation.

References: litestar-org/litestar#1461

WebSockets: Support DTOs in listeners#

Support for DTOs has been added to WebSocketListener and WebSocketListener. A dto and return_dto parameter has been added, providing the same functionality as their route handler counterparts.

References: litestar-org/litestar#1518

DTO based serialization plugin#breaking

SerializationPluginProtocol has been re-implemented, leveraging the new DTOInterface.

If a handler defines a plugin supported type as either the data kwarg type annotation, or as the return annotation for a handler function, and no DTO has otherwise been resolved to handle the type, the protocol creates a DTO implementation to represent that type which is then used to de-serialize into, and serialize from instances of that supported type.

Important

The Piccolo ORM and Tortoise ORM plugins have been removed by this change, but will be re-implemented using the new patterns in a future release leading up to the 2.0 release.

References: litestar-org/litestar#1501

Bugfixes#

Fix inconsistent parsing of unix timestamp between Pydantic and cattrs#

Timestamps parsed as date with Pydantic return a UTC date, while cattrs implementation return a date with the local timezone.

This was corrected by forcing dates to UTC when being parsed by attrs.

References: litestar-org/litestar#1491, litestar-org/litestar#1492

Fix: Retrieve type hints from class with no __init__ method causes error#

An error would occur when using a callable without an object.__init__() method was used in a placed that would cause it to be inspected (such as a route handler’s signature).

This was caused by trying to access the __module__ attribute of object.__init__(), which would fail with

'wrapper_descriptor' object has no attribute '__module__'

References: litestar-org/litestar#1504, litestar-org/litestar#1505

Fix error raised for partially installed attrs dependencies#

An error was fixed that would cause a MissingDependencyException to be raised when dependencies for attrs were partially installed. This was fixed by being more specific about the missing dependencies in the error messages.

References: litestar-org/litestar#1543

Remove bool coercion in URL parsing#breaking

When defining a query parameter as param: str, and passing it a string value of "true", the value received by the route handler was the string "True", having been title cased. The same was true for the value of "false".

This has been fixed by removing the coercing of boolean-like values during URL parsing and leaving it up to the parsing utilities of the receiving side (i.e. the handler’s signature model) to handle these values according to the associated type annotations.

References: litestar-org/litestar#1547, litestar-org/litestar#1550

Fix missing content-encoding headers on gzip/brotli compressed files#

Fixed a bug that would cause static files served via StaticFilesConfig that have been compressed with gripz or brotli to miss the appropriate content-encoding header.

References: litestar-org/litestar#1576, litestar-org/litestar#1577

Other changes#

SQLAlchemy repository: Rename SQLAlchemyRepository > SQLAlchemyAsyncRepository#breaking

SQLAlchemyRepository has been renamed to litestar.contrib.sqlalchemy.repository.SQLAlchemyAsyncRepository.

References: litestar-org/litestar#1345

DTO: Remove from_connection / extend from_data#breaking

The method DTOInterface.from_connection has been removed and replaced by DTOInterface.from_bytes, which receives both the raw bytes from the connection, and the connection instance. Since from_bytes now does not handle connections anymore, it can also be a synchronous method, improving symmetry with DTOInterface.from_bytes.

The signature of from_data has been changed to also accept the connection, matching from_bytes’ signature.

As a result of these changes, DTOInterface.from_bytes no longer needs to receive the connection instance, so the request parameter has been dropped.

References: litestar-org/litestar#1500

SQLAlchemy 1 contrib module removed#breaking

As a result of the changes introduced in #1501, SQLAlchemy 1 support has been dropped.

Note

If you rely on SQLAlchemy 1, you can stick to Starlite 1.51 for now. In the future, a SQLAlchemy 1 plugin may be released as a standalone package.

References: litestar-org/litestar#1501

Change MissingDependencyException to be a subclass of ImportError#

MissingDependencyException is now a subclass of ImportError, to make handling cases where both of them might be raised easier.

References: litestar-org/litestar#1557

Update standard and full package extras#
  • Add SQLAlchemy, uvicorn, attrs and structlog to the full extra

  • Add uvicorn to the standard extra

  • Add uvicorn[standard] as an optional dependency to be used in the extras

References: litestar-org/litestar#1494

Remove support for declaring DTOs as handler types#breaking

Prior to this, a DTO type could be declared implicitly using type annotations. With the addition of the dto and return_dto parameters, this feature has become superfluous and, in the spirit of offering only one clear way of doing things, has been removed.

References: litestar-org/litestar#1534

DTO: Simplify DTOConfig#breaking
  • The include parameter has been removed, to provide a more accessible interface and avoid overly complex interplay with exclude and its support for dotted attributes

  • field_mapping has been renamed to rename_fields and support to remap field types has been dropped

  • experimental field_definitions has been removed. It may be replaced with a “ComputedField” in a future release that will allow multiple field definitions to be added to the model, and a callable that transforms them into a value for a model field. See

References: litestar-org/litestar#1580

2.0.0alpha4#

Features#

attrs and msgspec support in Partial#

Partial now supports constructing partial models for attrs and msgspec

References: litestar-org/litestar#1462

Annotated support for route handler and dependency annotations#

Annotated can now be used in route handler and dependencies to specify additional information about the fields.

@get("/")
def index(param: int = Parameter(gt=5)) -> dict[str, int]: ...
@get("/")
def index(param: Annotated[int, Parameter(gt=5)]) -> dict[str, int]: ...

References: litestar-org/litestar#1462

Bugfixes#

Support text/html Media-Type in Redirect response container#

The media type in Redirect won’t be forced to text/plain anymore and now supports setting arbitrary media types.

References: litestar-org/litestar#1451, litestar-org/litestar#1474

Fix global namespace for type resolution#

Fix a bug where certain annotations would cause a NameError

References: litestar-org/litestar#1472, litestar-org/litestar#1477

Add uvicorn to cli extra#

Add the uvicorn package to the cli extra, as it is required unconditionally

References: litestar-org/litestar#1478, litestar-org/litestar#1480

Update logging levels when setting Litestar.debug dynamically#

When passing debug=True to Litestar, the litestar logger would be set up in debug mode, but changing the debug attribute after the class had been instantiated did not update the logger accordingly.

This lead to a regression where the --debug flag to the CLI’s run command would no longer have the desired affect, as loggers would still be on the INFO level.

References: litestar-org/litestar#1476, litestar-org/litestar#1482

2.0.0alpha3#

Features#

SQLAlchemy 2.0 Plugin#

A SQLAlchemyInitPlugin was added, providing support for managed synchronous and asynchronous sessions.

See also

SQLAlchemy

References: litestar-org/litestar#1395

Attrs signature modelling#

Added support to model route handler signatures with attrs instead of Pydantic

References: litestar-org/litestar#1382

Support setting status codes in Redirect container#

Add support for manually setting status codes in the RedirectResponse response container. This was previously only possible by setting the status_code parameter on the corresponding route handler, making dynamic redirect status codes and conditional redirects using this container hard to implement.

References: litestar-org/litestar#1371, litestar-org/litestar#1412

Sentinel value to support caching responses indefinitely#

Add the CACHE_FOREVER sentinel value, that, when passed to a route handlers cache argument, will cause it to be cached forever, skipping the default expiration.

Additionally, add support for setting ResponseCacheConfig.default_expiration to None, allowing to cache values indefinitely by default when setting cache=True on a route handler.

References: litestar-org/litestar#1365, litestar-org/litestar#1414

Accept-header parsing and content negotiation#

Add an accept property to Request, returning the newly added Accept header wrapper, representing the requests Accept HTTP header, offering basic content negotiation.

References: litestar-org/litestar#1317

Enhanced WebSockets support#

Add a new set of features for handling WebSockets, including automatic connection handling, (de)serialization of incoming and outgoing data analogous to route handlers and OOP based event dispatching.

See also

WebSockets

References: litestar-org/litestar#1402

Bugfixes#

SQLAlchemy 1 plugin mutates app state destructively#

When using the SQLAlchemy 1 plugin, repeatedly running through the application lifecycle (as done when testing an application not provided by a factory function), would result in a KeyError on the second pass.

This was caused be the plugin’s on_shutdown handler deleting the engine_app_state_key from the application’s state on application shutdown, but only adding it on application init.

This was fixed by adding performing the necessary setup actions on application startup rather than init.

References: litestar-org/litestar#1368, litestar-org/litestar#1391

Fix SQLAlchemy 1 Plugin - 'Request' object has no attribute 'dict'#

An annotation such as

async def provide_user(request: Request[User, Token, Any]) -> User: ...

would result in the error 'Request' object has no attribute 'dict'.

This was fixed by changing how get_plugin_for_value interacts with typing.get_args()

References: litestar-org/litestar#1388, litestar-org/litestar#1389

Support OpenAPI schema generation with stringized return annotation#

The following code would result in non-specific and incorrect information being generated for the OpenAPI schema:

from __future__ import annotations

from starlite import get


@get("/")
def hello_world() -> dict[str, str]:
    return {"hello": "world"}

This could be alleviated by removing from __future__ import annotations. Stringized annotations in any form are now fully supported.

References: litestar-org/litestar#1409, litestar-org/litestar#1410

Fix OpenAPI schema generation crashes for models with Annotated type attribute#

When using a model that includes a type annotation with typing.Annotated in a route handler, the interactive documentation would raise an error when accessed. This has been fixed and typing.Annotated is now fully supported.

References: litestar-org/litestar#1372, litestar-org/litestar#1400

Support empty data in RequestFactory#

Add support for passing an empty data parameter to a RequestFactory, which would previously lead to an error.

References: litestar-org/litestar#1419, litestar-org/litestar#1420

Other changes#

create_test_client and crate_async_test_client signatures and docstrings to to match Litestar#

Add missing parameters to create_test_client and create_test_client. The following parameters were added:

  • cache_control

  • debug

  • etag

  • opt

  • response_cache_config

  • response_cookies

  • response_headers

  • security

  • stores

  • tags

  • type_encoders

References: litestar-org/litestar#1417

2.0.0alpha2#

Features#

Repository contrib & SQLAlchemy repository#

Add a a repository module to contrib, providing abstract base classes to implement the repository pattern. Also added was the contrib.repository.sqlalchemy module, implementing a SQLAlchemy repository, offering hand-tuned abstractions over commonly used tasks, such as handling of object sessions, inserting, updating and upserting individual models or collections.

References: litestar-org/litestar#1254

Data stores & registry#breaking

The starlite.storage module added in the previous version has been renamed starlite.stores to reduce ambiguity, and a new feature, the starlite.stores.registry.StoreRegistry has been introduced; It serves as a central place to manage stores and reduces the amount of configuration needed for various integrations.

  • Add stores kwarg to Starlite and AppConfig to allow seeding of the StoreRegistry

  • Add Starlite.stores attribute, containing a StoreRegistry

  • Change RateLimitMiddleware to use app.stores

  • Change request caching to use app.stores

  • Change server side sessions to use app.stores

  • Move starlite.config.cache.CacheConfig to starlite.config.response_cache.ResponseCacheConfig

  • Rename Starlite.cache_config > Starlite.response_cache_config

  • Rename AppConfig.cache_config > response_cache_config

  • Remove starlite/cache module

  • Remove ASGIConnection.cache property

  • Remove Starlite.cache attribute

Attention

starlite.middleware.rate_limit.RateLimitMiddleware, starlite.config.response_cache.ResponseCacheConfig, and starlite.middleware.session.server_side.ServerSideSessionConfig instead of accepting a storage argument that could be passed a Storage instance now have to be configured via the store attribute, accepting a string key for the store to be used from the registry. The store attribute has a unique default set, guaranteeing a unique starlite.stores.memory.MemoryStore instance is acquired for every one of them from the registry by default

See also

Stores

References: litestar-org/litestar#1330

Add starlite.__version__#

Add a __version__ constant to the starlite namespace, containing a NamedTuple, holding information about the currently installed version of Starlite

References: litestar-org/litestar#1277

Add starlite version command to CLI#

Add a new version command to the CLI which displays the currently installed version of Starlite

References: litestar-org/litestar#1322

Enhance CLI autodiscovery logic#breaking

Update the CLI Autodiscovery to only consider canonical modules app and application, but every starlite.app.Starlite instance or application factory able to return a Starlite instance within those or one of their submodules, giving priority to the canonical names app and application for application objects and submodules containing them.

References: litestar-org/litestar#1322

Configurable exception logging and traceback truncation#

Add three new configuration options to starlite.logging.config.BaseLoggingConfig:

starlite.logging.config.LoggingConfig.log_exceptions

Configure when exceptions are logged.

always

Always log exceptions

debug

Log exceptions in debug mode only

never

Never log exception

starlite.logging.config.LoggingConfig.traceback_line_limit

Configure how many lines of tracback are logged

starlite.logging.config.LoggingConfig.exception_logging_handler

A callable that receives three parameters - the app.logger, the connection scope and the traceback list, and should handle logging

See also

starlite.logging.config.LoggingConfig

References: litestar-org/litestar#1296

Bugfixes#

Allow overwriting default OpenAPI response descriptions#

Fix litestar-org/litestar#1292 by allowing to overwrite the default OpenAPI response description instead of raising ImproperlyConfiguredException.

References: litestar-org/litestar#1292, litestar-org/litestar#1293

Fix regression in path resolution that prevented 404’s being raised for false paths#breaking

Invalid paths within controllers would under specific circumstances not raise a 404. This was a regression compared to v1.51

Note

This has been marked as breaking since one user has reported to rely on this “feature”

References: litestar-org/litestar#1316

Fix after_request hook not being called on responses returned from handlers#

after_request hooks were not being called automatically when a starlite.response.Response instances was returned from a route handler directly.

See also

After Request

References: litestar-org/litestar#1315, litestar-org/litestar#1344

Fix SQLAlchemyPlugin raises error when using SQLAlchemy UUID#

An error would be raised when using the SQLAlchemy plugin with a sqlalchemy UUID. This was fixed by adding it to the provider map.

References: litestar-org/litestar#1355

Fix JSON.parse error in ReDoc and Swagger OpenAPI handlers#

The HTML generated by the ReDoc and Swagger OpenAPI handlers would cause JSON.parse to throw an error. This was fixed by removing the call to JSON.parse.

References: litestar-org/litestar#1363

Fix CLI prints application info twice#

Fix an error where the CLI would print application info twice on startup

References: litestar-org/litestar#1322

Other changes#

Update SimpleEventEmitter to use worker pattern#

starlite.events.emitter.SimpleEventEmitter was updated to using an async worker, pulling emitted events from a queue and subsequently calling listeners. Previously listeners were called immediately, making the operation effectively “blocking”.

References: litestar-org/litestar#1346

Make BaseEventEmitterBackend.emit synchronous#breaking

starlite.events.emitter.BaseEventEmitterBackend, and subsequently starlite.events.emitter.SimpleEventEmitter and starlite.app.Starlite.emit have been changed to synchronous function, allowing them to easily be used within synchronous route handlers.

References: litestar-org/litestar#1376

Move 3rd party integration plugins to contrib#breaking
  • Move plugins.piccolo_orm > contrib.piccolo_orm

  • Move plugins.tortoise_orm > contrib.tortoise_orm

References: litestar-org/litestar#1279, litestar-org/litestar#1252

Remove picologging dependency from the standard package extra#breaking

picologging has been removed form the standard package extra. If you have been previously relying on this, you need to change pip install starlite[standard] to pip install starlite[standard,picologging]

References: litestar-org/litestar#1313

Replace Starlite() initial_state keyword argument with state#breaking

The initial_state argument to starlite.app.Starlite has been replaced with a state keyword argument, accepting an optional starlite.datastructures.state.State instance.

Existing code using this keyword argument will need to be changed from

from starlite import Starlite

app = Starlite(..., initial_state={"some": "key"})

to

from starlite import Starlite
from starlite.datastructures.state import State

app = Starlite(..., state=State({"some": "key"}))

References: litestar-org/litestar#1350

Remove support for 2 argument form of before_send#breaking

before_send hook handlers initially accepted 2 arguments, but support for a 3 argument form was added later on, accepting an additional scope parameter. Support for the 2 argument form has been dropped with this release.

See also

before_send

References: litestar-org/litestar#1354

Standardize module exports#breaking

A large refactoring standardising the way submodules make their names available.

The following public modules have changed their location:

  • config.openapi > openapi.config

  • config.logging > logging.config

  • config.template > template.config

  • config.static_files > static_files.config

The following modules have been removed from the public namespace:

  • asgi

  • kwargs

  • middleware.utils

  • cli.utils

  • contrib.htmx.utils

  • handlers.utils

  • openapi.constants

  • openapi.enums

  • openapi.datastructures

  • openapi.parameters

  • openapi.path_item

  • openapi.request_body

  • openapi.responses

  • openapi.schema

  • openapi.typescript_converter

  • openapi.utils

  • multipart

  • parsers

  • signature

References: litestar-org/litestar#1273

2.0.0alpha1#

Features#

Validation of controller route handler methods#

Starlite will now validate that no duplicate handlers (that is, they have the same path and same method) exist.

References: litestar-org/litestar#1144

HTMX support#

Basic support for HTMX requests and responses.

References: litestar-org/litestar#1086

Alternate constructor Starlite.from_config#

starlite.app.Starlite.from_config was added to the starlite.app.Starlite class which allows to construct an instance from an starlite.config.app.AppConfig instance.

References: litestar-org/litestar#1190

Web concurrency option for CLI run command#

A --wc / –web-concurrency` option was added to the starlite run command, enabling users to specify the amount of worker processes to use. A corresponding environment variable WEB_CONCURRENCY was added as well

References: litestar-org/litestar#1218

Validation of state parameter in handler functions#

Type annotations of the reserved state parameter in handler functions will now be validated such that annotations using an unsupported type will raise a starlite.exceptions.ImproperlyConfiguredException.

References: litestar-org/litestar#1264

Generic application state#

starlite.connection.base.ASGIConnection and its subclasses are now generic on State which allow to to fully type hint a request as Request[UserType, AuthType, StateType].

References: litestar-org/litestar#1030

Dependency injection of classes#

Support using classes (not class instances, which were already supported) as dependency providers. With this, now every callable is supported as a dependency provider.

References: litestar-org/litestar#1143

Event bus#

A simple event bus system for Starlite, supporting synchronous and asynchronous listeners and emitters, providing a similar interface to handlers. It currently features a simple in-memory, process-local backend

References: litestar-org/litestar#1105

Unified storage interfaces#breaking

Storage backends for server-side sessions starlite.cache.Cache` have been unified and replaced by the starlite.storages, which implements generic asynchronous key/values stores backed by memory, the file system or redis.

Important

This is a breaking change and you need to change your session / cache configuration accordingly

References: litestar-org/litestar#1184

Bugfixes#

Fix resolving of relative paths in StaticFilesConfig#

Using a relative pathlib.Path did not resolve correctly and result in a NotFoundException

References: litestar-org/litestar#1256

Fix --reload flag to starlite run not working correctly#

Passing the --reload flag to the starlite run command did not work correctly in all circumstances due to an issue with uvicorn. This was resolved by invoking uvicorn in a subprocess.

References: litestar-org/litestar#1191

Fix optional types generate incorrect OpenAPI schemas#

An optional query parameter was incorrectly represented as

{ "oneOf": [
  { "type": null" },
  { "oneOf": [] }
 ]}

References: litestar-org/litestar#1210

Fix LoggingMiddleware is sending obfuscated session id to client#

LoggingMiddleware would in some cases send obfuscated data to the client, due to a bug in the obfuscation function which obfuscated values in the input dictionary in-place.

References: litestar-org/litestar#1228

Fix missing domain configuration value for JWT cookie auth#

starlite.contrib.jwt.jwt_auth.JWTCookieAuth didn’t set the domain configuration value on the response cookie.

References: litestar-org/litestar#1223

Fix litestar-org/litestar#1201: Can not serve static file in / path#

A validation error made it impossible to serve static files from the root path / .

References: litestar-org/litestar#1201

Fix litestar-org/litestar#1149: Middleware not excluding static path#

A middleware’s exclude parameter would sometimes not be honoured if the path was used to serve static files using StaticFilesConfig

References: litestar-org/litestar#1149

Other changes#

Relaxed type annotations#

Type annotations across the library have been relaxed to more generic forms, for example Iterable[str] instead of List[str] or Mapping[str, str] instead of Dict[str, str].

References: litestar-org/litestar#1140

type_encoders support in AbstractSecurityConfig#

type_encoders support has been added to starlite.security.base.AbstractSecurityConfig, enabling support for customized type_encoders for example in starlite.contrib.jwt.jwt_auth.JWTAuth.

References: litestar-org/litestar#1167

Renamed handler module names#breaking

The modules containing route handlers have been renamed to prevent ambiguity between module and handler names.

  • starlite.handlers.asgi > starlite.handlers.asgi_handlers

  • starlite.handlers.http > starlite.handlers.http_handlers

  • starlite.handlers.websocket > starlite.handlers.websocket_handlers

References: litestar-org/litestar#1170

New plugin protocols#breaking

The plugin protocol has been split into three distinct protocols, covering different use cases:

starlite.plugins.InitPluginProtocol

Hook into an application’s initialization process

starlite.plugins.SerializationPluginProtocol

Extend the serialization and deserialization capabilities of an application

starlite.plugins.OpenAPISchemaPluginProtocol

Extend OpenAPI schema generation

References: litestar-org/litestar#1176

Unify response headers and cookies#breaking

response headers and response cookies now have the same interface, along with the headers and cookies keyword arguments to starlite.response.Response. They each allow to pass either a :class:`Mapping[str, str] <typing.Mapping>, e.g. a dictionary, or a Sequence of starlite.datastructures.response_header.ResponseHeader or starlite.datastructures.cookie.Cookie respectively.

References: litestar-org/litestar#1209

Replace Pydantic models with dataclasses#breaking

Several Pydantic models used for configuration have been replaced with dataclasses or plain classes. This change should be mostly non-breaking, unless you relied on those configuration objects being Pydantic models. The changed models are:

  • starlite.config.allowed_hosts.AllowedHostsConfig

  • starlite.config.app.AppConfig

  • starlite.config.response_cache.ResponseCacheConfig

  • starlite.config.compression.CompressionConfig

  • starlite.config.cors.CORSConfig

  • starlite.config.csrf.CSRFConfig

  • starlite.logging.config.LoggingConfig

  • starlite.openapi.OpenAPIConfig

  • starlite.static_files.StaticFilesConfig

  • starlite.template.TemplateConfig

  • starlite.contrib.jwt.jwt_token.Token

  • starlite.contrib.jwt.jwt_auth.JWTAuth

  • starlite.contrib.jwt.jwt_auth.JWTCookieAuth

  • starlite.contrib.jwt.jwt_auth.OAuth2Login

  • starlite.contrib.jwt.jwt_auth.OAuth2PasswordBearerAuth

  • starlite.contrib.opentelemetry.OpenTelemetryConfig

  • starlite.middleware.logging.LoggingMiddlewareConfig

  • starlite.middleware.rate_limit.RateLimitConfig

  • starlite.middleware.session.base.BaseBackendConfig

  • starlite.middleware.session.client_side.CookieBackendConfig

  • starlite.middleware.session.server_side.ServerSideSessionConfig

  • starlite.response_containers.ResponseContainer

  • starlite.response_containers.File

  • starlite.response_containers.Redirect

  • starlite.response_containers.Stream

  • starlite.security.base.AbstractSecurityConfig

  • starlite.security.session_auth.SessionAuth

References: litestar-org/litestar#1242

SQLAlchemy plugin moved to contrib#breaking

The SQLAlchemyPlugin` has moved to ``starlite.contrib.sqlalchemy_1.plugin and will only be compatible with the SQLAlchemy 1.4 release line. The newer SQLAlchemy 2.x releases will be supported by the contrib.sqlalchemy module.

References: litestar-org/litestar#1252

Cleanup of the starlite namespace#breaking

The starlite namespace has been cleared up, removing many names from it, which now have to be imported from their respective submodules individually. This was both done to improve developer experience as well as reduce the time it takes to import starlite.

References: litestar-org/litestar#1135