Skip to content

Commit

Permalink
Merge branch 'main' into fix-htmx-docs
Browse files Browse the repository at this point in the history
  • Loading branch information
JacobCoffee authored Sep 16, 2024
2 parents 13ae810 + bb1d0d4 commit 79895bb
Show file tree
Hide file tree
Showing 63 changed files with 1,792 additions and 1,244 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ jobs:
path: |
docs/_build/html
.pr_number
include-hidden-files: true

test_minimal_app:
name: Test Minimal Application with Base Dependencies
Expand Down
5 changes: 0 additions & 5 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ on:
push:
branches:
- main
- develop
- v3.0

jobs:
Expand Down Expand Up @@ -44,10 +43,6 @@ jobs:
run: pdm run python tools/build_docs.py docs-build --version main
if: github.event_name == 'push' && github.ref == 'refs/heads/main'

- name: Build docs (develop branch)
run: pdm run python tools/build_docs.py docs-build --version develop
if: github.event_name == 'push' && github.ref == 'refs/heads/develop'

- name: Build docs (v3.0 branch)
run: pdm run python tools/build_docs.py docs-build --version 3-dev
if: github.event_name == 'push' && github.ref == 'refs/heads/v3.0'
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/pr-merged.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ on:
types:
- closed
branches:
- develop
- main
- v3.0

jobs:
close_and_notify:
Expand All @@ -19,6 +19,9 @@ jobs:
script: |
const prNumber = context.payload.number
const branch = context.baseRef
# TODO: `develop` no longer exists. Need a new way to determine if the
# change will be introduced in a major, minor, or patch release.
# possibly conventional commit standards in the PR title or by labels?
const isDevelop = branch === "develop"
const commentBody = `<!--closing-comment-->\nThis issue has been closed in #${prNumber}. The change will be included in the upcoming ${isDevelop ? "minor" : "patch"} release.`
Expand Down
2 changes: 1 addition & 1 deletion docs/_static/versions.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{ "versions": ["1", "2", "main", "develop", "3-dev"], "latest": "2" }
{ "versions": ["1", "2", "main", "3-dev"], "latest": "2" }
3 changes: 1 addition & 2 deletions docs/release-notes/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1855,8 +1855,7 @@
- ``--schema``, to include the routes serving OpenAPI schema and docs
- ``--exclude`` to exclude routes matching a specified pattern

.. seealso::
:ref:`usage/cli:routes`
.. seealso:: Read more in the CLI :doc:`/reference/cli` section.

.. change:: Improve performance of threaded synchronous execution
:type: misc
Expand Down
346 changes: 38 additions & 308 deletions docs/usage/cli.rst

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions docs/usage/security/guards.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
Guards
======

Guards are :term:`callables <python:callable>` that receive two arguments - ``connection``, which is the
:class:`~.connection.ASGIConnection` instance, and ``route_handler``, which is a copy of the
Guards are :term:`callables <python:callable>` that receive two arguments - ``connection``, which is the :class:`Request <.connection.Request>` or :class:`WebSocket <.connection.WebSocket>` instance (both sub-classes of :class:`~.connection.ASGIConnection`), and ``route_handler``, which is a copy of the
:class:`~.handlers.BaseRouteHandler`. Their role is to *authorize* the request by verifying that
the connection is allowed to reach the endpoint handler in question. If verification fails, the guard should raise an
:exc:`HTTPException`, usually a :class:`~.exceptions.NotAuthorizedException` with a
Expand Down
2 changes: 1 addition & 1 deletion docs/usage/stores.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Built-in stores
:class:`MemoryStore <litestar.stores.memory.MemoryStore>`
A simple in-memory store, using a dictionary to hold data. This store offers no persistence and is not thread or multiprocess safe,
but it is suitable for basic applications such as caching and has generally the lowest overhead. This is the default store used by
Litestar internally. If you plan to enable :ref:`multiple web workers<cli-run-options>` and you need inter-process communication
Litestar internally. If you plan to enable :doc:`multiple web workers </reference/cli>` and you need inter-process communication
across multiple worker processes, you should use one of the other non-memory stores instead.

