Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ repos:
rev: "v1.0.0"
hooks:
- id: sphinx-lint
- repo: https://github.com/adamchainz/blacken-docs
rev: "1.19.1"
hooks:
- id: blacken-docs
args: ["--line-length=80"]
types_or: [rst, markdown]
- repo: local
hooks:
- id: pypi-readme
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,13 @@ pip install 'litestar[standard]'
```python title="app.py"
from litestar import Litestar, get


@get("/")
async def hello_world() -> dict[str, str]:
"""Keeping the tradition alive with hello world."""
return {"hello": "world"}


app = Litestar(route_handlers=[hello_world])
```

Expand Down Expand Up @@ -285,7 +287,9 @@ from litestar.handlers.base import BaseRouteHandler
from litestar.exceptions import NotAuthorizedException


async def is_authorized(connection: ASGIConnection, handler: BaseRouteHandler) -> None:
async def is_authorized(
connection: ASGIConnection, handler: BaseRouteHandler
) -> None:
# validate authorization
# if not authorized, raise NotAuthorizedException
raise NotAuthorizedException()
Expand Down
6 changes: 5 additions & 1 deletion docs/PYPI_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,13 @@ pip install 'litestar[standard]'
```python title="app.py"
from litestar import Litestar, get


@get("/")
async def hello_world() -> dict[str, str]:
"""Keeping the tradition alive with hello world."""
return {"hello": "world"}


app = Litestar(route_handlers=[hello_world])
```

Expand Down Expand Up @@ -282,7 +284,9 @@ from litestar.handlers.base import BaseRouteHandler
from litestar.exceptions import NotAuthorizedException


async def is_authorized(connection: ASGIConnection, handler: BaseRouteHandler) -> None:
async def is_authorized(
connection: ASGIConnection, handler: BaseRouteHandler
) -> None:
# validate authorization
# if not authorized, raise NotAuthorizedException
raise NotAuthorizedException()
Expand Down
34 changes: 20 additions & 14 deletions docs/migration/fastapi.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ controller methods. The handler can then be registered on an application or rout

from fastapi import FastAPI


app = FastAPI()


Expand Down Expand Up @@ -188,9 +187,7 @@ Litestar uses the same async context manager style as FastAPI, so the code does
.. code-block:: python

@asynccontextmanager
async def lifespan(
app: FastAPI
):
async def lifespan(app: FastAPI):
# Setup code here
yield
# Teardown code here
Expand All @@ -201,9 +198,7 @@ Litestar uses the same async context manager style as FastAPI, so the code does
.. code-block:: python

@asynccontextmanager
async def lifespan(
app: Litestar
):
async def lifespan(app: Litestar):
# Setup code here
yield
# Teardown code here
Expand Down Expand Up @@ -232,8 +227,7 @@ While with FastAPI you usually set cookies on the response ``Response`` object,
.. code-block:: python

@get(response_cookies={"my-cookie": "cookie-value"})
async def handler() -> str:
...
async def handler() -> str: ...


Dependencies parameters
Expand All @@ -250,6 +244,7 @@ You can get the state either with the state kwarg in the handler or ``request.st

from fastapi import Request


async def get_arqredis(request: Request) -> ArqRedis:
return request.state.arqredis

Expand All @@ -260,6 +255,7 @@ You can get the state either with the state kwarg in the handler or ``request.st

from litestar import State


async def get_arqredis(state: State) -> ArqRedis:
return state.arqredis

Expand All @@ -279,6 +275,7 @@ In FastAPI, you pass the JSON object directly as a parameter to the endpoint, wh
class ObjectType(BaseModel):
name: str


@app.post("/items/")
async def create_item(object_name: ObjectType) -> dict[str, str]:
return {"name": object_name.name}
Expand All @@ -291,9 +288,11 @@ In FastAPI, you pass the JSON object directly as a parameter to the endpoint, wh
from litestar import Litestar, post
from pydantic import BaseModel


class ObjectType(BaseModel):
name: str


@post("/items/")
async def create_item(data: ObjectType) -> dict[str, str]:
return {"name": data.name}
Expand Down Expand Up @@ -330,9 +329,7 @@ Also FastAPI let you pass a dictionary while in Litestar you need to explicitly

@get("/uploads")
async def get_uploads(app_settings) -> Template:
return Template(
name="uploads.html", context={"debug": app_settings.debug}
)
return Template(name="uploads.html", context={"debug": app_settings.debug})

