prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Bug: pydantic validations aren't being handled by DTOs
  ### Description
  
  In the documentation of Litestar we have:
  
  > When a value fails pydantic validation, the result will be a ValidationException with the extra key set to the pydantic validation errors. Thus, this data will be made available for the API consumers by default.
  
  But when combined with DTO's in a post request, if a pydantic validation fails the exception is not handled and the client receives an InternalServerError (500) instead of a BadRequest (400):
  
  
  ```
      __pydantic_self__.__pydantic_validator__.validate_python(data, self_instance=__pydantic_self__)
  pydantic_core._pydantic_core.ValidationError: 1 validation error for User
  name
    String should have at most 2 characters [type=string_too_long, input_value='abc', input_type=str]
      For further information visit https://errors.pydantic.dev/2.2/v/string_too_long
  
  Status code: 500
  ```
  
  If the validation isn't handled by pydantic (or at least it isn't handled **first** by pydantic) it works, for example an Enum validation returns a proper 400 status code because `msgspec` catches it first:
  
  ```python
  from enum import Enum
  
  class NameEnum(str, Enum):
      a = "A"
      b = "B"
  
  # (replace the User class of the example with this)
  class User(BaseModel):
      name: NameEnum
  ```
  
  Output for incorrect Enum:
  
  ```
    File ".../.venv/lib64/python3.11/site-packages/litestar/serialization/msgspec_hooks.py", line 191, in decode_json
      raise SerializationException(str(msgspec_error)) from msgspec_error
  litestar.exceptions.base_exceptions.SerializationException: Invalid enum value 'abc' - at `$.name`
  
  
  ...
  
    File ".../.venv/lib64/python3.11/site-packages/litestar/routes/http.py", line 186, in _get_response_data
      raise ClientException(str(e)) from e
  litestar.exceptions.http_exceptions.ClientException: 400: Invalid enum value 'abc' - at `$.name`
  ```
  
  ### URL to code causing the issue
  
  _No response_
  
  ### MCVE
  
  ```python
  from litestar import Litestar, post
  from litestar.contrib.pydantic import PydanticDTO
  from litestar.testing import TestClient
  from pydantic import BaseModel, Field
  
  
  class User(BaseModel):
      name: str = Field(max_length=2)
  
  
  UserDTO = PydanticDTO[User]
  
  
  @post("/user", dto=UserDTO, sync_to_thread=False)
  def create_user(data: User) -> User:
      return data
  
  
  with TestClient(Litestar([create_user], debug=True)) as client:
      response = client.post("/user", json={"name": "abc"})
      print(response.text)
      print(f"Status code: {response.status_code}")
      assert response.status_code == 201
  ```
  
  
  ### Steps to reproduce
  
  ```bash
  1. Execute the MCVE
  ```
  
  
  ### Screenshots
  
  _No response_
  
  ### Logs
  
  _No response_
  
  ### Litestar Version
  
  2.0.0rc1
  
  ### Platform
  
  - [X] Linux
  - [ ] Mac
  - [ ] Windows
  - [ ] Other (Please specify in the description above)
  
  <!-- POLAR PLEDGE BADGE START -->
  ---
  
  ## Funding
  * If you would like to see an issue prioritized, make a pledge towards it!
  * We receive the pledge once the issue is completed & verified
  
  <a href="https://polar.sh/litestar-org/litestar/issues/2190">
  <picture>
    <source media="(prefers-color-scheme: dark)" srcset="https://polar.sh/api/github/litestar-org/litestar/issues/2190/pledge.svg?darkmode=1">
    <img alt="Fund with Polar" src="https://polar.sh/api/github/litestar-org/litestar/issues/2190/pledge.svg">
  </picture>
  </a>
  <!-- POLAR PLEDGE BADGE END -->
  
  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
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `litestar/contrib/pydantic/pydantic_dto_factory.py`
  Content:
  ```
  1 from __future__ import annotations
  2 
  3 from dataclasses import replace
  4 from typing import TYPE_CHECKING, Collection, Generic, TypeVar
  5 
  6 from litestar.dto.base_dto import AbstractDTO
  7 from litestar.dto.data_structures import DTOFieldDefinition
  8 from litestar.dto.field import DTO_FIELD_META_KEY, DTOField
  9 from litestar.exceptions import MissingDependencyException
  10 from litestar.types.empty import Empty
  11 
  12 if TYPE_CHECKING:
  13     from typing import Generator
  14 
  15     from litestar.typing import FieldDefinition
  16 
  17 
  18 try:
  19     import pydantic
  20 
  21     if pydantic.VERSION.startswith("2"):
  22         from pydantic_core import PydanticUndefined
  23     else:  # pragma: no cover
  24         from pydantic.fields import Undefined as PydanticUndefined  # type: ignore
  25 except ImportError as e:
  26     raise MissingDependencyException("pydantic") from e
  27 
  28 __all__ = ("PydanticDTO",)
  29 
  30 T = TypeVar("T", bound="pydantic.BaseModel | Collection[pydantic.BaseModel]")
  31 
  32 
  33 class PydanticDTO(AbstractDTO[T], Generic[T]):
  34     """Support for domain modelling with Pydantic."""
  35 
  36     @classmethod
  37     def generate_field_definitions(
  38         cls, model_type: type[pydantic.BaseModel]
  39     ) -> Generator[DTOFieldDefinition, None, None]:
  40         model_field_definitions = cls.get_model_type_hints(model_type)
  41 
  42         if pydantic.VERSION.startswith("1"):  # pragma: no cover
  43             model_fields: dict[str, pydantic.fields.FieldInfo] = {k: model_field.field_info for k, model_field in model_type.__fields__.items()}  # type: ignore
  44         else:
  45             model_fields = dict(model_type.model_fields)
  46 
  47         for field_name, field_info in model_fields.items():
  48             field_definition = model_field_definitions[field_name]
  49             dto_field = (field_definition.extra or {}).pop(DTO_FIELD_META_KEY, DTOField())
  50 
  51             if field_info.default is not PydanticUndefined:
  52                 default = field_info.default
  53             elif field_definition.is_optional:
  54                 default = None
  55             else:
  56                 default = Empty
  57 
  58             yield replace(
  59                 DTOFieldDefinition.from_field_definition(
  60                     field_definition=field_definition,
  61                     dto_field=dto_field,
  62                     model_name=model_type.__name__,
  63                     default_factory=field_info.default_factory
  64                     if field_info.default_factory and field_info.default_factory is not PydanticUndefined  # type: ignore[comparison-overlap]
  65                     else Empty,
  66                 ),
  67                 default=default,
  68                 name=field_name,
  69             )
  70 
  71     @classmethod
  72     def detect_nested_field(cls, field_definition: FieldDefinition) -> bool:
  73         return field_definition.is_subclass_of(pydantic.BaseModel)
  74
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/litestar/contrib/pydantic/pydantic_dto_factory.py b/litestar/contrib/pydantic/pydantic_dto_factory.py
  --- a/litestar/contrib/pydantic/pydantic_dto_factory.py
  +++ b/litestar/contrib/pydantic/pydantic_dto_factory.py
  @@ -3,20 +3,23 @@
   from dataclasses import replace
   from typing import TYPE_CHECKING, Collection, Generic, TypeVar
   
  +from typing_extensions import override
  +
   from litestar.dto.base_dto import AbstractDTO
   from litestar.dto.data_structures import DTOFieldDefinition
   from litestar.dto.field import DTO_FIELD_META_KEY, DTOField
  -from litestar.exceptions import MissingDependencyException
  +from litestar.exceptions import MissingDependencyException, ValidationException
   from litestar.types.empty import Empty
   
   if TYPE_CHECKING:
  -    from typing import Generator
  +    from typing import Any, Generator
   
       from litestar.typing import FieldDefinition
   
   
   try:
       import pydantic
  +    from pydantic import ValidationError
   
       if pydantic.VERSION.startswith("2"):
           from pydantic_core import PydanticUndefined
  @@ -33,6 +36,20 @@
   class PydanticDTO(AbstractDTO[T], Generic[T]):
       """Support for domain modelling with Pydantic."""
   
  +    @override
  +    def decode_builtins(self, value: dict[str, Any]) -> Any:
  +        try:
  +            return super().decode_builtins(value)
  +        except ValidationError as ex:
  +            raise ValidationException(extra=ex.errors()) from ex
  +
  +    @override
  +    def decode_bytes(self, value: bytes) -> Any:
  +        try:
  +            return super().decode_bytes(value)
  +        except ValidationError as ex:
  +            raise ValidationException(extra=ex.errors()) from ex
  +
       @classmethod
       def generate_field_definitions(
           cls, model_type: type[pydantic.BaseModel]
  
verification_info: {"golden_diff": "diff --git a/litestar/contrib/pydantic/pydantic_dto_factory.py b/litestar/contrib/pydantic/pydantic_dto_factory.py\n--- a/litestar/contrib/pydantic/pydantic_dto_factory.py\n+++ b/litestar/contrib/pydantic/pydantic_dto_factory.py\n@@ -3,20 +3,23 @@\n from dataclasses import replace\n from typing import TYPE_CHECKING, Collection, Generic, TypeVar\n \n+from typing_extensions import override\n+\n from litestar.dto.base_dto import AbstractDTO\n from litestar.dto.data_structures import DTOFieldDefinition\n from litestar.dto.field import DTO_FIELD_META_KEY, DTOField\n-from litestar.exceptions import MissingDependencyException\n+from litestar.exceptions import MissingDependencyException, ValidationException\n from litestar.types.empty import Empty\n \n if TYPE_CHECKING:\n-    from typing import Generator\n+    from typing import Any, Generator\n \n     from litestar.typing import FieldDefinition\n \n \n try:\n     import pydantic\n+    from pydantic import ValidationError\n \n     if pydantic.VERSION.startswith(\"2\"):\n         from pydantic_core import PydanticUndefined\n@@ -33,6 +36,20 @@\n class PydanticDTO(AbstractDTO[T], Generic[T]):\n     \"\"\"Support for domain modelling with Pydantic.\"\"\"\n \n+    @override\n+    def decode_builtins(self, value: dict[str, Any]) -> Any:\n+        try:\n+            return super().decode_builtins(value)\n+        except ValidationError as ex:\n+            raise ValidationException(extra=ex.errors()) from ex\n+\n+    @override\n+    def decode_bytes(self, value: bytes) -> Any:\n+        try:\n+            return super().decode_bytes(value)\n+        except ValidationError as ex:\n+            raise ValidationException(extra=ex.errors()) from ex\n+\n     @classmethod\n     def generate_field_definitions(\n         cls, model_type: type[pydantic.BaseModel]\n", "issue": "Bug: pydantic validations aren't being handled by DTOs\n### Description\r\n\r\nIn the documentation of Litestar we have:\r\n\r\n> When a value fails pydantic validation, the result will be a ValidationException with the extra key set to the pydantic validation errors. Thus, this data will be made available for the API consumers by default.\r\n\r\nBut when combined with DTO's in a post request, if a pydantic validation fails the exception is not handled and the client receives an InternalServerError (500) instead of a BadRequest (400):\r\n\r\n\r\n```\r\n    __pydantic_self__.__pydantic_validator__.validate_python(data, self_instance=__pydantic_self__)\r\npydantic_core._pydantic_core.ValidationError: 1 validation error for User\r\nname\r\n  String should have at most 2 characters [type=string_too_long, input_value='abc', input_type=str]\r\n    For further information visit https://errors.pydantic.dev/2.2/v/string_too_long\r\n\r\nStatus code: 500\r\n```\r\n\r\nIf the validation isn't handled by pydantic (or at least it isn't handled **first** by pydantic) it works, for example an Enum validation returns a proper 400 status code because `msgspec` catches it first:\r\n\r\n```python\r\nfrom enum import Enum\r\n\r\nclass NameEnum(str, Enum):\r\n    a = \"A\"\r\n    b = \"B\"\r\n\r\n# (replace the User class of the example with this)\r\nclass User(BaseModel):\r\n    name: NameEnum\r\n```\r\n\r\nOutput for incorrect Enum:\r\n\r\n```\r\n  File \".../.venv/lib64/python3.11/site-packages/litestar/serialization/msgspec_hooks.py\", line 191, in decode_json\r\n    raise SerializationException(str(msgspec_error)) from msgspec_error\r\nlitestar.exceptions.base_exceptions.SerializationException: Invalid enum value 'abc' - at `$.name`\r\n\r\n\r\n...\r\n\r\n  File \".../.venv/lib64/python3.11/site-packages/litestar/routes/http.py\", line 186, in _get_response_data\r\n    raise ClientException(str(e)) from e\r\nlitestar.exceptions.http_exceptions.ClientException: 400: Invalid enum value 'abc' - at `$.name`\r\n```\r\n\r\n### URL to code causing the issue\r\n\r\n_No response_\r\n\r\n### MCVE\r\n\r\n```python\r\nfrom litestar import Litestar, post\r\nfrom litestar.contrib.pydantic import PydanticDTO\r\nfrom litestar.testing import TestClient\r\nfrom pydantic import BaseModel, Field\r\n\r\n\r\nclass User(BaseModel):\r\n    name: str = Field(max_length=2)\r\n\r\n\r\nUserDTO = PydanticDTO[User]\r\n\r\n\r\n@post(\"/user\", dto=UserDTO, sync_to_thread=False)\r\ndef create_user(data: User) -> User:\r\n    return data\r\n\r\n\r\nwith TestClient(Litestar([create_user], debug=True)) as client:\r\n    response = client.post(\"/user\", json={\"name\": \"abc\"})\r\n    print(response.text)\r\n    print(f\"Status code: {response.status_code}\")\r\n    assert response.status_code == 201\r\n```\r\n\r\n\r\n### Steps to reproduce\r\n\r\n```bash\r\n1. Execute the MCVE\r\n```\r\n\r\n\r\n### Screenshots\r\n\r\n_No response_\r\n\r\n### Logs\r\n\r\n_No response_\r\n\r\n### Litestar Version\r\n\r\n2.0.0rc1\r\n\r\n### Platform\r\n\r\n- [X] Linux\r\n- [ ] Mac\r\n- [ ] Windows\r\n- [ ] Other (Please specify in the description above)\r\n\r\n<!-- POLAR PLEDGE BADGE START -->\r\n---\r\n\r\n## Funding\r\n* If you would like to see an issue prioritized, make a pledge towards it!\r\n* We receive the pledge once the issue is completed & verified\r\n\r\n<a href=\"https://polar.sh/litestar-org/litestar/issues/2190\">\r\n<picture>\r\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://polar.sh/api/github/litestar-org/litestar/issues/2190/pledge.svg?darkmode=1\">\r\n  <img alt=\"Fund with Polar\" src=\"https://polar.sh/api/github/litestar-org/litestar/issues/2190/pledge.svg\">\r\n</picture>\r\n</a>\r\n<!-- POLAR PLEDGE BADGE END -->\r\n\nStaticFilesConfig and virtual directories\nI'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. \r\n\r\nThis 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.\r\n\r\nhttps://github.com/starlite-api/starlite/blob/9bb6dcd57c10a591377cf8e3a537e9292566d5b9/starlite/config/static_files.py#L32\n", "before_files": [{"content": "from __future__ import annotations\n\nfrom dataclasses import replace\nfrom typing import TYPE_CHECKING, Collection, Generic, TypeVar\n\nfrom litestar.dto.base_dto import AbstractDTO\nfrom litestar.dto.data_structures import DTOFieldDefinition\nfrom litestar.dto.field import DTO_FIELD_META_KEY, DTOField\nfrom litestar.exceptions import MissingDependencyException\nfrom litestar.types.empty import Empty\n\nif TYPE_CHECKING:\n    from typing import Generator\n\n    from litestar.typing import FieldDefinition\n\n\ntry:\n    import pydantic\n\n    if pydantic.VERSION.startswith(\"2\"):\n        from pydantic_core import PydanticUndefined\n    else:  # pragma: no cover\n        from pydantic.fields import Undefined as PydanticUndefined  # type: ignore\nexcept ImportError as e:\n    raise MissingDependencyException(\"pydantic\") from e\n\n__all__ = (\"PydanticDTO\",)\n\nT = TypeVar(\"T\", bound=\"pydantic.BaseModel | Collection[pydantic.BaseModel]\")\n\n\nclass PydanticDTO(AbstractDTO[T], Generic[T]):\n    \"\"\"Support for domain modelling with Pydantic.\"\"\"\n\n    @classmethod\n    def generate_field_definitions(\n        cls, model_type: type[pydantic.BaseModel]\n    ) -> Generator[DTOFieldDefinition, None, None]:\n        model_field_definitions = cls.get_model_type_hints(model_type)\n\n        if pydantic.VERSION.startswith(\"1\"):  # pragma: no cover\n            model_fields: dict[str, pydantic.fields.FieldInfo] = {k: model_field.field_info for k, model_field in model_type.__fields__.items()}  # type: ignore\n        else:\n            model_fields = dict(model_type.model_fields)\n\n        for field_name, field_info in model_fields.items():\n            field_definition = model_field_definitions[field_name]\n            dto_field = (field_definition.extra or {}).pop(DTO_FIELD_META_KEY, DTOField())\n\n            if field_info.default is not PydanticUndefined:\n                default = field_info.default\n            elif field_definition.is_optional:\n                default = None\n            else:\n                default = Empty\n\n            yield replace(\n                DTOFieldDefinition.from_field_definition(\n                    field_definition=field_definition,\n                    dto_field=dto_field,\n                    model_name=model_type.__name__,\n                    default_factory=field_info.default_factory\n                    if field_info.default_factory and field_info.default_factory is not PydanticUndefined  # type: ignore[comparison-overlap]\n                    else Empty,\n                ),\n                default=default,\n                name=field_name,\n            )\n\n    @classmethod\n    def detect_nested_field(cls, field_definition: FieldDefinition) -> bool:\n        return field_definition.is_subclass_of(pydantic.BaseModel)\n", "path": "litestar/contrib/pydantic/pydantic_dto_factory.py"}], "after_files": [{"content": "from __future__ import annotations\n\nfrom dataclasses import replace\nfrom typing import TYPE_CHECKING, Collection, Generic, TypeVar\n\nfrom typing_extensions import override\n\nfrom litestar.dto.base_dto import AbstractDTO\nfrom litestar.dto.data_structures import DTOFieldDefinition\nfrom litestar.dto.field import DTO_FIELD_META_KEY, DTOField\nfrom litestar.exceptions import MissingDependencyException, ValidationException\nfrom litestar.types.empty import Empty\n\nif TYPE_CHECKING:\n    from typing import Any, Generator\n\n    from litestar.typing import FieldDefinition\n\n\ntry:\n    import pydantic\n    from pydantic import ValidationError\n\n    if pydantic.VERSION.startswith(\"2\"):\n        from pydantic_core import PydanticUndefined\n    else:  # pragma: no cover\n        from pydantic.fields import Undefined as PydanticUndefined  # type: ignore\nexcept ImportError as e:\n    raise MissingDependencyException(\"pydantic\") from e\n\n__all__ = (\"PydanticDTO\",)\n\nT = TypeVar(\"T\", bound=\"pydantic.BaseModel | Collection[pydantic.BaseModel]\")\n\n\nclass PydanticDTO(AbstractDTO[T], Generic[T]):\n    \"\"\"Support for domain modelling with Pydantic.\"\"\"\n\n    @override\n    def decode_builtins(self, value: dict[str, Any]) -> Any:\n        try:\n            return super().decode_builtins(value)\n        except ValidationError as ex:\n            raise ValidationException(extra=ex.errors()) from ex\n\n    @override\n    def decode_bytes(self, value: bytes) -> Any:\n        try:\n            return super().decode_bytes(value)\n        except ValidationError as ex:\n            raise ValidationException(extra=ex.errors()) from ex\n\n    @classmethod\n    def generate_field_definitions(\n        cls, model_type: type[pydantic.BaseModel]\n    ) -> Generator[DTOFieldDefinition, None, None]:\n        model_field_definitions = cls.get_model_type_hints(model_type)\n\n        if pydantic.VERSION.startswith(\"1\"):  # pragma: no cover\n            model_fields: dict[str, pydantic.fields.FieldInfo] = {k: model_field.field_info for k, model_field in model_type.__fields__.items()}  # type: ignore\n        else:\n            model_fields = dict(model_type.model_fields)\n\n        for field_name, field_info in model_fields.items():\n            field_definition = model_field_definitions[field_name]\n            dto_field = (field_definition.extra or {}).pop(DTO_FIELD_META_KEY, DTOField())\n\n            if field_info.default is not PydanticUndefined:\n                default = field_info.default\n            elif field_definition.is_optional:\n                default = None\n            else:\n                default = Empty\n\n            yield replace(\n                DTOFieldDefinition.from_field_definition(\n                    field_definition=field_definition,\n                    dto_field=dto_field,\n                    model_name=model_type.__name__,\n                    default_factory=field_info.default_factory\n                    if field_info.default_factory and field_info.default_factory is not PydanticUndefined  # type: ignore[comparison-overlap]\n                    else Empty,\n                ),\n                default=default,\n                name=field_name,\n            )\n\n    @classmethod\n    def detect_nested_field(cls, field_definition: FieldDefinition) -> bool:\n        return field_definition.is_subclass_of(pydantic.BaseModel)\n", "path": "litestar/contrib/pydantic/pydantic_dto_factory.py"}]}