:class:`FileStore <litestar.stores.file.FileStore>`
Expand Down
29 changes: 15 additions & 14 deletions litestar/_kwargs/extractors.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
if TYPE_CHECKING:
from litestar._kwargs import KwargsModel
from litestar._kwargs.parameter_definition import ParameterDefinition
from litestar._kwargs.types import Extractor
from litestar.connection import ASGIConnection, Request
from litestar.dto import AbstractDTO
from litestar.typing import FieldDefinition
Expand Down Expand Up @@ -83,7 +84,7 @@ def create_connection_value_extractor(
connection_key: str,
expected_params: set[ParameterDefinition],
parser: Callable[[ASGIConnection, KwargsModel], Mapping[str, Any]] | None = None,
) -> Callable[[dict[str, Any], ASGIConnection], None]:
) -> Extractor:
"""Create a kwargs extractor function.
Args:
Expand All @@ -98,7 +99,7 @@ def create_connection_value_extractor(

alias_and_key_tuples, alias_defaults, alias_to_params = _create_param_mappings(expected_params)

def extractor(values: dict[str, Any], connection: ASGIConnection) -> None:
async def extractor(values: dict[str, Any], connection: ASGIConnection) -> None:
data = parser(connection, kwargs_model) if parser else getattr(connection, connection_key, {})

try:
Expand Down Expand Up @@ -178,7 +179,7 @@ def parse_connection_headers(connection: ASGIConnection, _: KwargsModel) -> Head
return Headers.from_scope(connection.scope)


def state_extractor(values: dict[str, Any], connection: ASGIConnection) -> None:
async def state_extractor(values: dict[str, Any], connection: ASGIConnection) -> None:
"""Extract the app state from the connection and insert it to the kwargs injected to the handler.
Args:
Expand All @@ -191,7 +192,7 @@ def state_extractor(values: dict[str, Any], connection: ASGIConnection) -> None:
values["state"] = connection.app.state._state


def headers_extractor(values: dict[str, Any], connection: ASGIConnection) -> None:
async def headers_extractor(values: dict[str, Any], connection: ASGIConnection) -> None:
"""Extract the headers from the connection and insert them to the kwargs injected to the handler.
Args:
Expand All @@ -206,7 +207,7 @@ def headers_extractor(values: dict[str, Any], connection: ASGIConnection) -> Non
values["headers"] = dict(connection.headers.items())


def cookies_extractor(values: dict[str, Any], connection: ASGIConnection) -> None:
async def cookies_extractor(values: dict[str, Any], connection: ASGIConnection) -> None:
"""Extract the cookies from the connection and insert them to the kwargs injected to the handler.
Args:
Expand All @@ -219,7 +220,7 @@ def cookies_extractor(values: dict[str, Any], connection: ASGIConnection) -> Non
values["cookies"] = connection.cookies


def query_extractor(values: dict[str, Any], connection: ASGIConnection) -> None:
async def query_extractor(values: dict[str, Any], connection: ASGIConnection) -> None:
"""Extract the query params from the connection and insert them to the kwargs injected to the handler.
Args:
Expand All @@ -232,7 +233,7 @@ def query_extractor(values: dict[str, Any], connection: ASGIConnection) -> None:
values["query"] = connection.query_params


def scope_extractor(values: dict[str, Any], connection: ASGIConnection) -> None:
async def scope_extractor(values: dict[str, Any], connection: ASGIConnection) -> None:
"""Extract the scope from the connection and insert it into the kwargs injected to the handler.
Args:
Expand All @@ -245,7 +246,7 @@ def scope_extractor(values: dict[str, Any], connection: ASGIConnection) -> None:
values["scope"] = connection.scope


def request_extractor(values: dict[str, Any], connection: ASGIConnection) -> None:
async def request_extractor(values: dict[str, Any], connection: ASGIConnection) -> None:
"""Set the connection instance as the 'request' value in the kwargs injected to the handler.
Args:
Expand All @@ -258,7 +259,7 @@ def request_extractor(values: dict[str, Any], connection: ASGIConnection) -> Non
values["request"] = connection


def socket_extractor(values: dict[str, Any], connection: ASGIConnection) -> None:
async def socket_extractor(values: dict[str, Any], connection: ASGIConnection) -> None:
"""Set the connection instance as the 'socket' value in the kwargs injected to the handler.
Args:
Expand All @@ -271,7 +272,7 @@ def socket_extractor(values: dict[str, Any], connection: ASGIConnection) -> None
values["socket"] = connection