Uploads
~~~~~~~
Expand All @@ -357,9 +354,14 @@ While this is more verbose, it's also more explicit and communicates the intent
.. code-block:: python

@post("/upload/")
async def upload_file(data: Annotated[list[UploadFile], Body(media_type=RequestEncodingType.MULTI_PART)]) -> dict[str, str]:
async def upload_file(
data: Annotated[
list[UploadFile], Body(media_type=RequestEncodingType.MULTI_PART)
],
) -> dict[str, str]:
return {"file_names": [file.filename for file in data]}


app = Litestar([upload_file])


Expand All @@ -380,6 +382,7 @@ If migrating you just change your HTTPException import this will break.

app = FastAPI()


@app.get("/")
async def index() -> None:
response_fields = {"array": "value"}
Expand All @@ -395,13 +398,16 @@ If migrating you just change your HTTPException import this will break.
from litestar import Litestar, get
from litestar.exceptions import HTTPException


@get("/")
async def index() -> None:
response_fields = {"array": "value"}
raise HTTPException(
status_code=400, detail=f"can't get that field: {response_fields.get('array')}"
status_code=400,
detail=f"can't get that field: {response_fields.get('array')}",
)


app = Litestar([index])


Expand Down
26 changes: 10 additions & 16 deletions docs/migration/flask.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ Routing

from flask import Flask


app = Flask(__name__)


Expand Down Expand Up @@ -78,7 +77,6 @@ Path parameters

from flask import Flask


app = Flask(__name__)


Expand Down Expand Up @@ -147,7 +145,6 @@ the request can be accessed through an optional parameter in the handler functio

from flask import Flask, request


app = Flask(__name__)


Expand Down Expand Up @@ -275,12 +272,14 @@ in Litestar.

.. code-block:: python

from litestar import Litestar
from litestar.static_files import create_static_files_router
from litestar import Litestar
from litestar.static_files import create_static_files_router

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

.. seealso::

Expand All @@ -304,7 +303,6 @@ In addition to Jinja, Litestar supports `Mako <https://www.makotemplates.org/>`_

from flask import Flask, render_template


app = Flask(__name__)


Expand Down Expand Up @@ -332,7 +330,9 @@ In addition to Jinja, Litestar supports `Mako <https://www.makotemplates.org/>`_

app = Litestar(
[hello],
template_config=TemplateConfig(directory="templates", engine=JinjaTemplateEngine),
template_config=TemplateConfig(
directory="templates", engine=JinjaTemplateEngine
),
)


Expand All @@ -353,7 +353,6 @@ Setting cookies and headers

from flask import Flask, make_response


app = Flask(__name__)


Expand Down Expand Up @@ -416,7 +415,6 @@ For redirects, instead of ``redirect`` use ``Redirect``:

from flask import Flask, redirect, url_for


app = Flask(__name__)


Expand Down Expand Up @@ -467,7 +465,6 @@ Instead of using the ``abort`` function, raise an ``HTTPException``:

from flask import Flask, abort


app = Flask(__name__)


Expand Down Expand Up @@ -511,7 +508,6 @@ Setting status codes

from flask import Flask


app = Flask(__name__)


Expand Down Expand Up @@ -558,7 +554,6 @@ the data returned is intended to be serialized into JSON and will do so unless t

from flask import Flask, Response


app = Flask(__name__)


Expand Down Expand Up @@ -617,7 +612,6 @@ Error handling
from flask import Flask
from werkzeug.exceptions import HTTPException


app = Flask(__name__)


Expand Down
18 changes: 14 additions & 4 deletions docs/release-notes/2.x-changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -276,9 +276,11 @@
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
Expand Down Expand Up @@ -449,7 +451,9 @@
.. code-block:: python

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


Expand Down Expand Up @@ -724,7 +728,9 @@

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

Expand Down Expand Up @@ -1190,7 +1196,9 @@
bars: list[Bar]


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


.. changelog:: 2.3.2
Expand Down Expand Up @@ -1777,7 +1785,9 @@
.. code-block:: python

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

Expand Down
1 change: 1 addition & 0 deletions docs/release-notes/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@

from typing import ReadOnly, TypedDict


class User(TypedDict):
id: ReadOnly[int]

Expand Down
Loading
Loading