Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor!: Remove deprecated StaticFileConfig #3357

Merged
merged 10 commits into from
Apr 10, 2024
Merged
8 changes: 0 additions & 8 deletions docs/examples/static_files/upgrade_from_static_1.py

This file was deleted.

8 changes: 0 additions & 8 deletions docs/examples/static_files/upgrade_from_static_2.py

This file was deleted.

6 changes: 3 additions & 3 deletions docs/release-notes/2.x-changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -423,15 +423,15 @@

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
:class:`~litestar.static_files.StaticFilesConfig` to maintain backwards
`litestar.static_files.StaticFilesConfig`` to maintain backwards
compatibility.

This achieves a few things:

- Fixes https:/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 :meth:`~litestar.app.Litestar.url_for_static_asset`
- 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:
Expand Down Expand Up @@ -1943,7 +1943,7 @@
:pr: 2154

Fixed a bug that would result in a ``404 - Not Found`` when requesting a static
file where the :attr:`~litestar.static_files.StaticFilesConfig.path` was also
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``
Expand Down
2 changes: 1 addition & 1 deletion docs/release-notes/whats-new-2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ Imports
+----------------------------------------------------+------------------------------------------------------------------------+
| ``starlite.OpenAPIConfig`` | :class:`.openapi.OpenAPIConfig` |
+----------------------------------------------------+------------------------------------------------------------------------+
| ``starlite.StaticFilesConfig`` | :class:`.static_files.config.StaticFilesConfig` |
| ``starlite.StaticFilesConfig`` | ``.static_files.config.StaticFilesConfig`` |
+----------------------------------------------------+------------------------------------------------------------------------+
| ``starlite.TemplateConfig`` | :class:`.template.TemplateConfig` |
+----------------------------------------------------+------------------------------------------------------------------------+
Expand Down
18 changes: 18 additions & 0 deletions docs/release-notes/whats-new-3.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,24 @@ Imports
+----------------------------------------------------+------------------------------------------------------------------------+



Removal of ``StaticFileConfig``
-------------------------------

The ``StaticFilesConfig`` has been removed, alongside these related parameters and
functions:

- ``Litestar.static_files_config``
- ``Litestar.url_for_static_asset``
- ``Request.url_for_static_asset``

:func:`create_static_files_router` is a drop-in replacement for ``StaticFilesConfig``,
and can simply be added to the ``route_handlers`` like any other regular handler.

Usage of ``url_for_static_assets`` should be replaced with a ``url_for("static", ...)``
call.


Other Changes
-------------

Expand Down
17 changes: 0 additions & 17 deletions docs/usage/static-files.rst
Original file line number Diff line number Diff line change
Expand Up @@ -94,20 +94,3 @@ with support for popular cloud providers available via 3rd party implementations
.. literalinclude:: /examples/static_files/file_system.py
:caption: Using a custom file system with
:func:`create_static_files_router`

Upgrading from legacy StaticFilesConfig
---------------------------------------

.. deprecated:: v3.0
:class:`StaticFilesConfig` is deprecated and will be removed in Litestar 3.0

Existing code can be upgraded to :func:`create_static_files_router` by replacing
:class:`StaticFilesConfig` instances with this function call and passing the result to
``route_handlers`` instead of ``static_files_config``:

.. literalinclude:: /examples/static_files/upgrade_from_static_1.py
:caption: Using the deprecated :class:`~.static_files.config.StaticFilesConfig`

.. literalinclude:: /examples/static_files/upgrade_from_static_2.py
:caption: Upgrading from :class:`~.static_files.config.StaticFilesConfig` to
:func:`create_static_files_router`
7 changes: 4 additions & 3 deletions docs/usage/templating.rst
Original file line number Diff line number Diff line change
Expand Up @@ -380,9 +380,10 @@ Built-in callables
if you wish to insert the ``csrf_token`` into non-HTML based templates, or insert it into HTML templates not using a hidden input field but
by some other means, for example inside a special ``<meta>`` tag.

``url_for_static_asset``
URLs for static files can be created using the ``url_for_static_asset`` function. It's signature and behaviour are identical to
:meth:`app.url_for_static_asset <litestar.app.Litestar.url_for_static_asset>`.
``url_for`` for static files
For static file serving as provided by :func:`~litestar.static_files.create_static_files_router`,
``url_for`` can be used with the ``static`` handler name: ``url_for("static", file_name="style.css")``



Registering template callables
Expand Down
1 change: 0 additions & 1 deletion litestar/_asgi/routing_trie/mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ def add_mount_route(
current_node = current_node.children[component] # type: ignore[index]

current_node.is_mount = True
current_node.is_static = route.route_handler.is_static

if route.path != "/":
mount_routes[route.path] = root_node.children[route.path] = current_node
Expand Down
3 changes: 1 addition & 2 deletions litestar/_asgi/routing_trie/traversal.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,7 @@ def parse_path_to_route(
if not children or all(sub_route not in path for sub_route in children): # type: ignore[operator]
asgi_app, handler = parse_node_handlers(node=mount_node, method=method)
remaining_path = remaining_path or "/"
if not mount_node.is_static:
remaining_path = remaining_path if remaining_path.endswith("/") else f"{remaining_path}/"
remaining_path = remaining_path if remaining_path.endswith("/") else f"{remaining_path}/"
return asgi_app, handler, remaining_path, {}

node, path_parameters, path = traverse_route_map(
Expand Down
4 changes: 0 additions & 4 deletions litestar/_asgi/routing_trie/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ class RouteTrieNode:
"children",
"is_asgi",
"is_mount",
"is_static",
"is_path_param_node",
"is_path_type",
"path_parameters",
Expand All @@ -56,8 +55,6 @@ class RouteTrieNode:
"""Designate the node as having an `asgi` type handler."""
is_mount: bool
"""Designate the node as being a mount route."""
is_static: bool
"""Designate the node as being a static mount route."""
path_parameters: dict[Method | Literal["websocket"] | Literal["asgi"], tuple[PathParameterDefinition, ...]]
"""A list of tuples containing path parameter definitions.

Expand All @@ -79,7 +76,6 @@ def create_node() -> RouteTrieNode:
is_path_param_node=False,
is_asgi=False,
is_mount=False,
is_static=False,
is_path_type=False,
path_parameters={},
)
59 changes: 0 additions & 59 deletions litestar/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
from litestar.plugins.base import CLIPlugin
from litestar.router import Router
from litestar.routes import ASGIRoute, HTTPRoute, WebSocketRoute
from litestar.static_files.base import StaticFiles
from litestar.stores.registry import StoreRegistry
from litestar.types import Empty, TypeDecodersSequence
from litestar.types.internal_types import PathParameterDefinition, TemplateConfigType
Expand All @@ -67,13 +66,11 @@
from litestar.openapi.spec import SecurityRequirement
from litestar.openapi.spec.open_api import OpenAPI
from litestar.response import Response
from litestar.static_files.config import StaticFilesConfig
from litestar.stores.base import Store
from litestar.types import (
AfterExceptionHookHandler,
AfterRequestHookHandler,
AfterResponseHookHandler,
AnyCallable,
ASGIApp,
BeforeMessageSendHookHandler,
BeforeRequestHookHandler,
Expand Down Expand Up @@ -139,7 +136,6 @@ class Litestar(Router):
"_server_lifespan_managers",
"_debug",
"_openapi_schema",
"_static_files_config",
"plugins",
"after_exception",
"allowed_hosts",
Expand Down Expand Up @@ -210,7 +206,6 @@ def __init__(
signature_namespace: Mapping[str, Any] | None = None,
signature_types: Sequence[Any] | None = None,
state: State | None = None,
static_files_config: Sequence[StaticFilesConfig] | None = None,
stores: StoreRegistry | dict[str, Store] | None = None,
tags: Sequence[str] | None = None,
template_config: TemplateConfigType | None = None,
Expand Down Expand Up @@ -302,7 +297,6 @@ def __init__(
signature_types: A sequence of types for use in forward reference resolution during signature modeling.
These types will be added to the signature namespace using their ``__name__`` attribute.
state: An optional :class:`State <.datastructures.State>` for application state.
static_files_config: A sequence of :class:`StaticFilesConfig <.static_files.StaticFilesConfig>`
stores: Central registry of :class:`Store <.stores.base.Store>` that will be available throughout the
application. If this is a dictionary to it will be passed to a
:class:`StoreRegistry <.stores.registry.StoreRegistry>`. If it is a
Expand Down Expand Up @@ -370,7 +364,6 @@ def __init__(
signature_namespace=dict(signature_namespace or {}),
signature_types=list(signature_types or []),
state=state or State(),
static_files_config=list(static_files_config or []),
stores=stores,
tags=list(tags or []),
template_config=template_config,
Expand Down Expand Up @@ -429,7 +422,6 @@ def __init__(
self.request_class: type[Request] = config.request_class or Request
self.response_cache_config = config.response_cache_config
self.state = config.state
self._static_files_config = config.static_files_config
self.template_engine = config.template_config.engine_instance if config.template_config else None
self.websocket_class: type[WebSocket] = config.websocket_class or WebSocket
self.debug = config.debug
Expand Down Expand Up @@ -486,16 +478,8 @@ def __init__(
self.get_logger = self.logging_config.configure()
self.logger = self.get_logger("litestar")

for static_config in self._static_files_config:
self.register(static_config.to_static_files_app())

self.asgi_handler = self._create_asgi_handler()

@property
@deprecated(version="2.6.0", kind="property", info="Use create_static_files router instead")
def static_files_config(self) -> list[StaticFilesConfig]:
return self._static_files_config

@property
@deprecated(version="2.0", alternative="Litestar.plugins.cli", kind="property")
def cli_plugins(self) -> list[CLIPluginProtocol]:
Expand Down Expand Up @@ -779,49 +763,6 @@ def get_membership_details(group_id: int, user_id: int) -> None:

return join_paths(output)

@deprecated(
"2.6.0", info="Use create_static_files router instead of StaticFilesConfig, which works with route_reverse"
)
def url_for_static_asset(self, name: str, file_path: str) -> str:
"""Receives a static files handler name, an asset file path and returns resolved url path to the asset.

Examples:
.. code-block:: python

from litestar import Litestar
from litestar.static_files.config import StaticFilesConfig

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

path = app.url_for_static_asset("css", "main.css")

# /static/css/main.css

Args:
name: A static handler unique name.
file_path: a string containing path to an asset.

Raises:
NoRouteMatchFoundException: If static files handler with ``name`` does not exist.

Returns:
A url path to the asset.
"""

handler_index = self.get_handler_index_by_name(name)
if handler_index is None:
raise NoRouteMatchFoundException(f"Static handler {name} can not be found")

handler_fn = cast("AnyCallable", handler_index["handler"].fn)
if not isinstance(handler_fn, StaticFiles):
raise NoRouteMatchFoundException(f"Handler with name {name} is not a static files handler")

return join_paths([handler_index["paths"][0], file_path]) # type: ignore[unreachable]

@property
def route_handler_method_view(self) -> dict[str, list[str]]:
"""Map route handlers to paths.
Expand Down
9 changes: 0 additions & 9 deletions litestar/cli/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,15 +382,6 @@ def show_app_info(app: Litestar) -> None: # pragma: no cover
if app.template_engine:
table.add_row("Template engine", type(app.template_engine).__name__)

if app.static_files_config:
static_files_configs = app.static_files_config
static_files_info = [
f"path=[yellow]{static_files.path}[/] dirs=[yellow]{', '.join(map(str, static_files.directories))}[/] "
f"html_mode={_format_is_enabled(static_files.html_mode)}"
for static_files in static_files_configs
]
table.add_row("Static files", "\n".join(static_files_info))

middlewares = []
for middleware in app.middleware:
updated_middleware = middleware.middleware if isinstance(middleware, DefineMiddleware) else middleware
Expand Down
3 changes: 0 additions & 3 deletions litestar/config/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
from litestar.openapi.config import OpenAPIConfig
from litestar.openapi.spec import SecurityRequirement
from litestar.plugins import PluginProtocol
from litestar.static_files.config import StaticFilesConfig
from litestar.stores.base import Store
from litestar.stores.registry import StoreRegistry
from litestar.types import (
Expand Down Expand Up @@ -193,8 +192,6 @@ class AppConfig:
"""
state: State = field(default_factory=State)
"""A :class:`State` <.datastructures.State>` instance holding application state."""
static_files_config: list[StaticFilesConfig] = field(default_factory=list)
"""An instance or list of :class:`StaticFilesConfig <.static_files.StaticFilesConfig>`."""
stores: StoreRegistry | dict[str, Store] | None = None
"""Central registry of :class:`Store <.stores.base.Store>` to be made available and be used throughout the
application. Can be either a dictionary mapping strings to :class:`Store <.stores.base.Store>` instances, or an
Expand Down
18 changes: 0 additions & 18 deletions litestar/connection/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,21 +325,3 @@ def url_for(self, name: str, **path_parameters: Any) -> str:
url_path = litestar_instance.route_reverse(name, **path_parameters)