def body_extractor(
async def body_extractor(
values: dict[str, Any],
connection: Request[Any, Any, Any],
) -> None:
Expand All @@ -287,7 +288,7 @@ def body_extractor(
Returns:
The Body value.
"""
values["body"] = connection.body()
values["body"] = await connection.body()


async def json_extractor(connection: Request[Any, Any, Any]) -> Any:
Expand Down Expand Up @@ -441,7 +442,7 @@ async def extract_url_encoded_extractor(
)


def create_data_extractor(kwargs_model: KwargsModel) -> Callable[[dict[str, Any], ASGIConnection], None]:
def create_data_extractor(kwargs_model: KwargsModel) -> Extractor:
"""Create an extractor for a request's body.
Args:
Expand Down Expand Up @@ -476,11 +477,11 @@ def create_data_extractor(kwargs_model: KwargsModel) -> Callable[[dict[str, Any]
"Callable[[ASGIConnection[Any, Any, Any, Any]], Coroutine[Any, Any, Any]]", json_extractor
)

def extractor(
async def extractor(
values: dict[str, Any],
connection: ASGIConnection[Any, Any, Any, Any],
) -> None:
values["data"] = data_extractor(connection)
values["data"] = await data_extractor(connection)

return extractor

Expand Down
15 changes: 8 additions & 7 deletions litestar/_kwargs/kwargs_model.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import annotations

from typing import TYPE_CHECKING, Any, Callable
from typing import TYPE_CHECKING, Any

from anyio import create_task_group

Expand Down Expand Up @@ -40,6 +40,7 @@


if TYPE_CHECKING:
from litestar._kwargs.types import Extractor
from litestar._signature import SignatureModel
from litestar.connection import ASGIConnection
from litestar.di import Provide
Expand Down Expand Up @@ -124,11 +125,11 @@ def __init__(
)

self.is_data_optional = is_data_optional
self.extractors = self._create_extractors()
self.extractors: list[Extractor] = self._create_extractors()
self.dependency_batches = create_dependency_batches(expected_dependencies)

def _create_extractors(self) -> list[Callable[[dict[str, Any], ASGIConnection], None]]:
reserved_kwargs_extractors: dict[str, Callable[[dict[str, Any], ASGIConnection], None]] = {
def _create_extractors(self) -> list[Extractor]:
reserved_kwargs_extractors: dict[str, Extractor] = {
"data": create_data_extractor(self),
"state": state_extractor,
"scope": scope_extractor,
Expand All @@ -140,7 +141,7 @@ def _create_extractors(self) -> list[Callable[[dict[str, Any], ASGIConnection],
"body": body_extractor, # type: ignore[dict-item]
}

extractors: list[Callable[[dict[str, Any], ASGIConnection], None]] = [
extractors: list[Extractor] = [
reserved_kwargs_extractors[reserved_kwarg] for reserved_kwarg in self.expected_reserved_kwargs
]

Expand Down Expand Up @@ -362,7 +363,7 @@ def create_for_signature_model(
sequence_query_parameter_names=sequence_query_parameter_names,
)

def to_kwargs(self, connection: ASGIConnection) -> dict[str, Any]:
async def to_kwargs(self, connection: ASGIConnection) -> dict[str, Any]:
"""Return a dictionary of kwargs. Async values, i.e. CoRoutines, are not resolved to ensure this function is
sync.
Expand All @@ -376,7 +377,7 @@ def to_kwargs(self, connection: ASGIConnection) -> dict[str, Any]:
output: dict[str, Any] = {}

for extractor in self.extractors:
extractor(output, connection)
await extractor(output, connection)

return output

Expand Down
9 changes: 9 additions & 0 deletions litestar/_kwargs/types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from __future__ import annotations

from typing import Any, Awaitable, Callable, Dict

from typing_extensions import TypeAlias

from litestar.connection import ASGIConnection

Extractor: TypeAlias = Callable[[Dict[str, Any], ASGIConnection], Awaitable[None]]
Loading

0 comments on commit 79895bb

Please sign in to comment.