.. changelog:: 2.7.1
:date: 2024-03-22
.. change:: add default encoders for `Enums` and `EnumMeta`
:type: bugfix
:pr: 3193
This addresses an issue when serializing ``Enums`` that was reported in discord.
.. change:: replace TestClient.__enter__ return type with Self
:type: bugfix
:pr: 3194
``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.
.. change:: use the full path for fetching openapi.json
:type: bugfix
:pr: 3196
:issue: 3047
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.
.. change:: JSON schema ``examples`` were OpenAPI formatted
:type: bugfix
:pr: 3224
:issue: 2849
The generated ``examples`` in *JSON schema* objects were formatted as:
.. code-block:: json
"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:
.. code-block:: json
"examples": [
"the real beef"
]
* Explained in `APIs You Won't Hate blog post <https://medium.com/apis-you-wont-hate/openapi-v3-1-and-json-schema-2019-09-6862cf3db959>`_.
* `Schema objects spec <https://spec.openapis.org/oas/v3.1.0#schema-object>`_
* `OpenAPI example format spec <https://spec.openapis.org/oas/v3.1.0#example-object>`_.
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).
.. change:: queue_listener handler for Python >= 3.12
:type: bugfix
:pr: 3185
:issue: 2954
- 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 <https://docs.python.org/3/library/logging.config.html#configuring-queuehandler-and-queuelistener>`_.
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 <https://docs.python.org/3/library/logging.handlers.html#logging.handlers.QueueHandler>`_ and
`QueueListener <https://docs.python.org/3/library/logging.handlers.html#logging.handlers.QueueListener>`_.
.. change:: extend openapi meta collected from domain models
:type: bugfix
:pr: 3237
:issue: 3232
:class:`~litestar.typing.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`.
.. change:: kwarg ambiguity exc msg for path params
:type: bugfix
:pr: 3261
Fixes the way we construct the exception message when there is a kwarg ambiguity detected for path parameters.
.. changelog:: 2.7.0
:date: 2024-03-10
.. change:: missing cors headers in response
:type: bugfix
:pr: 3179
:issue: 3178
Set CORS Middleware headers as per spec.
Addresses issues outlined on https://github.com/litestar-org/litestar/issues/3178
.. change:: sending empty data in sse in js client
:type: bugfix
:pr: 3176
Fix an issue with SSE where JavaScript clients fail to receive an event without data.
The `spec <https://html.spec.whatwg.org/multipage/server-sent-events.html#parsing-an-event-stream>`_ 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
.. change:: Support ``ResponseSpec(..., examples=[...])``
:type: feature
:pr: 3100
:issue: 3068
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.
.. code-block:: json
{
"paths": {
"/": {
"get": {
"responses": {
"200": {
"content": {
"application/json": {
"schema": {},
"examples": "..."}}
}}
}}
}
}
.. change:: support "+json"-suffixed response media types
:type: feature
:pr: 3096
:issue: 3088
Automatically encode responses with media type of the form ``application/<something>+json`` as json.
.. change:: Allow reusable ``Router`` instances
:type: feature
:pr: 3103
:issue: 3012
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.
.. change:: only display path in ``ValidationException``\ s
:type: feature
:pr: 3064
:issue: 3061
Fix an issue where ``ValidationException`` exposes the full URL in the error response, leaking internal IP(s) or other similar infra related information.
.. change:: expose ``request_class`` to other layers
:type: feature
:pr: 3125
Expose ``request_class`` to other layers
.. change:: expose ``websocket_class``
:type: feature
:pr: 3152
Expose ``websocket_class`` to other layers
.. change:: Add ``type_decoders`` to Router and route handlers
:type: feature
:pr: 3153
Add ``type_decoders`` to ``__init__`` method for handler, routers and decorators to keep consistency with ``type_encoders`` parameter
.. change:: Pass ``type_decoders`` in ``WebsocketListenerRouteHandler``
:type: feature
:pr: 3162
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`)
.. change:: 3116 enhancement session middleware
:type: feature
:pr: 3127
:issue: 3116
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
.. change:: make random seed for openapi example generation configurable
:type: feature
:pr: 3166
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 https://github.com/litestar-org/litestar/issues/3059 however whether this change is enough to close that issue or not is not confirmed.
.. change:: generate openapi components schemas in a deterministic order
:type: feature
:pr: 3172
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``).
.. changelog:: 2.6.3
:date: 2024-03-04
.. change:: Pydantic V1 schema generation for PrivateAttr in GenericModel
:type: bugfix
:pr: 3161
:issue: 3150
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.
.. changelog:: 2.6.2
:date: 2024/03/02
.. change:: DTO msgspec meta constraints not being included in transfer model
:type: bugfix
:pr: 3113
:issue: 3026
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``.
.. code-block:: python
from typing import Annotated
import msgspec
from litestar import post, Litestar
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.
.. change:: Missing control header for static files
:type: bugfix
:pr: 3131
:issue: 3129
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
.. change:: Fix OpenAPI schema generation for Pydantic v2 constrained ``Secret`` types
:type: bugfix
:pr: 3149
:issue: 3148
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.
.. change:: Fix OpenAPI schema generation for Pydantic private attributes
:type: bugfix
:pr: 3151
:issue: 3150
Fix a bug that caused a :exc:`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.
.. change:: OpenAPI description not set for UUID based path parameters in OpenAPI
:type: bugfix
:pr: 3118
:issue: 2967
Resolved a bug where the description was not set for UUID-based path
parameters in OpenAPI due to the reason mentioned in the issue.
.. change:: Fix ``RedisStore`` client created with ``with_client`` unclosed
:type: bugfix
:pr: 3111
:issue: 3083
Fix a bug where, when a :class:`~litestar.stores.redis.RedisStore` was created
with the :meth:`~litestar.stores.redis.RedisStore.with_client` method, that
client wasn't closed explicitly
.. changelog:: 2.6.1
:date: 2024/02/14
.. change:: SQLAlchemy: Use `IntegrityError` instead of deprecated `ConflictError`
:type: bugfix
:pr: 3094
Updated the repository to return ``IntegrityError`` instead of the now
deprecated ``ConflictError``
.. change:: Remove usage of deprecated `static_files` property
:type: bugfix
:pr: 3087
Remove the usage of the deprecated ``Litestar.static_files_config`` in
``Litestar.__init__``.
.. change:: Sessions: Fix cookie naming for short cookies
:type: bugfix
:pr: 3095
:issue: 3090
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.
.. change:: Static files: Fix path resolution for windows
:type: bugfix
:pr: 3102
Fix an issue with the path resolution on Windows introduced in
https://github.com/litestar-org/litestar/pull/2960 that would lead to 404s
.. change:: Fix logging middleware with structlog causes application to return a ``500`` when request body is malformed
:type: bugfix
:pr: 3109
:issue: 3063
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
.. change:: OpenAPI: Generate correct response schema for ``ResponseSpec(None)``
:type: bugfix
:pr: 3098
:issue: 3069
Explicitly declaring ``responses={...: ResponseSpec(None)}`` used to generate
OpenAPI a ``content`` property, when it should be omitted.
.. change:: Prevent exception handlers from extracting details from non-Litestar exceptions
:type: bugfix
:pr: 3106
:issue: 3082
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.
.. changelog:: 2.6.0
:date: 2024/02/06
.. change:: Enable disabling configuring ``root`` logger within ``LoggingConfig``
:type: feature
:pr: 2969
The option ``litestar.logging.config.LoggingConfig.configure_root_logger`` was
added to ``litestar.logging.config.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.
.. change:: Simplified static file handling and enhancements
:type: feature
:pr: 2960
:issue: 2629
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
`litestar.static_files.StaticFilesConfig`` to maintain backwards
compatibility.
This achieves a few things:
- Fixes https://github.com/litestar-org/litestar/issues/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 ``litestar.app.Litestar.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
:func:`~litestar.static_files.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
.. code-block:: python
app = Litestar(
static_files_config=[
StaticFilesConfig(path="/static", directories=["some_dir"])
]
)
You can now simply use
.. code-block:: python
app = Litestar(
route_handlers=[
create_static_files_router(path="/static", directories=["some_dir"])
]
)
.. seealso::
:doc:`/usage/static-files`
.. change:: Exclude Piccolo ORM columns with ``secret=True`` from ``PydanticDTO`` output
:type: feature
:pr: 3030
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``
.. change:: Allow discovering registered plugins by their fully qualified name
:type: feature
:pr: 3027
`PluginRegistryPluginRegistry`` now supports retrieving a plugin by its fully
qualified name.
.. change:: Support externally typed classes as dependency providers
:type: feature
:pr: 3066
:issue: 2979
- Implement a new :class:`~litestar.plugins.DIPlugin` class that allows the
generation of signatures for arbitrary types where their signature cannot be
extracted from the type's ``__init__`` method
- Implement ``DIPlugin``\ s for Pydantic and Msgspec to allow using their
respective modelled types as dependency providers. These plugins will be
registered by default
.. change:: Add structlog plugin
:type: feature
:pr: 2943
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
.. change:: Add reload-include and reload-exclude to CLI run command
:type: feature
:pr: 2973
:issue: 2875
The options ``reload-exclude`` and ``reload-include`` were added to the CLI
``run`` command to explicitly in-/exclude specific paths from the reloading
watcher.
.. changelog:: 2.5.5
:date: 2024/02/04
.. change:: Fix scope ``state`` key handling
:type: bugfix
:pr: 3070
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.
.. changelog:: 2.5.4
:date: 2024/01/31
.. change:: Handle ``KeyError`` when `root_path` is not present in ASGI scope
:type: bugfix
:pr: 3051
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.
.. code-block::
KeyError on GET /
'root_path'
.. change:: ServerSentEvent typing error
:type: bugfix
:pr: 3048
fixes small typing error:
.. code-block::
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.
.. changelog:: 2.5.3
:date: 2024/01/29
.. change:: Handle diverging ASGI ``root_path`` behaviour
:type: bugfix
:pr: 3039
:issue: 3041
Uvicorn `0.26.0 <https://github.com/encode/uvicorn/releases/tag/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.
.. changelog:: 2.5.2
:date: 2024/01/27
.. change:: Ensure ``MultiDict`` and ``ImmutableMultiDict`` copy methods return the instance's type
:type: bugfix
:pr: 3009
:issue: 2549
Ensure :class:`~litestar.datastructures.MultiDict` and
:class:`~litestar.datastructures.ImmutableMultiDict` copy methods return a new
instance of ``MultiDict`` and ``ImmutableMultiDict``. Previously, these would
return a :class:`multidict.MultiDict` instance.
.. change:: Ensure ``exceptiongroup`` is installed on Python 3.11
:type: bugfix
:pr: 3035
:issue: 3029
Add the `exceptiongroup <https://github.com/agronholm/exceptiongroup>`_ package
as a required dependency on Python ``<3.11`` (previously ``<3.10``) as a
backport of `Exception Groups <https://docs.python.org/3/library/exceptions.html#exception-groups>`_
.. changelog:: 2.5.1
:date: 2024/01/18
.. change:: Fix OpenAPI schema generation for Union of multiple ``msgspec.Struct``\ s and ``None``
:type: bugfix
:pr: 2982
:issue: 2971
The following code would raise a :exc:`TypeError`
.. code-block:: python
import msgspec
from litestar import get
from litestar.testing import create_test_client
class StructA(msgspec.Struct):
pass
class StructB(msgspec.Struct):
pass
@get("/")
async def handler() -> StructA | StructB | None:
return StructA()
.. change:: Fix misleading error message for missing dependencies provide by a package extra
:type: bugfix
:pr: 2921
Ensure that :exc:`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.
.. change:: Fix OpenAPI schema file upload schema types for swagger
:type: bugfix
:pr: 2745
:issue: 2628
- 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``.
.. changelog:: 2.5.0
:date: 2024/01/06
.. change:: Fix serialization of custom types in exception responses
:type: bugfix
:issue: 2867
:pr: 2941
Fix a bug that would lead to a :exc:`SerializationException` when custom types
were present in an exception response handled by the built-in exception
handlers.
.. code-block:: python
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.
.. change:: Fix SSE reverting to default ``event_type`` after 1st message
:type: bugfix
:pr: 2888
:issue: 2877
The ``event_type`` set within an SSE returned from a handler would revert back
to a default after the first message sent:
.. code-block:: python
@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.
.. change:: Correctly handle single file upload validation when multiple files are specified
:type: bugfix
:pr: 2950
:issue: 2939
Uploading a single file when the validation target allowed multiple would cause
a :exc:`ValidationException`:
.. code-block:: python
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.
.. change:: Fix trailing messages after unsubscribe in channels
:type: bugfix
:pr: 2894
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.
.. code-block:: python
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.
.. change:: Postgres channels backends
:type: feature
:pr: 2803
Two new channel backends were added to bring Postgres support:
:class:`~litestar.channels.backends.asyncpg.AsyncPgChannelsBackend`, using the
`asyncpg <https://magicstack.github.io/asyncpg/current/>`_ driver and
:class:`~litestar.channels.backends.psycopg.PsycoPgChannelsBackend` using the
`psycopg3 <https://www.psycopg.org/psycopg3/docs/>`_ async driver.
.. seealso::
:doc:`/usage/channels`
.. change:: Add ``--schema`` and ``--exclude`` option to ``litestar route`` CLI command
:type: feature
:pr: 2886
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
.. change:: Improve performance of threaded synchronous execution
:type: misc
:pr: 2937
Performance of threaded synchronous code was improved by using the async
library's native threading helpers instead of anyio. On asyncio,
:meth:`asyncio.loop.run_in_executor` is now used and on trio
:func:`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
- :class:`~litestar.stores.file.FileStore`
- Large file uploads where the ``max_spool_size`` is exceeded and the spooled
temporary file has been rolled to disk
- :class:`~litestar.response.file.File` and
:class:`~litestar.response.file.ASGIFileResponse`
.. changelog:: 2.4.5
:date: 2023/12/23
.. change:: Fix validation of empty payload data with default values
:type: bugfix
:issue: 2902
:pr: 2903
Prior to this fix, a handler like:
.. code-block:: python
@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:
.. code-block:: bash
{"status_code":400,"detail":"Validation failed for POST http://localhost:8000/","extra":[{"message":"Expected `str`, got `null`","key":"data","source":"body"}]}
.. change:: Support for returning ``Response[None]`` with a ``204`` status code from a handler
:type: bugfix
:pr: 2915
:issue: 2914
Returning a ``Response[None]`` from a route handler for a response with a
``204`` now works as expected without resulting in an
:exc:`ImproperlyConfiguredException`
.. change:: Fix error message of ``get_logger_placeholder()``
:type: bugfix
:pr: 2919
Using a method on
``Request.logger`` when not
setting a ``logging_config`` on the application would result in a non-descriptive
:exc:`TypeError`. An :exc:`ImproperlyConfiguredException` with an explanation is
now raised instead.
.. changelog:: 2.4.4
:date: 2023/12/13
.. change:: Support non-valid identifier as serialization target name
:type: bugfix
:pr: 2850
:issue: 2845
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.
.. change:: Fix regression signature validation for DTO validated types
:type: bugfix
:pr: 2854
:issue: 2149
Fix a regression introduced in ``2.0.0rc1`` that would cause data validated by
the DTO to be validated again by the signature model.
.. change:: Fix regression in OpenAPI schema key names
:type: bugfix
:pr: 2841
:issue: 2804
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.
.. change:: Fix regression in OpenAPI handling of routes with multiple handlers
:type: bugfix
:pr: 2864
:issue: 2863
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.
.. change:: Fix OpenAPI schema generation for recursive models
:type: bugfix
:pr: 2869
:issue: 2429
Fix an issue that would lead to a :exc:`RecursionError` when including nested
models in the OpenAPI schema.
.. changelog:: 2.4.3
:date: 2023/12/07
.. change:: Fix OpenAPI schema for ``Literal | None`` unions
:type: bugfix
:issue: 2812
:pr: 2818
Fix a bug where an incorrect OpenAPI schema was generated generated when any
``Literal | None``-union was present in an annotation.
For example
.. code-block:: python
type: Literal["sink", "source"] | None
would generate
.. code-block:: json
{
"name": "type",
"in": "query",
"schema": {
"type": "string",
"enum": [ "sink", "source", null ]
}
}
.. change:: Fix advanced-alchemy 0.6.0 compatibility issue with ``touch_updated_timestamp``
:type: bugfix
:pr: 2843
Fix an incorrect import for ``touch_updated_timestamp`` of Advanced Alchemy,
introduced in Advanced-Alchemy version 0.6.0.
.. changelog:: 2.4.2
:date: 2023/12/02
.. change:: Fix OpenAPI handling of parameters with duplicated names
:type: bugfix
:issue: 2662
:pr: 2788
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.
.. change:: Fix late failure where ``DTOData`` is used without a DTO
:type: bugfix
:issue: 2779
:pr: 2789
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.
.. change:: Correctly propagate camelCase names on OpenAPI schema
:type: bugfix
:pr: 2800
Fix a bug where OpenAPI schema fields would be inappropriately propagated as
camelCase where they should have been snake_case
.. change:: Fix error handling in event handler stream
:type: bugfix
:pr: 2810, 2814
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.
.. change:: Fix OpenAPI schema for pydantic computed fields
:type: bugfix
:pr: 2797
:issue: 2792
Add support for including computed fields in schemas generated from pydantic
models.
.. changelog:: 2.4.1
:date: 2023/11/28
.. change:: Fix circular import when importing from ``litestar.security.jwt``
:type: bugfix
:pr: 2784
:issue: 2782
An :exc:`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``.
.. change:: Raise config error when generator dependencies are cached
:type: bugfix
:pr: 2780
:issue: 2771
Previously, an :exc:`InternalServerError` was raised when attempting to use
`use_cache=True` with generator dependencies. This will now raise a configuration
error during application startup.
.. changelog:: 2.4.0
:date: 2023/11/27
.. change:: Fix ``HTTPException`` handling during concurrent dependency resolving
:type: bugfix
:pr: 2596
:issue: 2594
An issue was fixed that would lead to :exc:`HTTPExceptions` not being re-raised
properly when they occurred within the resolution of nested dependencies during
the request lifecycle.
.. change:: Fix OpenAPI examples format
:type: bugfix
:pr: 2660
:issue: 2272
Fix the OpenAPI examples format by removing the wrapping object.
Before the change, for a given model
.. code-block:: python
@dataclass
class Foo:
foo: int
The following example would be generated:
.. code-block:: json
{
"description": "Example value",
"value": {
"foo": 7906
}
}
After the fix, this is now:
.. code-block:: json
{
"foo": 7906
}
.. change:: Fix CLI plugin commands not showing up in command list
:type: bugfix
:pr: 2441
Fix a bug where commands registered by CLI plugins were available, but would not
show up in the commands list
.. change:: Fix missing ``write-only`` mark in ``dto_field()`` signature
:type: bugfix
:pr: 2684
Fix the missing ``write-only`` string literal in the ``mark`` parameter of
:func:`~litestar.dto.field.dto_field`
.. change:: Fix OpenAPI schemas incorrectly flagged as duplicates
:type: bugfix
:pr: 2475
:issue: 2471
Fix an issue that would lead to OpenAPI schemas being incorrectly considered
duplicates, resulting in an :exc:`ImproperlyConfiguredException` being raised.
.. change:: Fix Pydantic URL type support in OpenAPI and serialization
:type: bugfix
:pr: 2701
:issue: 2664
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.
.. change:: Fix incorrect ``ValidationException`` message when multiple errors were encountered
:type: bugfix
:pr: 2716
:issue: 2714
Fix a bug where :exc:`ValidationException` could contain duplicated messages in
``extra`` field, when multiple errors were encountered during validation
.. change:: Fix DTO renaming renames all fields of the same name in nested DTOs
:type: bugfix
:pr: 2764
:issue: 2721
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``
.. code-block:: python
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"})]]
.. change:: Fix handling of DTO objects nested in mappings
:type: bugfix
:pr: 2775
:issue: 2737
Fix a bug where DTOs nested in a :class:`~typing.Mapping` type would fail to
serialize correctly.
.. change:: Fix inconsistent sequence union parameter errors
:type: bugfix
:pr: 2776
:issue: 2600
Fix a bug where unions of collection types would result in different errors
depending on whether the union included :obj:`None` or not.
.. change:: Fix graceful handling of WebSocket disconnect in channels WebSockets handlers
:type: bugfix
:pr: 2691
Fix the behaviour of WebSocket disconnect handling within the WebSocket handlers
provided by :doc:`channels </usage/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.
.. change:: Add ``server_lifespan`` hook
:type: feature
:pr: 2658
A new ``server_lifespan`` hook is now available on :class:`~litestar.app.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.
.. change:: Allow rendering templates directly from strings
:type: feature
:pr: 2689
:issue: 2687
A new ``template_string`` parameter was added to :class:`~litestar.template.Template`,
allowing to render templates directly from strings.
.. seealso::
:ref:`usage/templating:Template Files vs. Strings`
.. change:: Support nested DTO field renaming
:type: feature
:pr: 2764
:issue: 2721
Using similar semantics as for exclusion/inclusion, nested DTO fields can now
also be renamed:
.. code-block:: python
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"})]
]
.. changelog:: 2.3.2
:date: 2023/11/06
.. change:: Fix recursion error when re-using the path of a route handler for static files
:type: bugfix
:pr: 2630
:issue: 2629
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.
.. code-block:: python
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"),
],
)
.. changelog:: 2.3.1
:date: 2023/11/04
.. change:: CLI: Fix not providing SSL certfiles breaks uvicorn command when using reload or multiple workers
:type: bugfix
:pr: 2616
:issue: 2613
Fix an issue where not providing the ``--ssl-certfile`` and ``--ssl-keyfile``
options to the ``litestar run`` command would cause a :exc:`FileNotFoundError`
in uvicorn, when used together with the ``--reload``, ``--web-concurrency``
options.
.. changelog:: 2.3.0
:date: 2023/11/02
.. change:: Python 3.12 support
:type: feature
:pr: 2396
:issue: 1862
Python 3.12 is now fully supported and tested.
.. change:: New layered parameter ``signature_types``
:type: feature
:pr: 2422
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.
.. change:: Added RapiDoc for OpenAPI schema visualisation
:type: feature
:pr: 2522
Add support for using `RapiDoc <https://github.com/rapi-doc/RapiDoc>`_ for
OpenAPI schema visualisation.
.. change:: Support Pydantic 1 & 2 within the same application
:type: feature
:pr: 2487
Added support for Pydantic 1 & 2 within the same application by integrating with
Pydantic's backwards compatibility layer:
.. code-block:: python
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
.. change:: Add ``ResponseCacheConfig.cache_response_filter`` to allow filtering responses eligible for caching
:type: feature
:pr: 2537
:issue: 2501
``ResponseCacheConfig.cache_response_filter`` is predicate called by the
response cache middleware that discriminates whether a response should be
cached, or not.
.. change:: SSL support and self-signed certificates for CLI
:type: feature
:pr: 2554
:issue: 2335
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 <https://www.uvicorn.org/#command-line-options>`_
**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
.. change:: Use custom request class when given during exception handling
:type: bugfix
:pr: 2444
:issue: 2399
When a custom ``request_class`` is provided, it will now be used while returning
an error response
.. change:: Fix missing OpenAPI schema for generic response type annotations
:type: bugfix
:pr: 2463
:issue: 2383
OpenAPI schemas are now correctly generated when a response type annotation
contains a generic type such as
.. code-block:: python
from msgspec import Struct
from litestar import Litestar, 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"),
)
.. change:: Fix rendering of OpenAPI examples
:type: bugfix
:pr: 2509
:issue: 2494
An issue was fixed where OpenAPI examples would be rendered as
.. code-block:: json
{
"parameters": [
{
"schema": {
"type": "string",
"examples": [
{
"summary": "example summary",
"value": "example value"
}
]
}
}
]
}
instead of
.. code-block:: json
{
"parameters": [
{
"schema": {
"type": "string"
},
"examples": {
"example1": {
"summary": "example summary"
"value": "example value"
}
}
}
]
}
.. change:: Fix non UTF-8 handling when logging requests
:type: bugfix
:issue: 2529
:pr: 2530
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.
.. change:: Fix ``ExceptionHandler`` typing to properly support ``Exception`` subclasses
:type: bugfix
:issue: 2520
:pr: 2533
Fix the typing for ``ExceptionHandler`` to support subclasses of ``Exception``,
such that code like this will type check properly:
.. code-block:: python
from litestar import Litestar, Request, Response
class CustomException(Exception): ...
def handle_exc(req: Request, exc: CustomException) -> Response: ...
.. change:: Fix OpenAPI schema generation for variable length tuples
:type: bugfix
:issue: 2460
:pr: 2552
Fix a bug where an annotation such as ``tuple[str, ...]`` would cause a
``TypeError: '<' not supported between instances of 'NoneType' and 'OpenAPIType')``.
.. change:: Fix channels performance issue when polling with no subscribers in ``arbitrary_channels_allowed`` mode
:type: bugfix
:pr: 2547
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.
.. change:: Fix CLI schema export for non-serializable types when using ``create_examples=True``
:type: bugfix
:pr: 2581
:issue: 2575
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.
.. change:: Fix OpenAPI schema generation for ``Literal`` and ``Enum`` unions with ``None``
:type: bugfix
:pr: 2550
:issue: 2546
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.
.. change:: Fix cache overrides when using same route with different handlers
:type: bugfix
:pr: 2592
:issue: 2573, 2588
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.
.. changelog:: 2.2.0
:date: 2023/10/12
.. change:: Fix implicit conversion of objects to ``bool`` in debug response
:type: bugfix
:pr: 2384
:issue: 2381
The exception handler middleware would, when in debug mode, implicitly call an
object's :meth:`__bool__ <object.__bool__>`, which would lead to errors if that
object overloaded the operator, for example if the object in question was a
SQLAlchemy element.
.. change:: Correctly re-export filters and exceptions from ``advanced-alchemy``
:type: bugfix
:pr: 2360
:issue: 2358
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.
.. change:: Re-add ``create_engine`` method to SQLAlchemy configs
:type: bugfix
:pr: 2382
The ``create_engine`` method was removed in an ``advanced-alchemy`` releases.
This was addresses by re-adding it to the versions provided by Litestar.
.. change:: Fix ``before_request`` modifies route handler signature
:type: bugfix
:pr: 2391
:issue: 2368
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.
.. change:: Ensure compression is applied before caching when using compression middleware
:type: bugfix
:pr: 2393
:issue: 1301
A previous limitation was removed that would apply compression from the
:class:`~litestar.middleware.compression.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.
.. change:: Fix implicit JSON parsing of URL encoded data
:type: bugfix
:pr: 2394
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.
.. change:: CLI enabled by default
:type: feature
:pr: 2346
:issue: 2318
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.
.. change:: Customization of Pydantic integration via ``PydanticPlugin``
:type: feature
:pr: 2404
:issue: 2373
A new :class:`~litestar.contrib.pydantic.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.
.. change:: Add ``/schema/openapi.yml`` to the available schema paths
:type: feature
:pr: 2411
The YAML version of the OpenAPI schema is now available under
``/schema/openapi.yml`` in addition to ``/schema/openapi.yaml``.
.. change:: Add experimental DTO codegen backend
:type: feature
:pr: 2388
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:
.. code-block:: python
from litestar import Litestar
from litestar.config.app import ExperimentalFeatures
app = Litestar(experimental_features=[ExperimentalFeatures.DTO_CODEGEN])
.. seealso::
For more information see
:ref:`usage/dto/0-basic-use:Improving performance with the codegen backend`
.. change:: Improved error messages for missing required parameters
:type: feature
:pr: 2418
Error messages for missing required parameters will now also contain the source
of the expected parameter:
Before:
.. code-block:: json
{
"status_code": 400,
"detail": "Missing required parameter foo for url http://testerver.local"
}
After:
.. code-block:: json
{
"status_code": 400,
"detail": "Missing required header parameter 'foo' for url http://testerver.local"
}
.. changelog:: 2.1.1
:date: 2023/09/24
.. change:: Fix ``DeprecationWarning`` raised by ``Response.to_asgi_response``
:type: bugfix
:pr: 2364
:meth:`~litestar.response.Response.to_asgi_response` was passing a
non-:obj:`None` default value (``[]``) to ``ASGIResponse`` for
``encoded_headers``, resulting in a :exc:`DeprecationWarning` being raised.
This was fixed by leaving the default value as :obj:`None`.
.. changelog:: 2.1.0
:date: 2023/09/23
`View the full changelog <https://github.com/litestar-org/litestar/compare/v2.0.0...v2.1.0x>`_
.. change:: Make ``302`` the default ``status_code`` for redirect responses
:type: feature
:pr: 2189
:issue: 2138
Make ``302`` the default ``status_code`` for redirect responses
.. change:: Add :meth:`include_in_schema` option for all layers
:type: feature
:pr: 2295
:issue: 2267
Adds the :meth:`include_in_schema` option to all layers, allowing to include/exclude
specific routes from the generated OpenAPI schema.
.. change:: Deprecate parameter ``app`` of ``Response.to_asgi_response``
:type: feature
:pr: 2268
:issue: 2217
Adds deprecation warning for unused ``app`` parameter of ``to_asgi_response`` as
it is unused and redundant due to ``request.app`` being available.
.. change:: Authentication: Add parameters to set the JWT ``extras`` field
:type: feature
:pr: 2313
Adds ``token_extras`` to both :func:`BaseJWTAuth.login` and :meth:`BaseJWTAuth.create_token` methods,
to allow the definition of the ``extras`` JWT field.
.. change:: Templating: Add possibility to customize Jinja environment
:type: feature
:pr: 2195
:issue: 965
Adds the ability to pass a custom Jinja2 ``Environment`` or Mako ``TemplateLookup`` by providing a
dedicated class method.
.. change:: Add support for `minjinja <https://github.com/mitsuhiko/minijinja>`_
:type: feature
:pr: 2250
Adds support for MiniJinja, a minimal Jinja2 implementation.
.. seealso:: :doc:`/usage/templating`
.. change:: SQLAlchemy: Exclude implicit fields for SQLAlchemy DTO
:type: feature
:pr: 2170
:class:`SQLAlchemyDTO (Advanced Alchemy) <advanced_alchemy.extensions.litestar.dto.SQLAlchemyDTO>` can now be
configured using a separate config object. This can be set using both
class inheritance and `Annotated <https://docs.python.org/3/library/typing.html#typing.Annotated>`_:
.. code-block:: python
:caption: :class:`SQLAlchemyDTO (Advanced Alchemy) <advanced_alchemy.extensions.litestar.dto.SQLAlchemyDTO>` can now be configured using a separate config object using ``config`` object.
class MyModelDTO(SQLAlchemyDTO[MyModel]):
config = SQLAlchemyDTOConfig()
or
.. code-block:: python
:caption: :class:`SQLAlchemyDTO (Advanced Alchemy) <advanced_alchemy.extensions.litestar.dto.SQLAlchemyDTO>` 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``.
.. change:: SQLAlchemy: Allow repository functions to be filtered by expressions
:type: feature
:pr: 2265
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:
.. code-block:: python
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``:
.. code-block:: python
locations, total_count = await model_service.list_and_count(
statement=select(Model).where(
ST_DWithin(UniqueLocation.location, geog, 1000)
),
account_id=str(account_id),
)
.. change:: SQLAlchemy: Use :func:`lambda_stmt <sqlalchemy.sql.expression.lambda_stmt>` in the repository
:type: feature
:pr: 2179
Converts the repository to use :func:`lambda_stmt <sqlalchemy.sql.expression.lambda_stmt>`
instead of the normal ``select``
.. change:: SQLAlchemy: Swap to the `advanced_alchemy <https://advanced-alchemy.litestar.dev>`_ implementations
:type: feature
:pr: 2312
Swaps the internal SQLAlchemy repository to use the external
`advanced_alchemy <https://advanced-alchemy.litestar.dev>`_ library implementations
.. change:: Remove usages of deprecated ``ExceptionHandlerMiddleware`` ``debug`` parameter
:type: bugfix
:pr: 2192
Removes leftover usages of deprecated ``ExceptionHandlerMiddleware`` debug parameter.
.. change:: DTOs: Raise :class:`ValidationException` when Pydantic validation fails
:type: bugfix
:pr: 2204
:issue: 2190
Ensures that when the Pydantic validation fails in the Pydantic DTO,
a :class:`ValidationException` is raised with the extras set to the errors given by Pydantic.
.. change:: Set the max width of the console to 80
:type: bugfix
:pr: 2244
Sets the max width of the console to 80, to prevent the output from being
wrapped.
.. change:: Handling of optional path parameters
:type: bugfix
:pr: 2224
:issue: 2222
Resolves an issue where optional path parameters caused a 500 error to be raised.
.. change:: Use os.replace instead of shutil.move for renaming files
:type: bugfix
:pr: 2223
Change to using :func:`os.replace` instead of :func:`shutil.move` for renaming files, to
ensure atomicity.
.. change:: Exception detail attribute
:type: bugfix
:pr: 2231
Set correctly the detail attribute on :class:`LitestarException` and :class:`HTTPException`
regardless of whether it's passed positionally or by name.
.. change:: Filters not available in ``exists()``
:type: bugfix
:pr: 2228
:issue: 2221
Fixes :meth:`exists` method for SQLAlchemy sync and async.
.. change:: Add Pydantic types to SQLAlchemy registry only if Pydantic is installed
:type: bugfix
:pr: 2252
Allows importing from ``litestar.contrib.sqlalchemy.base`` even if Pydantic is not installed.
.. change:: Don't add content type for responses that don't have a body
:type: bugfix
:pr: 2263
:issue: 2106
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)``.
.. change:: ``SQLAlchemyPlugin`` refactored
:type: bugfix
:pr: 2269
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.
.. change:: Ensure ``app-dir`` is appended to path during autodiscovery
:type: bugfix
:pr: 2277
:issue: 2266
Fixes a bug which caused the ``--app-dir`` option to the Litestar CLI to not be propagated during autodiscovery.
.. change:: Set content length header by default
:type: bugfix
:pr: 2271
Sets the ``content-length`` header by default even if the length of the body is ``0``.
.. change:: Incorrect handling of mutable headers in :class:`ASGIResponse`
:type: bugfix
:pr: 2308
:issue: 2196
Update :class:`ASGIResponse`, :class:`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 :class:`ASGIResponse` with :class:`MutableScopeHeaders`, which allows for case-insensitive membership tests, ``.setdefault`` operations, etc.
.. change:: Adds missing ORM registry export
:type: bugfix
:pr: 2316
Adds an export that was overlooked for the base repo
.. change:: Discrepancy in ``attrs``, ``msgspec`` and ``Pydantic`` for multi-part forms
:type: bugfix
:pr: 2280
:issue: 2278
Resolves issue in ``attrs``, ``msgspec`` and Pydantic for multi-part forms
.. change:: Set proper default for ``exclude_http_methods`` in auth middleware
:type: bugfix
:pr: 2325
:issue: 2205
Sets ``OPTIONS`` as the default value for ``exclude_http_methods`` in the base authentication middleware class.
.. changelog:: 2.0.0
:date: 2023/08/19
.. change:: Regression | Missing ``media_type`` information to error responses
:type: bugfix
:pr: 2131
:issue: 2024
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.
.. change:: Regression | ``Litestar.debug`` does not propagate to exception handling middleware
:type: bugfix
:pr: 2153
:issue: 2147
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.
.. change:: Static files not being served if a route handler with the same base path was registered
:type: bugfix
:pr: 2154
Fixed a bug that would result in a ``404 - Not Found`` when requesting a static
file where the ``litestar.static_files.StaticFilesConfig.path`` was also
used by a route handler.
.. change:: HTMX: Missing default values for ``receive`` and ``send`` parameters of ``HTMXRequest``
:type: bugfix
:pr: 2145
Add missing default values for the ``receive`` and ``send`` parameters of
``litestar.contrib.htmx.request.HTMXRequest``.
.. change:: DTO: Excluded attributes accessed during transfer
:type: bugfix
:pr: 2127
:issue: 2125
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).
.. change:: DTO | Regression: ``DTOData.create_instance`` ignores renaming
:type: bugfix
:pr: 2144
Fix a regression where calling
:meth:`~litestar.dto.data_structures.DTOData.create_instance` would ignore the
renaming settings of fields.
.. change:: OpenAPI | Regression: Response schema for files and streams set ``application/octet-stream`` as ``contentEncoding`` instead of ``contentMediaType``
:type: bugfix
:pr: 2130
Fix a regression that would set ``application/octet-stream`` as the ``contentEncoding``
instead of ``contentMediaType`` in the response schema of
:class:`~litestar.response.File` :class:`~litestar.response.Stream`.
.. change:: OpenAPI | Regression: Response schema diverges from ``prefer_alias`` setting for Pydantic models
:type: bugfix
:pr: 2150
Fix a regression that made the response schema use ``prefer_alias=True``,
diverging from how Pydantic models are exported by default.
.. change:: OpenAPI | Regression: Examples not being generated deterministically
:type: bugfix
:pr: 2161
Fix a regression that made generated examples non-deterministic, caused by a
misconfiguration of the random seeding.
.. change:: SQLAlchemy repository: Handling of dialects not supporting JSON
:type: bugfix
:pr: 2139
:issue: 2137
Fix a bug where SQLAlchemy would raise a :exc:`TypeError` when using a dialect
that does not support JSON with the SQLAlchemy repositories.
.. change:: JWT | Regression: ``OPTIONS`` and ``HEAD`` being authenticated by default
:type: bugfix
:pr: 2160
Fix a regression that would make
``litestar.contrib.jwt.JWTAuthenticationMiddleware`` authenticate
``OPTIONS`` and ``HEAD`` requests by default.
.. change:: SessionAuth | Regression: ``OPTIONS`` and ``HEAD`` being authenticated by default
:type: bugfix
:pr: 2182
Fix a regression that would make
:class:`~litestar.security.session_auth.middleware.SessionAuthMiddleware` authenticate
``OPTIONS`` and ``HEAD`` requests by default.
.. changelog:: 2.0.0rc1
:date: 2023/08/05
.. change:: Support for server-sent-events
:type: feature
:pr: 2035
:issue: 1185
Support for `Server-sent events <https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events>` has been
added with the :class:`ServerSentEvent <.response.ServerSentEvent>`:
.. code-block:: python
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())
.. seealso::
:ref:`Server Sent Events <usage/responses:Server Sent Event Responses>`
.. change:: SQLAlchemy repository: allow specifying ``id_attribute`` per method
:type: feature
:pr: 2052
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``
.. change:: SQLAlchemy repository: New ``upsert_many`` method
:type: feature
:pr: 2056
A new method ``upsert_many`` has been added to the SQLAlchemy repositories,
providing equivalent functionality to the ``upsert`` method for multiple
model instances.
.. seealso::
``~litestar.contrib.sqlalchemy.repository.SQLAlchemyAsyncRepository.upsert_many``
``~litestar.contrib.sqlalchemy.repository.SQLAlchemySyncRepository.upsert_many``
.. change:: SQLAlchemy repository: New filters: ``OnBeforeAfter``, ``NotInCollectionFilter`` and ``NotInSearchFilter``
:type: feature
:pr: 2057
The following filters have been added to the SQLAlchemy repositories:
``litestar.contrib.repository.filters.OnBeforeAfter``
Allowing to filter :class:`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
.. change:: SQLAlchemy repository: Configurable chunk sizing for ``delete_many``
:type: feature
:pr: 2061
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.
.. change:: SQLAlchemy repository: Support InstrumentedAttribute for attribute columns
:type: feature
:pr: 2054
Support :class:`~sqlalchemy.orm.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``
.. change:: OpenAPI: Support callable ``operation_id`` on route handlers
:type: feature
:pr: 2078
Route handlers may be passed a callable to ``operation_id`` to create the
OpenAPI operation ID.
.. change:: Run event listeners concurrently
:type: feature
:pr: 2096
:doc:`/usage/events` now run concurrently inside a task group.
.. change:: Support extending the CLI with plugins
:type: feature
:pr: 2066
A new plugin protocol ``CLIPluginProtocol`` has been added that can be used to
extend the Litestar CLI.
.. seealso::
:ref:`usage/cli:Using a plugin`
.. change:: DTO: Support renamed fields in ``DTOData`` and ``create_instance``
:type: bugfix
:pr: 2065
A bug was fixed that would cause field renaming to be skipped within
:class:`~litestar.dto.data_structures.DTOData` and
:meth:`~litestar.dto.data_structures.DTOData.create_instance`.
.. change:: SQLAlchemy repository: Fix ``health_check`` for oracle
:type: bugfix
:pr: 2060
The emitted statement for oracle has been changed to ``SELECT 1 FROM DUAL``.
.. change:: Fix serialization of empty strings in multipart form
:type: bugfix
:pr: 2044
A bug was fixed that would cause a validation error to be raised for empty
strings during multipart form decoding.
.. change:: Use debug mode by default in test clients
:type: misc
:pr: 2113
The test clients will now default to ``debug=True`` instead of ``debug=None``.
.. change:: Removal of deprecated ``partial`` module
:type: misc
:pr: 2113
:breaking:
The deprecated ``litestar.partial`` has been removed. It can be replaced with
DTOs, making use of the :class:`~litestar.dto.config.DTOConfig` option
``partial=True``.
.. change:: Removal of deprecated ``dto/factory`` module
:type: misc
:pr: 2114
:breaking:
The deprecated module ``litestar.dto.factory`` has been removed.
.. change:: Removal of deprecated ``contrib/msgspec`` module
:type: misc
:pr: 2114
:breaking:
The deprecated module ``litestar.contrib.msgspec`` has been removed.
.. changelog:: 2.0.0beta4
:date: 2023/07/21
.. change:: Fix extra package dependencies
:type: bugfix
:pr: 2029
A workaround for a
`bug in poetry <https://github.com/python-poetry/poetry/issues/4401>`_ that
caused development / extra dependencies to be installed alongside the package
has been added.
.. changelog:: 2.0.0beta3
:date: 2023/07/20
.. change:: :class:`SQLAlchemyDTO (Advanced Alchemy) <advanced_alchemy.extensions.litestar.dto.SQLAlchemyDTO>`: column/relationship type inference
:type: feature
:pr: 1879
:issue: 1853
If type annotations aren't available for a given column/relationship, they may
be inferred from the mapped object.
For columns, the :attr:`~sqlalchemy.engine.interfaces.ReflectedColumn.type`\ 's
:attr:`~sqlalchemy.types.TypeEngine.python_type` will be used as the type of the
column, and the :attr:`~sqlalchemy.engine.interfaces.ReflectedColumn.nullable`
property to determine if the field should have a :obj:`None` union.
For relationships, where the ``RelationshipProperty.direction`` is
:attr:`~sqlalchemy.orm.RelationshipDirection.ONETOMANY` or
:attr:`~sqlalchemy.orm.RelationshipDirection.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 :obj:`None` if all of the
foreign key columns are nullable.
.. change:: DTO: Piccolo ORM
:type: feature
:pr: 1896
Add support for piccolo ORM with the
:class:`!litestar.contrib.piccolo.PiccoloDTO`.
.. change:: OpenAPI: Allow setting ``OpenAPIController.path`` from ```OpenAPIConfig``
:type: feature
:pr: 1886
:attr:`~litestar.openapi.OpenAPIConfig.path` has been added, which can be used
to set the ``path`` for :class:`~litestar.openapi.OpenAPIController` directly,
without needing to create a custom instance of it.
If ``path`` is set in both :class:`~litestar.openapi.OpenAPIConfig` and
:class:`~litestar.openapi.OpenAPIController`, the path set on the controller
will take precedence.
.. change:: SQLAlchemy repository: ``auto_commit``, ``auto_expunge`` and ``auto_refresh`` options
:type: feature
:pr: 1900
.. currentmodule:: litestar.contrib.sqlalchemy.repository
Three new parameters have been added to the repository and various methods:
``auto_commit``
When this :obj:`True`, the session will
:meth:`~sqlalchemy.orm.Session.commit` instead of
:meth:`~sqlalchemy.orm.Session.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 :obj:`True`, the session will execute
:meth:`~sqlalchemy.orm.Session.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 :obj:`True`, the session will execute
:meth:`~sqlalchemy.orm.Session.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)
.. change:: Include path name in ``ImproperlyConfiguredException`` message for missing param types
:type: feature
:pr: 1935
The message of a :exc:`ImproperlyConfiguredException` raised when a path
parameter is missing a type now contains the name of the path.
.. change:: DTO: New ``include`` parameter added to ``DTOConfig``
:type: feature
:pr: 1950
:attr:`~litestar.dto.config.DTOConfig.include` has been added to
:class:`~litestar.dto.config.DTOConfig`, providing a counterpart to
:attr:`~litestar.dto.config.DTOConfig.exclude`.
If ``include`` is provided, only those fields specified within it will be
included.
.. change:: ``AbstractDTOFactory`` moved to ``dto.factory.base``
:type: misc
:breaking:
:pr: 1950
:class:`~litestar.dto.base_factory.AbstractDTOFactory` has moved from
``litestar.dto.factory.abc`` to ``litestar.dto.factory.base``.
.. change:: SQLAlchemy repository: Rename ``_sentinel`` column to ``sa_orm_sentinel``
:type: misc
:breaking:
:pr: 1933
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 ``_``.
.. change:: SQLAlchemy repository: Fix audit columns defaulting to app startup time
:type: bugfix
:pr: 1894
A bug was fixed where
``~litestar.contrib.sqlalchemy.base.AuditColumns.created_at`` and
``~litestar.contrib.sqlalchemy.base.AuditColumns.updated_at`` would default
to the :class:`~datetime.datetime` at initialization time, instead of the time
of the update.
.. change:: :class:`SQLAlchemyDTO (Advanced Alchemy) <advanced_alchemy.extensions.litestar.dto.SQLAlchemyDTO>`: Fix handling of ``Sequence`` with defaults
:type: bugfix
:pr: 1883
:issue: 1851
Fixes handling of columns defined with
`Sequence <https://docs.sqlalchemy.org/en/20/core/defaults.html#defining-sequences>`_
default values.
The SQLAlchemy default value for a :class:`~sqlalchemy.schema.Column` will be
ignored when it is a :class:`~sqlalchemy.schema.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.
.. change:: Allow JSON as redirect response
:type: bugfix
:pr: 1908
Enables using redirect responses with a JSON media type.
.. change:: DTO / OpenAPI: Fix detection of required fields for Pydantic and msgspec DTOs
:type: bugfix
:pr: 1946
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.
.. change:: Replace ``Header``, ``CacheControlHeader`` and ``ETag`` Pydantic models with dataclasses
:type: misc
:pr: 1917
:breaking:
As part of the removal of Pydantic as a hard dependency, the header models
:class:`~litestar.datastructures.Header`,
:class:`~litestar.datastructures.CacheControlHeader` and
:class:`~litestar.datastructures.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.
.. change:: Pydantic as an optional dependency
:breaking:
:pr: 1963
:type: misc
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.
.. change:: Pydantic 2 support
:type: feature
:pr: 1956
Pydantic 2 is now supported alongside Pydantic 1.
.. change:: Deprecation of ``partial`` module
:type: misc
:pr: 2002
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 :class:`~litestar.dto.config.DTOConfig` option
``partial=True``.
.. changelog:: 2.0.0beta2
:date: 2023/06/24
.. change:: Support ``annotated-types``
:type: feature
:pr: 1847
Extended support for the
`annotated-types <https://pypi.org/project/annotated-types>`_ library is now
available.
.. change:: Increased verbosity of validation error response keys
:type: feature
:pr: 1774
: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.
.. code-block:: json
:caption: 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"}
]
}
.. code-block:: json
:caption: 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"},
]
}
.. change:: ``TestClient`` default timeout
:type: feature
:pr: 1840
:breaking:
A ``timeout`` parameter was added to
- :class:`~litestar.testing.TestClient`
- :class:`~litestar.testing.AsyncTestClient`
- :class:`~litestar.testing.create_test_client`
- :class:`~litestar.testing.create_async_test_client`
The value is passed down to the underlying HTTPX client and serves as a default
timeout for all requests.
.. change:: SQLAlchemy DTO: Explicit error messages when type annotations for a column are missing
:type: feature
:pr: 1852
Replace the nondescript :exc:`KeyError` raised when a SQLAlchemy DTO is
constructed from a model that is missing a type annotation for an included
column with an :exc:`ImproperlyConfiguredException`, including an explicit error
message, pointing at the potential cause.
.. change:: Remove exception details from Internal Server Error responses
:type: bugfix
:pr: 1857
:issue: 1856
Error responses with a ``500`` status code will now always use
`"Internal Server Error"` as default detail.
.. change:: Pydantic v1 regex validation
:type: bugfix
:pr: 1865
:issue: 1860
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
:attr:`~litestar.params.KwargDefinition.pattern` not being validated.
.. changelog:: 2.0.0beta1
:date: 2023/06/16
.. change:: Expose ``ParsedType`` as public API
:type: feature
:pr: 1677 1567
Expose the previously private :class:`litestar.typing.ParsedType`. This is
mainly indented for usage with
``litestar.plugins.SerializationPluginProtocol.supports_type``
.. change:: Improved debugging capabilities
:type: feature
:pr: 1742
- A new ``pdb_on_exception`` parameter was added to
:class:`~litestar.app.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``
.. change:: OpenAPI: Add `operation_class` argument to HTTP route handlers
:type: feature
:pr: 1732
The ``operation_class`` argument was added to
:class:`~litestar.handlers.HTTPRouteHandler` and the corresponding decorators,
allowing to override the :class:`~litestar.openapi.spec.Operation` class, to
enable further customization of the generated OpenAPI schema.
.. change:: OpenAPI: Support nested ``Literal`` annotations
:type: feature
:pr: 1829
Support nested :class:`typing.Literal` annotations by flattening them into
a single ``Literal``.
.. change:: CLI: Add ``--reload-dir`` option to ``run`` command
:type: feature
:pr: 1689
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.
.. change:: Allow extra attributes on JWTs via ``extras`` attribute
:type: feature
:pr: 1695
Add the ``litestar.contrib.jwt.Token.extras`` attribute, containing extra
attributes found on the JWT.
.. change:: Add default modes for ``Websocket.iter_json`` and ``WebSocket.iter_data``
:type: feature
:pr: 1733
Add a default ``mode`` for :meth:`~litestar.connection.WebSocket.iter_json` and
:meth:`~litestar.connection.WebSocket.iter_data`, with a value of ``text``.
.. change:: SQLAlchemy repository: Synchronous repositories
:type: feature
:pr: 1683
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 :class:`sqlalchemy.orm.Session`.
.. change:: SQLAlchemy repository: Oracle Database support
:type: feature
:pr: 1694
Add support for Oracle Database via
`oracledb <https://oracle.github.io/python-oracledb/>`_.
.. change:: SQLAlchemy repository: DuckDB support
:type: feature
:pr: 1744
Add support for `DuckDB <https://duckdb.org/>`_.
.. change:: SQLAlchemy repository: Google Spanner support
:type: feature
:pr: 1744
Add support for `Google Spanner <https://cloud.google.com/spanner>`_.
.. change:: SQLAlchemy repository: JSON check constraint for Oracle Database
:type: feature
:pr: 1780
When using the :class:`litestar.contrib.sqlalchemy.types.JsonB` type with an
Oracle Database engine, a JSON check constraint will be created for that
column.
.. change:: SQLAlchemy repository: Remove ``created`` and ``updated`` columns
:type: feature
:pr: 1816
:breaking:
The ``created`` and ``updated`` columns have been superseded by
``created_at`` and ``updated_at`` respectively, to prevent name clashes.
.. change:: SQLAlchemy repository: Add timezone aware type
:type: feature
:pr: 1816
:breaking:
A new timezone aware type ``litestar.contrib.sqlalchemy.types.DateTimeUTC``
has been added, which enforces UTC timestamps stored in the database.
.. change:: SQLAlchemy repository: Exclude unloaded columns in ``to_dict``
:type: feature
:pr: 1802
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.
.. change:: DTOs: Nested keyword arguments in ``.create_instance()``
:type: feature
:pr: 1741
:issue: 1727
The
:meth:`DTOData.create_instance <litestar.dto.factory.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")``.
.. seealso::
:ref:`usage/dto/1-abstract-dto:Providing values for nested data`
.. change:: DTOs: Hybrid properties and association proxies in
:class:`SQLAlchemyDTO (Advanced Alchemy) <advanced_alchemy.extensions.litestar.dto.SQLAlchemyDTO>`
:type: feature
:pr: 1754 1776
The :class:`SQLAlchemyDTO (Advanced Alchemy) <advanced_alchemy.extensions.litestar.dto.SQLAlchemyDTO>`
now supports `hybrid attribute <https://docs.sqlalchemy.org/en/20/orm/extensions/hybrid.html>`_
and `associationproxy <https://docs.sqlalchemy.org/en/20/orm/extensions/associationproxy.html>`_.
The generated field will be marked read-only.
.. change:: DTOs: Transfer to generic collection types
:type: feature
:pr: 1764
:issue: 1763
DTOs can now be wrapped in generic collection types such as
:class:`typing.Sequence`. These will be substituted with a concrete and
instantiable type at run time, e.g. in the case of ``Sequence`` a :class:`list`.
.. change:: DTOs: Data transfer for non-generic builtin collection annotations
:type: feature
:pr: 1799
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]``.
.. change:: DTOs: Exclude leading underscore fields by default
:type: feature
:pr: 1777
:issue: 1768
:breaking:
Leading underscore fields will not be excluded by default. This behaviour can be
configured with the newly introduced
:attr:`~litestar.dto.factory.DTOConfig.underscore_fields_private` configuration
value, which defaults to ``True``.
.. change:: DTOs: Msgspec and Pydantic DTO factory implementation
:type: feature
:pr: 1712
:issue: 1531, 1532
DTO factories for `msgspec <https://jcristharif.com/msgspec/>`_ and
`Pydantic <https://docs.pydantic.dev/latest/>`_ have been added:
- :class:`~litestar.contrib.msgspec.MsgspecDTO`
- :class:`~litestar.contrib.pydantic.PydanticDTO`
.. change:: DTOs: Arbitrary generic wrappers
:pr: 1801
:issue: 1631, 1798
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
.. code-block:: python
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}
.. change:: Store and reuse state `deep_copy` directive when copying state
:type: bugfix
:issue: 1674
:pr: 1678
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.
.. change:: ``ParsedType.is_subclass_of(X)`` ``True`` for union if all union types are subtypes of ``X``
:type: bugfix
:pr: 1690
:issue: 1652
When :class:`~litestar.typing.ParsedType` was introduced,
:meth:`~litestar.typing.ParsedType.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
:class:`~litestar.response.Response` subtypes then the correct response handler
will now be applied.
.. change:: Inconsistent template autoescape behavior
:type: bugfix
:pr: 1718
:issue: 1699
The mako template engine now defaults to autoescaping expressions, making it
consistent with config of Jinja template engine.
.. change:: Missing ``ChannelsPlugin`` in signature namespace population
:type: bugfix
:pr: 1719
:issue: 1691
The :class:`~litestar.channels.plugin.ChannelsPlugin` has been added to the
signature namespace, fixing an issue where using
``from __future__ import annotations`` or stringized annotations would lead to
a :exc:`NameError`, if the plugin was not added to the signatured namespace
manually.
.. change:: Gzip middleware not sending small streaming responses
:type: bugfix
:pr: 1723
:issue: 1681
A bug was fixed that would cause smaller streaming responses to not be sent at
all when the :class:`~litestar.middleware.compression.CompressionMiddleware` was
used with ``gzip``.
.. change:: Premature transfer to nested models with `DTOData`
:type: bugfix
:pr: 1731
:issue: 1726
An issue was fixed where data that should be transferred to builtin types on
instantiation of :class:`~litestar.dto.factory.DTOData` was being instantiated
into a model type for nested models.
.. change:: Incorrect ``sync_to_thread`` usage warnings for generator dependencies
:type: bugfix
:pr: 1716 1740
:issue: 1711
A bug was fixed that caused incorrect warnings about missing ``sync_to_thread``
usage were issues when asynchronous generators were being used as dependencies.
.. change:: Dependency injection custom dependencies in ``WebSocketListener``
:type: bugfix
:pr: 1807
:issue: 1762
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
:class:`~litestar.handlers.WebsocketListener`.
.. change:: OpenAPI schema for ``Dict[K, V]`` ignores generic
:type: bugfix
:pr: 1828
:issue: 1795
An issue with the OpenAPI schema generation was fixed that would lead to generic
arguments to :class:`dict` being ignored.
An type like ``dict[str, int]`` now correctly renders as
``{"type": "object", "additionalProperties": { "type": "integer" }}``.
.. change:: ``WebSocketTestSession`` not timing out without when connection is not accepted
:type: bugfix
:pr: 1696
A bug was fixed that caused :class:`~litestar.testing.WebSocketTestSession` to
block indefinitely when if :meth:`~litestar.connection.WebSocket.accept` was
never called, ignoring the ``timeout`` parameter.
.. change:: SQLAlchemy repository: Fix alembic migrations generated for models using ``GUID``
:type: bugfix
:pr: 1676
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.
.. change:: Remove ``state`` parameter from ``AfterExceptionHookHandler`` and ``BeforeMessageSendHookHandler``
:type: misc
:pr: 1739
:breaking:
Remove the ``state`` parameter from ``AfterExceptionHookHandler`` and
``BeforeMessageSendHookHandler``.
``AfterExceptionHookHandler``\ s will have to be updated from
.. code-block:: python
async def after_exception_handler(
exc: Exception, scope: Scope, state: State
) -> None: ...
to
.. code-block:: python
async def after_exception_handler(exc: Exception, scope: Scope) -> None: ...
The state can still be accessed like so:
.. code-block:: python
async def after_exception_handler(exc: Exception, scope: Scope) -> None:
state = scope["app"].state
``BeforeMessageSendHookHandler``\ s will have to be updated from
.. code-block:: python
async def before_send_hook_handler(
message: Message, state: State, scope: Scope
) -> None: ...
to
.. code-block:: python
async def before_send_hook_handler(message: Message, scope: Scope) -> None: ...
where state can be accessed in the same manner:
.. code-block:: python
async def before_send_hook_handler(message: Message, scope: Scope) -> None:
state = scope["app"].state
.. change:: Removal of ``dto.exceptions`` module
:pr: 1773
:breaking:
The module ``dto.exceptions`` has been removed, since it was not used anymore
internally by the DTO implementations, and superseded by standard exceptions.
.. change:: ``BaseRouteHandler`` no longer generic
:pr: 1819
:breaking:
:class:`~litestar.handlers.BaseRouteHandler` was originally made generic to
support proper typing of the ``ownership_layers`` property, but the same effect
can now be achieved using :class:`typing.Self`.
.. change:: Deprecation of ``Litestar`` parameter ``preferred_validation_backend``
:pr: 1810
:breaking:
The following changes have been made regarding the
``preferred_validation_backend``:
- The ``preferred_validation_backend`` parameter of
:class:`~litestar.app.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
:class:`~litestar.config.app.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.
.. change:: ``Response.get_serializer`` moved to ``serialization.get_serializer``
:pr: 1820
:breaking:
The ``Response.get_serializer()`` method has been removed in favor of the
:func:`~litestar.serialization.get_serializer` function.
In the previous :class:`~litestar.response.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 :class:`~litestar.response.base.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``.
.. change:: Remove response containers and introduce ``ASGIResponse``
:pr: 1790
: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 :class:`~litestar.response.Response`. The predefined response containers
still exist functionally, as subclasses of
:class:`Response <.response.Response>` and are now located within the
:mod:`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 :class:`~litestar.response.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
:class:`ASGIResponse <.response.base.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.
.. changelog:: 2.0.0alpha7
:date: 2023/05/14
.. change:: Warn about sync callables in route handlers and dependencies without an explicit ``sync_to_thread`` value
:type: feature
:pr: 1648 1655
A warning will now be raised when a synchronous callable is being used in an
:class:`~.handlers.HTTPRouteHandler` or :class:`~.di.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``.
.. seealso::
:doc:`/topics/sync-vs-async`
.. change:: Warn about ``sync_to_thread`` with async callables
:type: feature
:pr: 1664
A warning will be raised when ``sync_to_thread`` is being used in
:class:`~.handlers.HTTPRouteHandler` or :class:`~.di.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``.
.. change:: WebSockets: Dependencies in listener hooks
:type: feature
:pr: 1647
Dependencies can now be used in the
:func:`~litestar.handlers.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.
.. change:: Declaring dependencies without ``Provide``
:type: feature
:pr: 1647
Dependencies can now be declared without using :class:`~litestar.di.Provide`.
The callables can be passed directly to the ``dependencies`` dictionary.
.. change:: Add ``DTOData`` to receive unstructured but validated DTO data
:type: feature
:pr: 1650
:class:`~litestar.dto.factory.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.
.. change:: Partial DTOs
:type: feature
:pr: 1651
Add a ``partial`` flag to :class:`~litestar.dto.factory.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.
.. change:: SQLAlchemy repository: ``psycopg`` asyncio support
:type: feature
:pr: 1657
Async `psycopg <https://www.psycopg.org/>`_ is now officially supported and
tested for the SQLAlchemy repository.
.. change:: SQLAlchemy repository: ``BigIntPrimaryKey`` mixin
:type: feature
:pr: 1657
``~litestar.contrib.sqlalchemy.base.BigIntPrimaryKey`` mixin, providing a
``BigInt`` primary key column, with a fallback to ``Integer`` for sqlite.
.. change:: SQLAlchemy repository: Store GUIDs as binary on databases that don't have a native GUID type
:type: feature
:pr: 1657
On databases without native support for GUIDs,
``~litestar.contrib.sqlalchemy.types.GUID`` will now fall back to
``BINARY(16)``.
.. change:: Application lifespan context managers
:type: feature
:pr: 1635
A new ``lifespan`` argument has been added to :class:`~litestar.app.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.
.. change:: Unify application lifespan hooks: Remove ``before_`` and ``after_``
:breaking:
:type: feature
:pr: 1663
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 :class:`~litestar.app.Litestar` application instead
of the application's state.
.. change:: Trio-compatible event emitter
:type: feature
:pr: 1666
The default :class:`~litestar.events.emitter.SimpleEventEmitter` is now
compatible with `trio <https://trio.readthedocs.io/en/stable/>`_.
.. change:: OpenAPI: Support ``msgspec.Meta``
:type: feature
:pr: 1669
:class:`msgspec.Meta` is now fully supported for OpenAPI schema generation.
.. change:: OpenAPI: Support Pydantic ``FieldInfo``
:type: feature
:pr: 1670
:issue: 1541
Pydantic's ``FieldInfo`` (``regex``, ``gt``, ``title``, etc.) now have full
support for OpenAPI schema generation.
.. change:: OpenAPI: Fix name collision in DTO models
:type: bugfix
:pr: 1649
:issue: 1643
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.
.. change:: Fix validated attrs model being injected as a dictionary
:type: bugfix
:pr: 1668
:issue: 1643
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.
.. change:: Validate unknown media types
:breaking:
:type: bugfix
:pr: 1671
:issue: 1446
An unknown media type in places where Litestar can't infer the type from the
return annotation, an :exc:`ImproperlyConfiguredException` will now be raised.
.. changelog:: 2.0.0alpha6
:date: 2023/05/09
.. change:: Relax typing of ``**kwargs`` in ``ASGIConnection.url_for``
:type: bugfix
:pr: 1610
Change the typing of the ``**kwargs`` in
:meth:`ASGIConnection.url_for <litestar.connection.ASGIConnection.url_for>` from
``dict[str, Any]`` to ``Any``
.. change:: Fix: Using ``websocket_listener`` in controller causes ``TypeError``
:type: bugfix
:pr: 1627
:issue: 1615
A bug was fixed that would cause a type error when using a
:func:`websocket_listener <litestar.handlers.websocket_listener>`
in a ``Controller``
.. change:: Add ``connection_accept_handler`` to ``websocket_listener``
:type: feature
:pr: 1572
:issue: 1571
Add a new ``connection_accept_handler`` parameter to
:func:`websocket_listener <litestar.handlers.websocket_listener>`,
which can be used to customize how a connection is accepted, for example to
add headers or subprotocols
.. change:: Testing: Add ``block`` and ``timeout`` parameters to ``WebSocketTestSession`` receive methods
:type: feature
:pr: 1593
Two parameters, ``block`` and ``timeout`` have been added to the following methods:
- :meth:`receive <litestar.testing.WebSocketTestSession.receive>`
- :meth:`receive_text <litestar.testing.WebSocketTestSession.receive_text>`
- :meth:`receive_bytes <litestar.testing.WebSocketTestSession.receive_bytes>`
- :meth:`receive_json <litestar.testing.WebSocketTestSession.receive_json>`
.. change:: CLI: Add ``--app-dir`` option to root command
:type: feature
:pr: 1506
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.
.. change:: WebSockets: Data iterators
:type: feature
:pr: 1626
Two new methods were added to the :class:`WebSocket <litestar.connection.WebSocket>`
connection, which allow to continuously receive data and iterate over it:
- :meth:`iter_data <litestar.connection.WebSocket.iter_data>`
- :meth:`iter_json <litestar.connection.WebSocket.iter_json>`
.. change:: WebSockets: MessagePack support
:type: feature
:pr: 1626
Add support for `MessagePack <https://msgpack.org/index.html>`_ to the
:class:`WebSocket <litestar.connection.WebSocket>` connection.
Three new methods have been added for handling MessagePack:
- :meth:`send_msgpack <litestar.connection.WebSocket.send_msgpack>`
- :meth:`receive_msgpack <litestar.connection.WebSocket.receive_msgpack>`
- :meth:`iter_msgpack <litestar.connection.WebSocket.iter_msgpack>`
In addition, two MessagePack related methods were added to
:class:`WebSocketTestSession <litestar.testing.WebSocketTestSession>`:
- :meth:`send_msgpack <litestar.testing.WebSocketTestSession.send_msgpack>`
- :meth:`receive_msgpack <litestar.testing.WebSocketTestSession.receive_msgpack>`
.. change:: SQLAlchemy repository: Add support for sentinel column
:type: feature
:pr: 1603
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.
.. change:: DTO: Alias generator for field names
:type: feature
:pr: 1590
A new argument ``rename_strategy`` has been added to the :class:`DTOConfig <litestar.dto.factory.DTOConfig>`,
allowing to remap field names with strategies such as "camelize".
.. change:: DTO: Nested field exclusion
:type: feature
:pr: 1596
:issue: 1197
This feature adds support for excluding nested model fields using dot-notation,
e.g., ``"a.b"`` excludes field ``b`` from nested model field ``a``
.. change:: WebSockets: Managing a socket's lifespan using a context manager in websocket listeners
:type: feature
:pr: 1625
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
:func:`WebSocketListener <litestar.handlers.websocket_listener>`, which accepts
an asynchronous context manager, which can be used to handle the lifespan of
the socket.
.. change:: New module: Channels
:type: feature
:pr: 1587
A new module :doc:`channels </usage/channels>` has been added: A general purpose
event streaming library, which can for example be used to broadcast messages
via WebSockets.
.. change:: DTO: Undocumented ``dto.factory.backends`` has been made private
:breaking:
:type: misc
:pr: 1589
The undocumented ``dto.factory.backends`` module has been made private
.. changelog:: 2.0.0alpha5
.. change:: Pass template context to HTMX template response
:type: feature
:pr: 1488
Pass the template context to the ``Template`` returned by
``htmx.Response``.
.. change:: OpenAPI support for attrs and msgspec classes
:type: feature
:pr: 1487
Support OpenAPI schema generation for `attrs <https://www.attrs.org>`_ classes and
`msgspec <https://jcristharif.com/msgspec/>`_ ``Struct``\ s.
.. change:: SQLAlchemy repository: Add ``ModelProtocol``
:type: feature
:pr: 1503
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
.. change:: SQLAlchemy repository: Support MySQL/MariaDB
:type: feature
:pr: 1345
Add support for MySQL/MariaDB to the SQLAlchemy repository, using the
`asyncmy <https://github.com/long2ice/asyncmy>`_ driver.
.. change:: SQLAlchemy repository: Support MySQL/MariaDB
:type: feature
:pr: 1345
Add support for MySQL/MariaDB to the SQLAlchemy repository, using the
`asyncmy <https://github.com/long2ice/asyncmy>`_ driver.
.. change:: SQLAlchemy repository: Add matching logic to ``get_or_create``
:type: feature
:pr: 1345
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.
.. change:: Repository: Extend filter types
:type: feature
:pr: 1345
Add new filters ``litestar.contrib.repository.filters.OrderBy`` and
``litestar.contrib.repository.filters.SearchFilter``, providing ``ORDER BY ...`` and
``LIKE ...`` / ``ILIKE ...`` clauses respectively
.. change:: SQLAlchemy repository: Rename ``SQLAlchemyRepository`` > ``SQLAlchemyAsyncRepository``
:breaking:
:type: misc
:pr: 1345
``SQLAlchemyRepository`` has been renamed to
``litestar.contrib.sqlalchemy.repository.SQLAlchemyAsyncRepository``.
.. change:: DTO: Add ``AbstractDTOFactory`` and backends
:type: feature
:pr: 1461
An all-new DTO implementation was added, using ``AbstractDTOFactory`` as a base class, providing Pydantic and
msgspec backends to facilitate (de)serialization and validation.
.. change:: DTO: Remove ``from_connection`` / extend ``from_data``
:breaking:
:type: misc
:pr: 1500
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,
:meth:`DTOInterface.from_bytes <litestar.dto.interface.DTOInterface.data_to_encodable_type>` no longer needs to
receive the connection instance, so the ``request`` parameter has been dropped.
.. change:: WebSockets: Support DTOs in listeners
:type: feature
:pr: 1518
Support for DTOs has been added to :class:`WebSocketListener <litestar.handlers.WebsocketListener>` and
:func:`WebSocketListener <litestar.handlers.websocket_listener>`. A ``dto`` and ``return_dto`` parameter has
been added, providing the same functionality as their route handler counterparts.
.. change:: DTO based serialization plugin
:breaking:
:type: feature
:pr: 1501
``SerializationPluginProtocol`` has been re-implemented, leveraging the new
:class:`DTOInterface <litestar.dto.interface.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 <https://piccolo-orm.com/>`_ and `Tortoise ORM <https://tortoise.github.io/>`_ 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.
.. change:: SQLAlchemy 1 contrib module removed
:breaking:
:type: misc
:pr: 1501
As a result of the changes introduced in `#1501 <https://github.com/litestar-org/litestar/pull/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.
.. change:: Fix inconsistent parsing of unix timestamp between pydantic and cattrs
:type: bugfix
:pr: 1492
:issue: 1491
Timestamps parsed as :class:`date <datetime.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.
.. change:: Fix: Retrieve type hints from class with no ``__init__`` method causes error
:type: bugfix
:pr: 1505
:issue: 1504
An error would occur when using a callable without an :meth:`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 :meth:`object.__init__`, which would fail
with
.. code-block::
'wrapper_descriptor' object has no attribute '__module__'
.. change:: Fix error raised for partially installed attrs dependencies
:type: bugfix
:pr: 1543
An error was fixed that would cause a :exc:`MissingDependencyException` to be raised when dependencies for
`attrs <https://www.attrs.org>`_ were partially installed. This was fixed by being more specific about the
missing dependencies in the error messages.
.. change:: Change ``MissingDependencyException`` to be a subclass of ``ImportError``
:type: misc
:pr: 1557
:exc:`MissingDependencyException` is now a subclass of :exc:`ImportError`, to make handling cases where both
of them might be raised easier.
.. change:: Remove bool coercion in URL parsing
:breaking:
:type: bugfix
:pr: 1550
:issue: 1547
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.
.. change:: Update ``standard`` and ``full`` package extras
:type: misc
:pr: 1494
- 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
.. change:: Remove support for declaring DTOs as handler types
:breaking:
:type: misc
:pr: 1534
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.
.. change:: Fix missing ``content-encoding`` headers on gzip/brotli compressed files
:type: bugfix
:pr: 1577
:issue: 1576
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.
.. change:: DTO: Simplify ``DTOConfig``
:type: misc
:breaking:
:pr: 1580
- 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
.. changelog:: 2.0.0alpha4
.. change:: ``attrs`` and ``msgspec`` support in :class:`Partial <litestar.partial.Partial>`
:type: feature
:pr: 1462
:class:`Partial <litestar.partial.Partial>` now supports constructing partial models for attrs and msgspec
.. change:: :class:`Annotated <typing.Annotated>` support for route handler and dependency annotations
:type: feature
:pr: 1462
:class:`Annotated <typing.Annotated>` can now be used in route handler and dependencies to specify additional
information about the fields.
.. code-block:: python
@get("/")
def index(param: int = Parameter(gt=5)) -> dict[str, int]: ...
.. code-block:: python
@get("/")
def index(param: Annotated[int, Parameter(gt=5)]) -> dict[str, int]: ...
.. change:: Support ``text/html`` Media-Type in ``Redirect`` response container
:type: bugfix
:issue: 1451
:pr: 1474
The media type in :class:`Redirect <litestar.response.RedirectResponse>` won't be forced to ``text/plain`` anymore and
now supports setting arbitrary media types.
.. change:: Fix global namespace for type resolution
:type: bugfix
:pr: 1477
:issue: 1472
Fix a bug where certain annotations would cause a :exc:`NameError`
.. change:: Add uvicorn to ``cli`` extra
:type: bugfix
:issue: 1478
:pr: 1480
Add the ``uvicorn`` package to the ``cli`` extra, as it is required unconditionally
.. change:: Update logging levels when setting ``Litestar.debug`` dynamically
:type: bugfix
:issue: 1476
:pr: 1482
When passing ``debug=True`` to :class:`Litestar <litestar.app.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.
.. changelog:: 2.0.0alpha3
.. change:: SQLAlchemy 2.0 Plugin
:type: feature
:pr: 1395
A :class:`SQLAlchemyInitPlugin <litestar.contrib.sqlalchemy.plugins.SQLAlchemyInitPlugin>` was added,
providing support for managed synchronous and asynchronous sessions.
.. note::
SQLAlchemy documentation was available in v2 but SQLAlchemy support was moved into a standalone library in v3.
.. change:: Attrs signature modelling
:type: feature
:pr: 1382
Added support to model route handler signatures with attrs instead of Pydantic
.. change:: Support setting status codes in ``Redirect`` container
:type: feature
:pr: 1412
:issue: 1371
Add support for manually setting status codes in the
:class:`RedirectResponse <litestar.response_containers.Redirect>` 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.
.. change:: Sentinel value to support caching responses indefinitely
:type: feature
:pr: 1414
:issue: 1365
Add the :class:`CACHE_FOREVER <litestar.config.response_cache.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
:attr:`ResponseCacheConfig.default_expiration <litestar.config.response_cache.ResponseCacheConfig>` to ``None``,
allowing to cache values indefinitely by default when setting ``cache=True`` on a route handler.
.. change:: `Accept`-header parsing and content negotiation
:type: feature
:pr: 1317
Add an :attr:`accept <litestar.connection.Request.accept>` property to
:class:`Request <litestar.connection.Request>`, returning the newly added
:class:`Accept <litestar.datastructures.headers.Accept>` header wrapper, representing the requests ``Accept``
HTTP header, offering basic content negotiation.
.. seealso::
:ref:`usage/responses:Content Negotiation`
.. change:: Enhanced WebSockets support
:type: feature
:pr: 1402
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.
.. seealso::
:doc:`/usage/websockets`
.. change:: SQLAlchemy 1 plugin mutates app state destructively
:type: bugfix
:pr: 1391
:issue: 1368
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 :exc:`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.
.. change:: Fix SQLAlchemy 1 Plugin - ``'Request' object has no attribute 'dict'``
:type: bugfix
:pr: 1389
:issue: 1388
An annotation such as
.. code-block:: python
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 :func:`typing.get_args`
.. change:: Support OpenAPI schema generation with stringized return annotation
:type: bugfix
:pr: 1410
:issue: 1409
The following code would result in non-specific and incorrect information being generated for the OpenAPI schema:
.. code-block:: python
from __future__ import annotations
from starlite import Starlite, 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.
.. change:: Fix OpenAPI schema generation crashes for models with ``Annotated`` type attribute
:type: bugfix
:issue: 1372
:pr: 1400
When using a model that includes a type annotation with :class:`typing.Annotated` in a route handler, the
interactive documentation would raise an error when accessed. This has been fixed and :class:`typing.Annotated`
is now fully supported.
.. change:: Support empty ``data`` in ``RequestFactory``
:type: bugfix
:issue: 1419
:pr: 1420
Add support for passing an empty ``data`` parameter to a
:class:`RequestFactory <litestar.testing.RequestFactory>`, which would previously lead to an error.
.. change:: ``create_test_client`` and ``crate_async_test_client`` signatures and docstrings to to match ``Litestar``
:type: misc
:pr: 1417
Add missing parameters to :func:`create_test_client <litestar.testing.create_test_client>` and
:func:`create_test_client <litestar.testing.create_async_test_client>`. The following parameters were added:
- ``cache_control``
- ``debug``
- ``etag``
- ``opt``
- ``response_cache_config``
- ``response_cookies``
- ``response_headers``
- ``security``
- ``stores``
- ``tags``
- ``type_encoders``
.. changelog:: 2.0.0alpha2
.. change:: Repository contrib & SQLAlchemy repository
:type: feature
:pr: 1254
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.
.. change:: Data stores & registry
:type: feature
:pr: 1330
: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
.. seealso::
:doc:`/usage/stores`
.. change:: Add ``starlite.__version__``
:type: feature
:pr: 1277
Add a ``__version__`` constant to the ``starlite`` namespace, containing a
:class:`NamedTuple <typing.NamedTuple>`, holding information about the currently
installed version of Starlite
.. change:: Add ``starlite version`` command to CLI
:type: feature
:pr: 1322
Add a new ``version`` command to the CLI which displays the currently installed
version of Starlite
.. change:: Enhance CLI autodiscovery logic
:type: feature
:breaking:
:pr: 1322
Update the CLI :ref:`usage/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.
.. seealso::
:ref:`CLI autodiscovery <usage/cli:autodiscovery>`
.. change:: Configurable exception logging and traceback truncation
:type: feature
:pr: 1296
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
.. seealso::
``starlite.logging.config.LoggingConfig``
.. change:: Allow overwriting default OpenAPI response descriptions
:type: bugfix
:issue: 1292
:pr: 1293
Fix https://github.com/litestar-org/litestar/issues/1292 by allowing to overwrite
the default OpenAPI response description instead of raising :exc:`ImproperlyConfiguredException`.
.. change:: Fix regression in path resolution that prevented 404's being raised for false paths
:type: bugfix
:pr: 1316
: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"
.. change:: Fix ``after_request`` hook not being called on responses returned from handlers
:type: bugfix
:pr: 1344
:issue: 1315
``after_request`` hooks were not being called automatically when a ``starlite.response.Response``
instances was returned from a route handler directly.
.. seealso::
:ref:`after_request`
.. change:: Fix ``SQLAlchemyPlugin`` raises error when using SQLAlchemy UUID
:type: bugfix
:pr: 1355
An error would be raised when using the SQLAlchemy plugin with a
`sqlalchemy UUID <https://docs.sqlalchemy.org/en/20/core/type_basics.html#sqlalchemy.types.UUID>`_. This
was fixed by adding it to the provider map.
.. change:: Fix ``JSON.parse`` error in ReDoc and Swagger OpenAPI handlers
:type: bugfix
:pr: 1363
The HTML generated by the ReDoc and Swagger OpenAPI handlers would cause
`JSON.parse <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse>`_
to throw an error. This was fixed by removing the call to ``JSON.parse``.
.. change:: Fix CLI prints application info twice
:type: bugfix
:pr: 1322
Fix an error where the CLI would print application info twice on startup
.. change:: Update ``SimpleEventEmitter`` to use worker pattern
:type: misc
:pr: 1346
``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".
.. change:: Make ``BaseEventEmitterBackend.emit`` synchronous
:type: misc
:breaking:
:pr: 1376
``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.
.. change:: Move 3rd party integration plugins to ``contrib``
:type: misc
:breaking:
:pr: 1279 1252
- Move ``plugins.piccolo_orm`` > ``contrib.piccolo_orm``
- Move ``plugins.tortoise_orm`` > ``contrib.tortoise_orm``
.. change:: Remove ``picologging`` dependency from the ``standard`` package extra
:type: misc
:breaking:
:pr: 1313
`picologging <https://github.com/microsoft/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]``
.. change:: Replace ``Starlite()`` ``initial_state`` keyword argument with ``state``
:type: misc
:pr: 1350
: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
.. code-block:: python
from starlite import Starlite
app = Starlite(..., initial_state={"some": "key"})
to
.. code-block:: python
from starlite import Starlite
from starlite.datastructures.state import State
app = Starlite(..., state=State({"some": "key"}))
.. change:: Remove support for 2 argument form of ``before_send``
:type: misc
:pr: 1354
: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.
.. seealso::
:ref:`before_send`
.. change:: Standardize module exports
:type: misc
:pr: 1273
: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``
.. changelog:: 2.0.0alpha1
.. change:: Validation of controller route handler methods
:type: feature
:pr: 1144
Starlite will now validate that no duplicate handlers (that is, they have the same
path and same method) exist.
.. change:: HTMX support
:type: feature
:pr: 1086
Basic support for HTMX requests and responses.
.. change:: Alternate constructor ``Starlite.from_config``
:type: feature
:pr: 1190
``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.
.. change:: Web concurrency option for CLI ``run`` command
:pr: 1218
:type: feature
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
.. change:: Validation of ``state`` parameter in handler functions
:type: feature
:pr: 1264
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``.
.. change:: Generic application state
:type: feature
:pr: 1030
``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]``.
.. change:: Dependency injection of classes
:type: feature
:pr: 1143
Support using classes (not class instances, which were already supported) as dependency providers.
With this, now every callable is supported as a dependency provider.
.. change:: Event bus
:pr: 1105
:type: feature
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
.. change:: Unified storage interfaces
:type: feature
:pr: 1184
: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
.. change:: Relaxed type annotations
:pr: 1140
:type: misc
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]``.
.. change:: ``type_encoders`` support in ``AbstractSecurityConfig``
:type: misc
:pr: 1167
``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``.
.. change:: Renamed handler module names
:type: misc
:breaking:
:pr: 1170
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``
.. change:: New plugin protocols
:type: misc
:pr: 1176
: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
.. change:: Unify response headers and cookies
:type: misc
:breaking:
:pr: 1209
:ref:`response headers <usage/responses:Setting Response Headers>` and
:ref:`response cookies <usage/responses:Setting 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 :class:`Sequence <typing.Sequence>` of
``starlite.datastructures.response_header.ResponseHeader`` or
``starlite.datastructures.cookie.Cookie`` respectively.
.. change:: Replace Pydantic models with dataclasses
:type: misc
:breaking:
:pr: 1242
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``
.. change:: SQLAlchemy plugin moved to ``contrib``
:type: misc
:breaking:
:pr: 1252
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.
.. change:: Cleanup of the ``starlite`` namespace
:type: misc
:breaking:
:pr: 1135
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``.
.. change:: Fix resolving of relative paths in ``StaticFilesConfig``
:type: bugfix
:pr: 1256
Using a relative :class:`pathlib.Path` did not resolve correctly and result in a ``NotFoundException``
.. change:: Fix ``--reload`` flag to ``starlite run`` not working correctly
:type: bugfix
:pr: 1191
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.
.. change:: Fix optional types generate incorrect OpenAPI schemas
:type: bugfix
:pr: 1210
An optional query parameter was incorrectly represented as
.. code-block::
{ "oneOf": [
{ "type": null" },
{ "oneOf": [] }
]}
.. change:: Fix ``LoggingMiddleware`` is sending obfuscated session id to client
:type: bugfix
:pr: 1228
``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.
.. change:: Fix missing ``domain`` configuration value for JWT cookie auth
:type: bugfix
:pr: 1223
``starlite.contrib.jwt.jwt_auth.JWTCookieAuth`` didn't set the ``domain`` configuration value on the response
cookie.
.. change:: Fix https://github.com/litestar-org/litestar/issues/1201: Can not serve static file in ``/`` path
:type: bugfix
:issue: 1201
A validation error made it impossible to serve static files from the root path ``/`` .
.. change:: Fix https://github.com/litestar-org/litestar/issues/1149: Middleware not excluding static path
:type: bugfix
:issue: 1149
A middleware's ``exclude`` parameter would sometimes not be honoured if the path was used to serve static files
using ``StaticFilesConfig``.