return make_absolute_url(url_path, self.base_url)

def url_for_static_asset(self, name: str, file_path: str) -> str:
"""Receives a static files handler name, an asset file path and returns resolved absolute url to the asset.

Args:
name: A static handler unique name.
file_path: a string containing path to an asset.

Raises:
NoRouteMatchFoundException: If static files handler with ``name`` does not exist.

Returns:
A string representing absolute url to the asset.
"""
litestar_instance = self.scope["app"]
url_path = litestar_instance.url_for_static_asset(name, file_path)

return make_absolute_url(url_path, self.base_url)
2 changes: 0 additions & 2 deletions litestar/contrib/jinja.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
TemplateEngineProtocol,
csrf_token,
url_for,
url_for_static_asset,
)

try:
Expand Down Expand Up @@ -53,7 +52,6 @@ def __init__(
self.engine = Environment(loader=loader, autoescape=True)
elif engine_instance:
self.engine = engine_instance
self.register_template_callable(key="url_for_static_asset", template_callable=url_for_static_asset)
self.register_template_callable(key="csrf_token", template_callable=csrf_token)
self.register_template_callable(key="url_for", template_callable=url_for)

Expand Down
2 changes: 0 additions & 2 deletions litestar/contrib/mako.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
TemplateProtocol,
csrf_token,
url_for,
url_for_static_asset,
)

try:
Expand Down Expand Up @@ -83,7 +82,6 @@ def __init__(self, directory: Path | list[Path] | None = None, engine_instance:
self.engine = engine_instance

self._template_callables: list[tuple[str, TemplateCallableType]] = []
self.register_template_callable(key="url_for_static_asset", template_callable=url_for_static_asset)
self.register_template_callable(key="csrf_token", template_callable=csrf_token)
self.register_template_callable(key="url_for", template_callable=url_for)

Expand Down
2 changes: 0 additions & 2 deletions litestar/contrib/minijinja.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
TemplateProtocol,
csrf_token,
url_for,
url_for_static_asset,
)
from litestar.utils.deprecation import warn_deprecation

Expand Down Expand Up @@ -142,7 +141,6 @@ def _loader(name: str) -> str:

self.register_template_callable("url_for", _transform_state(url_for))
self.register_template_callable("csrf_token", _transform_state(csrf_token))
self.register_template_callable("url_for_static_asset", _transform_state(url_for_static_asset))

def get_template(self, template_name: str) -> MiniJinjaTemplate:
"""Retrieve a template by matching its name (dotted path) with files in the directory or directories provided.
Expand Down
Loading
Loading