Repository: litestar-org/litestar

Issue:
StaticFilesConfig and virtual directories
I'm trying to write a ``FileSystemProtocol`` to load files from the package data using [importlib_resources](https://importlib-resources.readthedocs.io/en/latest/using.html#). But because ``directories`` is defined as ``DirectoryPath``, pydantic checks if the given directories exist in the local filesystem. 

This is not generally true, especially in any kind of virtual filesystem (e.g. a zipped package). I think this condition should be relaxed to support virtual filesystems.

https://github.com/starlite-api/starlite/blob/9bb6dcd57c10a591377cf8e3a537e9292566d5b9/starlite/config/static_files.py#L32


Discussion:
I agree. Do you want to submit a PR?

Resolving patch:
diff --git a/litestar/types/callable_types.py b/litestar/types/callable_types.py
--- a/litestar/types/callable_types.py
+++ b/litestar/types/callable_types.py
@@ -1,15 +1,6 @@
 from __future__ import annotations
 
-from typing import (
-    TYPE_CHECKING,
-    Any,
-    AsyncGenerator,
-    Awaitable,
-    Callable,
-    Generator,
-    List,
-    Union,
-)
+from typing import TYPE_CHECKING, Any, AsyncGenerator, Awaitable, Callable, Generator
 
 if TYPE_CHECKING:
     from typing_extensions import TypeAlias
@@ -25,43 +16,23 @@
     from litestar.types.internal_types import LitestarType, PathParameterDefinition
     from litestar.types.protocols import Logger
 
-    AfterExceptionHookHandler: TypeAlias = Callable[[Exception, Scope], SyncOrAsyncUnion[None]]
-    AfterRequestHookHandler: TypeAlias = Union[
-        Callable[[ASGIApp], SyncOrAsyncUnion[ASGIApp]], Callable[[Response], SyncOrAsyncUnion[Response]]
-    ]
-    AfterResponseHookHandler: TypeAlias = Callable[[Request], SyncOrAsyncUnion[None]]
-    AsyncAnyCallable: TypeAlias = Callable[..., Awaitable[Any]]
-    AnyCallable: TypeAlias = Callable[..., Any]
-    AnyGenerator: TypeAlias = Union[Generator[Any, Any, Any], AsyncGenerator[Any, Any]]
-    BeforeMessageSendHookHandler: TypeAlias = Callable[[Message, Scope], SyncOrAsyncUnion[None]]
-    BeforeRequestHookHandler: TypeAlias = Callable[[Request], Union[Any, Awaitable[Any]]]
-    CacheKeyBuilder: TypeAlias = Callable[[Request], str]
-    ExceptionHandler: TypeAlias = Callable[[Request, Exception], Response]
-    ExceptionLoggingHandler: TypeAlias = Callable[[Logger, Scope, List[str]], None]
-    GetLogger: TypeAlias = Callable[..., Logger]
-    Guard: TypeAlias = Callable[[ASGIConnection, BaseRouteHandler], SyncOrAsyncUnion[None]]
-    LifespanHook: TypeAlias = Union[
-        Callable[[LitestarType], SyncOrAsyncUnion[Any]],
-        Callable[[], SyncOrAsyncUnion[Any]],
-    ]
-    OnAppInitHandler: TypeAlias = Callable[[AppConfig], AppConfig]
-    OperationIDCreator: TypeAlias = Callable[[HTTPRouteHandler, Method, List[Union[str, PathParameterDefinition]]], str]
-    Serializer: TypeAlias = Callable[[Any], Any]
-else:
-    AfterExceptionHookHandler: TypeAlias = Any
-    AfterRequestHookHandler: TypeAlias = Any
-    AfterResponseHookHandler: TypeAlias = Any
-    AsyncAnyCallable: TypeAlias = Any
-    AnyCallable: TypeAlias = Any
-    AnyGenerator: TypeAlias = Any
-    BeforeMessageSendHookHandler: TypeAlias = Any
-    BeforeRequestHookHandler: TypeAlias = Any
-    CacheKeyBuilder: TypeAlias = Any
-    ExceptionHandler: TypeAlias = Any
-    ExceptionLoggingHandler: TypeAlias = Any
-    GetLogger: TypeAlias = Any
-    Guard: TypeAlias = Any
-    LifespanHook: TypeAlias = Any
-    OnAppInitHandler: TypeAlias = Any
-    OperationIDCreator: TypeAlias = Any
-    Serializer: TypeAlias = Any
+
+AfterExceptionHookHandler: TypeAlias = "Callable[[Exception, Scope], SyncOrAsyncUnion[None]]"
+AfterRequestHookHandler: TypeAlias = (
+    "Callable[[ASGIApp], SyncOrAsyncUnion[ASGIApp]] | Callable[[Response], SyncOrAsyncUnion[Response]]"
+)
+AfterResponseHookHandler: TypeAlias = "Callable[[Request], SyncOrAsyncUnion[None]]"
+AsyncAnyCallable: TypeAlias = Callable[..., Awaitable[Any]]
+AnyCallable: TypeAlias = Callable[..., Any]
+AnyGenerator: TypeAlias = "Generator[Any, Any, Any] | AsyncGenerator[Any, Any]"
+BeforeMessageSendHookHandler: TypeAlias = "Callable[[Message, Scope], SyncOrAsyncUnion[None]]"
+BeforeRequestHookHandler: TypeAlias = "Callable[[Request], Any | Awaitable[Any]]"
+CacheKeyBuilder: TypeAlias = "Callable[[Request], str]"
+ExceptionHandler: TypeAlias = "Callable[[Request, Exception], Response]"
+ExceptionLoggingHandler: TypeAlias = "Callable[[Logger, Scope, list[str]], None]"
+GetLogger: TypeAlias = "Callable[..., Logger]"
+Guard: TypeAlias = "Callable[[ASGIConnection, BaseRouteHandler], SyncOrAsyncUnion[None]]"
+LifespanHook: TypeAlias = "Callable[[LitestarType], SyncOrAsyncUnion[Any]] | Callable[[], SyncOrAsyncUnion[Any]]"
+OnAppInitHandler: TypeAlias = "Callable[[AppConfig], AppConfig]"
+OperationIDCreator: TypeAlias = "Callable[[HTTPRouteHandler, Method, list[str | PathParameterDefinition]], str]"
+Serializer: TypeAlias = Callable[[Any], Any]
diff --git a/litestar/types/internal_types.py b/litestar/types/internal_types.py
--- a/litestar/types/internal_types.py
+++ b/litestar/types/internal_types.py
@@ -1,14 +1,6 @@
 from __future__ import annotations
 
