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/starlite/app.py b/starlite/app.py
--- a/starlite/app.py
+++ b/starlite/app.py
@@ -801,7 +801,7 @@ def update_openapi_schema(self) -> None:
                         )
                     operation_ids.append(operation_id)
 
-    async def emit(self, event_id: str, *args: Any, **kwargs: Any) -> None:
+    def emit(self, event_id: str, *args: Any, **kwargs: Any) -> None:
         """Emit an event to all attached listeners.
 
         Args:
@@ -812,4 +812,4 @@ async def emit(self, event_id: str, *args: Any, **kwargs: Any) -> None:
         Returns:
             None
         """
-        await self.event_emitter.emit(event_id, *args, **kwargs)
+        self.event_emitter.emit(event_id, *args, **kwargs)
diff --git a/starlite/events/emitter.py b/starlite/events/emitter.py
--- a/starlite/events/emitter.py
+++ b/starlite/events/emitter.py
@@ -36,7 +36,7 @@ def __init__(self, listeners: Sequence[EventListener]):
                 self.listeners[event_id].add(listener)
 
     @abstractmethod
-    async def emit(self, event_id: str, *args: Any, **kwargs: Any) -> None:  # pragma: no cover
+    def emit(self, event_id: str, *args: Any, **kwargs: Any) -> None:  # pragma: no cover
         """Emit an event to all attached listeners.
 
         Args:
@@ -126,7 +126,7 @@ async def on_shutdown(self) -> None:
         self._worker_task = None
         self._queue = None
 
-    async def emit(self, event_id: str, *args: Any, **kwargs: Any) -> None:
+    def emit(self, event_id: str, *args: Any, **kwargs: Any) -> None:
         """Emit an event to all attached listeners.
 
         Args:


Test patch:
diff --git a/tests/events/test_listener.py b/tests/events/test_listener.py
--- a/tests/events/test_listener.py
+++ b/tests/events/test_listener.py
@@ -1,4 +1,4 @@
-from asyncio import sleep
+from time import sleep
 from typing import Any
 from unittest.mock import MagicMock
 
@@ -10,7 +10,7 @@
 from starlite.events.listener import EventListener, listener
 from starlite.exceptions import ImproperlyConfiguredException
 from starlite.status_codes import HTTP_200_OK
-from starlite.testing import create_async_test_client, create_test_client
+from starlite.testing import create_test_client
 
 
 @pytest.fixture()
@@ -37,17 +37,17 @@ async def listener_fn(*args: Any, **kwargs: Any) -> None:
 
 
 @pytest.mark.parametrize("listener", [lazy_fixture("sync_listener"), lazy_fixture("async_listener")])
-async def test_event_listener(mock: MagicMock, listener: EventListener) -> None:
+def test_event_listener(mock: MagicMock, listener: EventListener) -> None:
     test_value = {"key": "123"}
 
     @get("/")
-    async def route_handler(request: Request[Any, Any, Any]) -> None:
-        await request.app.emit("test_event", test_value)
+    def route_handler(request: Request[Any, Any, Any]) -> None:
+        request.app.emit("test_event", test_value)
 
     with create_test_client(route_handlers=[route_handler], listeners=[listener]) as client:
         response = client.get("/")
         assert response.status_code == HTTP_200_OK
-        await sleep(0.01)
+        sleep(0.01)
         mock.assert_called_with(test_value)
 
 
@@ -56,50 +56,46 @@ async def test_shutdown_awaits_pending(async_listener: EventListener, mock: Magi
     await emitter.on_startup()
 
     for _ in range(100):
-        await emitter.emit("test_event")
+        emitter.emit("test_event")
 
     await emitter.on_shutdown()
 
     assert mock.call_count == 100
 
 
-async def test_multiple_event_listeners(
-    async_listener: EventListener, sync_listener: EventListener, mock: MagicMock
-) -> None:
+def test_multiple_event_listeners(async_listener: EventListener, sync_listener: EventListener, mock: MagicMock) -> None:
     @get("/")
-    async def route_handler(request: Request[Any, Any, Any]) -> None:
-        await request.app.emit("test_event")
-
-    async with create_async_test_client(
-        route_handlers=[route_handler], listeners=[async_listener, sync_listener]
-    ) as client:
-        response = await client.get("/")
-        await sleep(0.01)
+    def route_handler(request: Request[Any, Any, Any]) -> None:
+        request.app.emit("test_event")
+
+    with create_test_client(route_handlers=[route_handler], listeners=[async_listener, sync_listener]) as client:
+        response = client.get("/")
+        sleep(0.01)
         assert response.status_code == HTTP_200_OK
         assert mock.call_count == 2
 
 
-async def test_multiple_event_ids(mock: MagicMock) -> None:
+def test_multiple_event_ids(mock: MagicMock) -> None:
     @listener("test_event_1", "test_event_2")
     def event_handler() -> None:
         mock()
 
     @get("/{event_id:int}")
-    async def route_handler(request: Request[Any, Any, Any], event_id: int) -> None:
-        await request.app.emit(f"test_event_{event_id}")
+    def route_handler(request: Request[Any, Any, Any], event_id: int) -> None:
+        request.app.emit(f"test_event_{event_id}")
 
-    async with create_async_test_client(route_handlers=[route_handler], listeners=[event_handler]) as client:
-        response = await client.get("/1")
-        await sleep(0.01)
+    with create_test_client(route_handlers=[route_handler], listeners=[event_handler]) as client:
+        response = client.get("/1")
+        sleep(0.01)
         assert response.status_code == HTTP_200_OK
         assert mock.call_count == 1
-        response = await client.get("/2")
-        await sleep(0.01)
+        response = client.get("/2")
+        sleep(0.01)
         assert response.status_code == HTTP_200_OK
         assert mock.call_count == 2
 
 
-def test_raises_when_decorator_called_without_callable() -> None:
+async def test_raises_when_decorator_called_without_callable() -> None:
     with pytest.raises(ImproperlyConfiguredException):
         listener("test_even")(True)  # type: ignore
 
@@ -108,18 +104,18 @@ async def test_raises_when_not_initialized() -> None:
     app = Starlite([])
 
     with pytest.raises(ImproperlyConfiguredException):
-        await app.emit("x")
+        app.emit("x")
 
 
 async def test_raises_for_wrong_async_backend(async_listener: EventListener) -> None:
-    async with create_async_test_client([], listeners=[async_listener], backend="trio") as client:
+    with create_test_client([], listeners=[async_listener], backend="trio") as client:
         assert not client.app.event_emitter._queue
         assert not client.app.event_emitter._worker_task
         with pytest.raises(ImproperlyConfiguredException):
-            await client.app.emit("test_event")
+            client.app.emit("test_event")
 
 
 async def test_raises_when_not_listener_are_registered_for_an_event_id(async_listener: EventListener) -> None:
-    async with create_async_test_client(route_handlers=[], listeners=[async_listener]) as client:
+    with create_test_client(route_handlers=[], listeners=[async_listener]) as client:
         with pytest.raises(ImproperlyConfiguredException):
-            await client.app.emit("x")
+            client.app.emit("x")