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/docs/examples/contrib/sqlalchemy/sqlalchemy_declarative_models.py b/docs/examples/contrib/sqlalchemy/sqlalchemy_declarative_models.py
--- a/docs/examples/contrib/sqlalchemy/sqlalchemy_declarative_models.py
+++ b/docs/examples/contrib/sqlalchemy/sqlalchemy_declarative_models.py
@@ -22,8 +22,8 @@ class Author(UUIDBase):
 
 
 # The `AuditBase` class includes the same UUID` based primary key (`id`) and 2
-# additional columns: `created` and `updated`. `created` is a timestamp of when the
-# record created, and `updated` is the last time the record was modified.
+# additional columns: `created_at` and `updated_at`. `created_at` is a timestamp of when the
+# record created, and `updated_at` is the last time the record was modified.
 class Book(UUIDAuditBase):
     title: Mapped[str]
     author_id: Mapped[UUID] = mapped_column(ForeignKey("author.id"))
diff --git a/litestar/contrib/sqlalchemy/base.py b/litestar/contrib/sqlalchemy/base.py
--- a/litestar/contrib/sqlalchemy/base.py
+++ b/litestar/contrib/sqlalchemy/base.py
@@ -93,7 +93,7 @@ class UUIDPrimaryKey:
 
     @declared_attr
     def _sentinel(cls) -> Mapped[int]:
-        return orm_insert_sentinel()
+        return orm_insert_sentinel(name="sa_orm_sentinel")
 
 
 class BigIntPrimaryKey:
@@ -143,7 +143,7 @@ def to_dict(self, exclude: set[str] | None = None) -> dict[str, Any]:
         Returns:
             dict[str, Any]: A dict representation of the model
         """
-        exclude = {"_sentinel"}.union(self._sa_instance_state.unloaded).union(exclude or [])  # type: ignore[attr-defined]
+        exclude = {"sa_orm_sentinel", "_sentinel"}.union(self._sa_instance_state.unloaded).union(exclude or [])  # type: ignore[attr-defined]
         return {field.name: getattr(self, field.name) for field in self.__table__.columns if field.name not in exclude}
 
 
diff --git a/litestar/contrib/sqlalchemy/dto.py b/litestar/contrib/sqlalchemy/dto.py
--- a/litestar/contrib/sqlalchemy/dto.py
+++ b/litestar/contrib/sqlalchemy/dto.py
@@ -225,7 +225,7 @@ def _detect_defaults(elem: ElementType) -> tuple[Any, Any]:
             def default_factory(d: Any = sqla_default) -> Any:
                 return d.arg({})
 
-        elif sqla_default.is_sequence:
+        elif sqla_default.is_sequence or sqla_default.is_sentinel:
             # SQLAlchemy sequences represent server side defaults
             # so we cannot infer a reasonable default value for
             # them on the client side


Test patch:
diff --git a/tests/unit/test_cli/test_cli.py b/tests/unit/test_cli/test_cli.py
--- a/tests/unit/test_cli/test_cli.py
+++ b/tests/unit/test_cli/test_cli.py
@@ -45,7 +45,7 @@ def test_register_commands_from_entrypoint(mocker: "MockerFixture", runner: "Cli
     def custom_group() -> None:
         pass
 
-    @custom_group.command()  # type: ignore
+    @custom_group.command()  # type: ignore[attr-defined]
     def custom_command(app: Litestar) -> None:
         mock_command_callback()
 
diff --git a/tests/unit/test_contrib/test_sqlalchemy/test_repository/test_sqlalchemy_async.py b/tests/unit/test_contrib/test_sqlalchemy/test_repository/test_sqlalchemy_async.py
--- a/tests/unit/test_contrib/test_sqlalchemy/test_repository/test_sqlalchemy_async.py
+++ b/tests/unit/test_contrib/test_sqlalchemy/test_repository/test_sqlalchemy_async.py
@@ -12,7 +12,7 @@
 from sqlalchemy.ext.asyncio import (
     AsyncSession,
 )
-from sqlalchemy.orm import Mapped, MappedColumn, mapped_column
+from sqlalchemy.orm import InstrumentedAttribute, Mapped, mapped_column
 
 from litestar.contrib.repository.exceptions import ConflictError, RepositoryError
 from litestar.contrib.repository.filters import (
@@ -88,8 +88,8 @@ class TheBigIntModel(base.BigIntBase):
     sa_instance_mock = MagicMock()
     sa_instance_mock.unloaded = unloaded_cols
 
-    assert isinstance(AnotherModel._sentinel, MappedColumn)
-    assert isinstance(TheTestModel._sentinel, MappedColumn)
+    assert isinstance(AnotherModel._sentinel, InstrumentedAttribute)  # pyright: ignore
+    assert isinstance(TheTestModel._sentinel, InstrumentedAttribute)  # pyright: ignore
     assert not hasattr(TheBigIntModel, "_sentinel")
     model1, model2, model3 = AnotherModel(), TheTestModel(), TheBigIntModel()
     monkeypatch.setattr(model1, "_sa_instance_state", sa_instance_mock)
@@ -97,6 +97,9 @@ class TheBigIntModel(base.BigIntBase):
     monkeypatch.setattr(model3, "_sa_instance_state", sa_instance_mock)
     assert "created_at" not in model1.to_dict(exclude={"created_at"}).keys()
     assert "the_extra_col" not in model1.to_dict(exclude={"created_at"}).keys()
+    assert "sa_orm_sentinel" not in model1.to_dict().keys()
+    assert "sa_orm_sentinel" not in model2.to_dict().keys()
+    assert "sa_orm_sentinel" not in model3.to_dict().keys()
     assert "_sentinel" not in model1.to_dict().keys()
     assert "_sentinel" not in model2.to_dict().keys()
     assert "_sentinel" not in model3.to_dict().keys()
diff --git a/tests/unit/test_contrib/test_sqlalchemy/test_repository/test_sqlalchemy_sync.py b/tests/unit/test_contrib/test_sqlalchemy/test_repository/test_sqlalchemy_sync.py
--- a/tests/unit/test_contrib/test_sqlalchemy/test_repository/test_sqlalchemy_sync.py
+++ b/tests/unit/test_contrib/test_sqlalchemy/test_repository/test_sqlalchemy_sync.py
@@ -9,7 +9,7 @@
 import pytest
 from sqlalchemy import String
 from sqlalchemy.exc import IntegrityError, InvalidRequestError, SQLAlchemyError
-from sqlalchemy.orm import Mapped, MappedColumn, Session, mapped_column
+from sqlalchemy.orm import InstrumentedAttribute, Mapped, Session, mapped_column
 
 from litestar.contrib.repository.exceptions import ConflictError, RepositoryError
 from litestar.contrib.repository.filters import (
@@ -87,15 +87,18 @@ class TheBigIntModel(base.BigIntBase):
     unloaded_cols = {"the_extra_col"}
     sa_instance_mock = MagicMock()
     sa_instance_mock.unloaded = unloaded_cols
-    assert isinstance(AnotherModel._sentinel, MappedColumn)
-    assert isinstance(TheTestModel._sentinel, MappedColumn)
+    assert isinstance(AnotherModel._sentinel, InstrumentedAttribute)  # pyright: ignore
+    assert isinstance(TheTestModel._sentinel, InstrumentedAttribute)  # pyright: ignore
     assert not hasattr(TheBigIntModel, "_sentinel")
     model1, model2, model3 = AnotherModel(), TheTestModel(), TheBigIntModel()
     monkeypatch.setattr(model1, "_sa_instance_state", sa_instance_mock)
     monkeypatch.setattr(model2, "_sa_instance_state", sa_instance_mock)
     monkeypatch.setattr(model3, "_sa_instance_state", sa_instance_mock)
-    assert "created" not in model1.to_dict(exclude={"created"}).keys()
-    assert "the_extra_col" not in model1.to_dict(exclude={"created"}).keys()
+    assert "created_at" not in model1.to_dict(exclude={"created_at"}).keys()
+    assert "the_extra_col" not in model1.to_dict(exclude={"created_at"}).keys()
+    assert "sa_orm_sentinel" not in model1.to_dict().keys()
+    assert "sa_orm_sentinel" not in model2.to_dict().keys()
+    assert "sa_orm_sentinel" not in model3.to_dict().keys()
     assert "_sentinel" not in model1.to_dict().keys()
     assert "_sentinel" not in model2.to_dict().keys()
     assert "_sentinel" not in model3.to_dict().keys()