-from typing import (
-    TYPE_CHECKING,
-    Any,
-    Callable,
-    Dict,
-    Literal,
-    NamedTuple,
-    Union,
-)
+from typing import TYPE_CHECKING, Any, Callable, Literal, NamedTuple
 
 __all__ = (
     "ControllerRouterHandler",
@@ -34,19 +26,12 @@
     from litestar.router import Router
     from litestar.types import Method
 
-    ReservedKwargs: TypeAlias = Literal["request", "socket", "headers", "query", "cookies", "state", "data"]
-    LitestarType: TypeAlias = Litestar
-    RouteHandlerType: TypeAlias = Union[HTTPRouteHandler, WebsocketRouteHandler, ASGIRouteHandler]
-    ResponseType: TypeAlias = type[Response]
-    ControllerRouterHandler: TypeAlias = Union[type[Controller], RouteHandlerType, Router, Callable[..., Any]]
-    RouteHandlerMapItem: TypeAlias = Dict[Union[Method, Literal["websocket", "asgi"]], RouteHandlerType]
-else:
-    ReservedKwargs: TypeAlias = Any
-    LitestarType: TypeAlias = Any
-    RouteHandlerType: TypeAlias = Any
-    ResponseType: TypeAlias = Any
-    ControllerRouterHandler: TypeAlias = Any
-    RouteHandlerMapItem: TypeAlias = Any
+ReservedKwargs: TypeAlias = Literal["request", "socket", "headers", "query", "cookies", "state", "data"]
+LitestarType: TypeAlias = "Litestar"
+RouteHandlerType: TypeAlias = "HTTPRouteHandler | WebsocketRouteHandler | ASGIRouteHandler"
+ResponseType: TypeAlias = "type[Response]"
+ControllerRouterHandler: TypeAlias = "type[Controller] | RouteHandlerType | Router | Callable[..., Any]"
+RouteHandlerMapItem: TypeAlias = 'dict[Method | Literal["websocket", "asgi"], RouteHandlerType]'
 
 
 class PathParameterDefinition(NamedTuple):


Test patch: