|
3 | 3 | 2.x Changelog |
4 | 4 | ============= |
5 | 5 |
|
| 6 | +.. changelog:: 2.5.0 |
| 7 | + :date: 2024/01/06 |
| 8 | + |
| 9 | + .. change:: Fix serialization of custom types in exception responses |
| 10 | + :type: bugfix |
| 11 | + :issue: 2867 |
| 12 | + :pr: 2941 |
| 13 | + |
| 14 | + Fix a bug that would lead to a :exc:`SerializationException` when custom types |
| 15 | + were present in an exception response handled by the built-in exception |
| 16 | + handlers. |
| 17 | + |
| 18 | + .. code-block:: python |
| 19 | +
|
| 20 | + class Foo: |
| 21 | + pass |
| 22 | +
|
| 23 | +
|
| 24 | + @get() |
| 25 | + def handler() -> None: |
| 26 | + raise ValidationException(extra={"foo": Foo("bar")}) |
| 27 | +
|
| 28 | +
|
| 29 | + app = Litestar(route_handlers=[handler], type_encoders={Foo: lambda foo: "foo"}) |
| 30 | +
|
| 31 | + The cause was that, in examples like the one shown above, ``type_encoders`` |
| 32 | + were not resolved properly from all layers by the exception handling middleware, |
| 33 | + causing the serializer to throw an exception for an unknown type. |
| 34 | + |
| 35 | + .. change:: Fix SSE reverting to default ``event_type`` after 1st message |
| 36 | + :type: bugfix |
| 37 | + :pr: 2888 |
| 38 | + :issue: 2877 |
| 39 | + |
| 40 | + The ``event_type`` set within an SSE returned from a handler would revert back |
| 41 | + to a default after the first message sent: |
| 42 | + |
| 43 | + .. code-block:: python |
| 44 | +
|
| 45 | + @get("/stream") |
| 46 | + async def stream(self) -> ServerSentEvent: |
| 47 | + async def gen() -> AsyncGenerator[str, None]: |
| 48 | + c = 0 |
| 49 | + while True: |
| 50 | + yield f"<div>{c}</div>\n" |
| 51 | + c += 1 |
| 52 | +
|
| 53 | + return ServerSentEvent(gen(), event_type="my_event") |
| 54 | +
|
| 55 | + In this example, the event type would only be ``my_event`` for the first |
| 56 | + message, and fall back to a default afterwards. The implementation has been |
| 57 | + fixed and will now continue sending the set event type for all messages. |
| 58 | + |
| 59 | + .. change:: Correctly handle single file upload validation when multiple files are specified |
| 60 | + :type: bugfix |
| 61 | + :pr: 2950 |
| 62 | + :issue: 2939 |
| 63 | + |
| 64 | + Uploading a single file when the validation target allowed multiple would cause |
| 65 | + a :exc:`ValidationException`: |
| 66 | + |
| 67 | + .. code-block:: python |
| 68 | +
|
| 69 | + class FileUpload(Struct): |
| 70 | + files: list[UploadFile] |
| 71 | +
|
| 72 | +
|
| 73 | + @post(path="/") |
| 74 | + async def upload_files_object( |
| 75 | + data: Annotated[FileUpload, Body(media_type=RequestEncodingType.MULTI_PART)] |
| 76 | + ) -> list[str]: |
| 77 | + pass |
| 78 | +
|
| 79 | +
|
| 80 | + This could would only allow for 2 or more files to be sent, and otherwise throw |
| 81 | + an exception. |
| 82 | + |
| 83 | + .. change:: Fix trailing messages after unsubscribe in channels |
| 84 | + :type: bugfix |
| 85 | + :pr: 2894 |
| 86 | + |
| 87 | + Fix a bug that would allow some channels backend to receive messages from a |
| 88 | + channel it just unsubscribed from, for a short period of time, due to how the |
| 89 | + different brokers handle unsubscribes. |
| 90 | + |
| 91 | + .. code-block:: python |
| 92 | +
|
| 93 | + await backend.subscribe(["foo", "bar"]) # subscribe to two channels |
| 94 | + await backend.publish( |
| 95 | + b"something", ["foo"] |
| 96 | + ) # publish a message to a channel we're subscribed to |
| 97 | +
|
| 98 | + # start the stream after publishing. Depending on the backend |
| 99 | + # the previously published message might be in the stream |
| 100 | + event_generator = backend.stream_events() |
| 101 | +
|
| 102 | + # unsubscribe from the channel we previously published to |
| 103 | + await backend.unsubscribe(["foo"]) |
| 104 | +
|
| 105 | + # this should block, as we expect messages from channels |
| 106 | + # we unsubscribed from to not appear in the stream anymore |
| 107 | + print(anext(event_generator)) |
| 108 | +
|
| 109 | + Backends affected by this were in-memory, Redis PubSub and asyncpg. The Redis |
| 110 | + stream and psycopg backends were not affected. |
| 111 | + |
| 112 | + .. change:: Postgres channels backends |
| 113 | + :type: feature |
| 114 | + :pr: 2803 |
| 115 | + |
| 116 | + Two new channel backends were added to bring Postgres support: |
| 117 | + |
| 118 | + :class:`~litestar.channels.backends.asyncpg.AsyncPgChannelsBackend`, using the |
| 119 | + `asyncpg <https://magicstack.github.io/asyncpg/current/>`_ driver and |
| 120 | + :class:`~litestar.channels.backends.psycopg.PsycoPgChannelsBackend` using the |
| 121 | + `psycopg3 <https://www.psycopg.org/psycopg3/docs/>`_ async driver. |
| 122 | + |
| 123 | + .. seealso:: |
| 124 | + :doc:`/usage/channels` |
| 125 | + |
| 126 | + |
| 127 | + .. change:: Add ``--schema`` and ``--exclude`` option to ``litestar route`` CLI command |
| 128 | + :type: feature |
| 129 | + :pr: 2886 |
| 130 | + |
| 131 | + Two new options were added to the ``litestar route`` CLI command: |
| 132 | + |
| 133 | + - ``--schema``, to include the routes serving OpenAPI schema and docs |
| 134 | + - ``--exclude`` to exclude routes matching a specified pattern |
| 135 | + |
| 136 | + .. seealso:: |
| 137 | + :ref:`usage/cli:routes` |
| 138 | + |
| 139 | + .. change:: Improve performance of threaded synchronous execution |
| 140 | + :type: misc |
| 141 | + :pr: 2937 |
| 142 | + |
| 143 | + Performance of threaded synchronous code was improved by using the async |
| 144 | + library's native threading helpers instead of anyio. On asyncio, |
| 145 | + :meth:`asyncio.loop.run_in_executor` is now used and on trio |
| 146 | + :func:`trio.to_thread.run_sync`. |
| 147 | + |
| 148 | + Beneficiaries of these performance improvements are: |
| 149 | + |
| 150 | + - Synchronous route handlers making use of ``sync_to_thread=True`` |
| 151 | + - Synchronous dependency providers making use of ``sync_to_thread=True`` |
| 152 | + - Synchronous SSE generators |
| 153 | + - :class:`~litestar.stores.file.FileStore` |
| 154 | + - Large file uploads where the ``max_spool_size`` is exceeded and the spooled |
| 155 | + temporary file has been rolled to disk |
| 156 | + - :class:`~litestar.response.file.File` and |
| 157 | + :class:`~litestar.response.file.ASGIFileResponse` |
| 158 | + |
| 159 | + |
6 | 160 | .. changelog:: 2.4.5 |
7 | 161 | :date: 2023/12/23 |
8 | 162 |
|
|
0 commit comments