We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Bug: App launching fails because of Pydantic version handling problem
### Description

Launching a Litestar app fails because of a variable that has a value of type `_EmptyEnum` and is expected to have an attribute `JsonValue`.

This is [a Pydantic version handling mechanism](https://github.com/litestar-org/litestar/blob/8d6782db0a176e3d327b42f3ed36e728e199a229/litestar/contrib/pydantic/pydantic_dto_factory.py#L50) that assigns a value of `Empty` ([here](https://github.com/litestar-org/litestar/blob/8d6782db0a176e3d327b42f3ed36e728e199a229/litestar/types/empty.py#L16)) to `pydantic_v2`.

### URL to code causing the issue

_No response_

### MCVE

```python
from litestar import Litestar, get


@get("/")
async def index() -> str:
    return "Hello, world!"


@get("/books/{book_id:int}")
async def get_book(book_id: int) -> dict[str, int]:
    return {"book_id": book_id}


app = Litestar([index, get_book])
```


### Steps to reproduce

```bash
1. Write the MCVE code in a file and name it `app.py`.
2. Run the app with `litestar --app app:app run  --host 0.0.0.0 --port 8000`
```


### Screenshots

```bash
"![SCREENSHOT_DESCRIPTION](SCREENSHOT_LINK.png)"
```


### Logs

```bash
Using Litestar app from env: 'sample_app:app'
Traceback (most recent call last):
  File "/home/zahran/miniconda3/envs/sample_env/bin/litestar", line 8, in <module>
    sys.exit(run_cli())
  File "/home/zahran/miniconda3/envs/sample_env/lib/python3.10/site-packages/litestar/__main__.py", line 6, in run_cli
    litestar_group()
  File "/home/zahran/miniconda3/envs/sample_env/lib/python3.10/site-packages/click/core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
  File "/home/zahran/miniconda3/envs/sample_env/lib/python3.10/site-packages/rich_click/rich_command.py", line 125, in main
    with self.make_context(prog_name, args, **extra) as ctx:
  File "/home/zahran/miniconda3/envs/sample_env/lib/python3.10/site-packages/litestar/cli/_utils.py", line 218, in make_context
    self._prepare(ctx)
  File "/home/zahran/miniconda3/envs/sample_env/lib/python3.10/site-packages/litestar/cli/_utils.py", line 200, in _prepare
    env = ctx.obj = LitestarEnv.from_env(ctx.params.get("app_path"), ctx.params.get("app_dir"))
  File "/home/zahran/miniconda3/envs/sample_env/lib/python3.10/site-packages/litestar/cli/_utils.py", line 106, in from_env
    loaded_app = _load_app_from_path(app_path)
  File "/home/zahran/miniconda3/envs/sample_env/lib/python3.10/site-packages/litestar/cli/_utils.py", line 271, in _load_app_from_path
    module = importlib.import_module(module_path)
  File "/home/zahran/miniconda3/envs/sample_env/lib/python3.10/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 883, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/home/ahmedzahran/projects/repos/agolo/neural-qbs/sample_app.py", line 14, in <module>
    app = Litestar([index, get_book])
  File "/home/zahran/miniconda3/envs/sample_env/lib/python3.10/site-packages/litestar/app.py", line 361, in __init__
    plugins=self._get_default_plugins(list(plugins or [])),
  File "/home/zahran/miniconda3/envs/sample_env/lib/python3.10/site-packages/litestar/app.py", line 521, in _get_default_plugins
    from litestar.contrib.pydantic import (
  File "/home/zahran/miniconda3/envs/sample_env/lib/python3.10/site-packages/litestar/contrib/pydantic/__init__.py", line 8, in <module>
    from .pydantic_dto_factory import PydanticDTO
  File "/home/zahran/miniconda3/envs/sample_env/lib/python3.10/site-packages/litestar/contrib/pydantic/pydantic_dto_factory.py", line 50, in <module>
    pydantic_v2.JsonValue: Any,
AttributeError: '_EmptyEnum' object has no attribute 'JsonValue'
```


### Litestar Version

2.8.0

### Platform

- [X] Linux
- [ ] Mac
- [ ] Windows
- [ ] Other (Please specify in the description above)

<!-- POLAR PLEDGE BADGE START -->
---
> [!NOTE]  
> While we are open for sponsoring on [GitHub Sponsors](https://github.com/sponsors/litestar-org/) and 
> [OpenCollective](https://opencollective.com/litestar), we also utilize [Polar.sh](https://polar.sh/) to engage in pledge-based sponsorship.
>
> Check out all issues funded or available for funding [on our Polar.sh dashboard](https://polar.sh/litestar-org)
> * If you would like to see an issue prioritized, make a pledge towards it!
> * We receive the pledge once the issue is completed & verified
> * This, along with engagement in the community, helps us know which features are a priority to our users.

<a href="https://polar.sh/litestar-org/litestar/issues/3334">
<picture>
  <source media="(prefers-color-scheme: dark)" srcset="https://polar.sh/api/github/litestar-org/litestar/issues/3334/pledge.svg?darkmode=1">
  <img alt="Fund with Polar" src="https://polar.sh/api/github/litestar-org/litestar/issues/3334/pledge.svg">
</picture>
</a>
<!-- POLAR PLEDGE BADGE END -->


--- 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, Any, Collection, Generic, TypeVar
5 from warnings import warn
6 
7 from typing_extensions import Annotated, TypeAlias, override
8 
9 from litestar.contrib.pydantic.utils import is_pydantic_undefined
10 from litestar.dto.base_dto import AbstractDTO
11 from litestar.dto.data_structures import DTOFieldDefinition
12 from litestar.dto.field import DTO_FIELD_META_KEY, extract_dto_field
13 from litestar.exceptions import MissingDependencyException, ValidationException
14 from litestar.types.empty import Empty
15 from litestar.typing import FieldDefinition
16 
17 if TYPE_CHECKING:
18     from typing import Generator
19 
20 try:
21     import pydantic as _  # noqa: F401
22 except ImportError as e:
23     raise MissingDependencyException("pydantic") from e
24 
25 
26 try:
27     import pydantic as pydantic_v2
28     from pydantic import ValidationError as ValidationErrorV2
29     from pydantic import v1 as pydantic_v1
30     from pydantic.v1 import ValidationError as ValidationErrorV1
31 
32     ModelType: TypeAlias = "pydantic_v1.BaseModel | pydantic_v2.BaseModel"
33 
34 except ImportError:
35     import pydantic as pydantic_v1  # type: ignore[no-redef]
36 
37     pydantic_v2 = Empty  # type: ignore[assignment]
38     from pydantic import ValidationError as ValidationErrorV1  # type: ignore[assignment]
39 
40     ValidationErrorV2 = ValidationErrorV1  # type: ignore[assignment, misc]
41     ModelType = "pydantic_v1.BaseModel"  # type: ignore[misc]
42 
43 
44 T = TypeVar("T", bound="ModelType | Collection[ModelType]")
45 
46 
47 __all__ = ("PydanticDTO",)
48 
49 _down_types = {
50     pydantic_v2.JsonValue: Any,
51     pydantic_v1.EmailStr: str,
52     pydantic_v2.EmailStr: str,
53     pydantic_v1.IPvAnyAddress: str,
54     pydantic_v2.IPvAnyAddress: str,
55     pydantic_v1.IPvAnyInterface: str,
56     pydantic_v2.IPvAnyInterface: str,
57     pydantic_v1.IPvAnyNetwork: str,
58     pydantic_v2.IPvAnyNetwork: str,
59 }
60 
61 
62 def convert_validation_error(validation_error: ValidationErrorV1 | ValidationErrorV2) -> list[dict[str, Any]]:
63     error_list = validation_error.errors()
64     for error in error_list:
65         if isinstance(exception := error.get("ctx", {}).get("error"), Exception):
66             error["ctx"]["error"] = type(exception).__name__
67     return error_list  # type: ignore[return-value]
68 
69 
70 def downtype_for_data_transfer(field_definition: FieldDefinition) -> FieldDefinition:
71     if sub := _down_types.get(field_definition.annotation):
72         return FieldDefinition.from_kwarg(
73             annotation=Annotated[sub, field_definition.metadata], name=field_definition.name
74         )
75     return field_definition
76 
77 
78 class PydanticDTO(AbstractDTO[T], Generic[T]):
79     """Support for domain modelling with Pydantic."""
80 
81     @override
82     def decode_builtins(self, value: dict[str, Any]) -> Any:
83         try:
84             return super().decode_builtins(value)
85         except (ValidationErrorV2, ValidationErrorV1) as ex:
86             raise ValidationException(extra=convert_validation_error(ex)) from ex
87 
88     @override
89     def decode_bytes(self, value: bytes) -> Any:
90         try:
91             return super().decode_bytes(value)
92         except (ValidationErrorV2, ValidationErrorV1) as ex:
93             raise ValidationException(extra=convert_validation_error(ex)) from ex
94 
95     @classmethod
96     def generate_field_definitions(
97         cls, model_type: type[pydantic_v1.BaseModel | pydantic_v2.BaseModel]
98     ) -> Generator[DTOFieldDefinition, None, None]:
99         model_field_definitions = cls.get_model_type_hints(model_type)
100 
101         model_fields: dict[str, pydantic_v1.fields.FieldInfo | pydantic_v2.fields.FieldInfo]
102         try:
103             model_fields = dict(model_type.model_fields)  # type: ignore[union-attr]
104         except AttributeError:
105             model_fields = {
106                 k: model_field.field_info
107                 for k, model_field in model_type.__fields__.items()  # type: ignore[union-attr]
108             }
109 
110         for field_name, field_info in model_fields.items():
111             field_definition = downtype_for_data_transfer(model_field_definitions[field_name])
112             dto_field = extract_dto_field(field_definition, field_definition.extra)
113 
114             try:
115                 extra = field_info.extra  # type: ignore[union-attr]
116             except AttributeError:
117                 extra = field_info.json_schema_extra  # type: ignore[union-attr]
118 
119             if extra is not None and extra.pop(DTO_FIELD_META_KEY, None):
120                 warn(
121                     message="Declaring 'DTOField' via Pydantic's 'Field.extra' is deprecated. "
122                     "Use 'Annotated', e.g., 'Annotated[str, DTOField(mark='read-only')]' instead. "
123                     "Support for 'DTOField' in 'Field.extra' will be removed in v3.",
124                     category=DeprecationWarning,
125                     stacklevel=2,
126                 )
127 
128             if not is_pydantic_undefined(field_info.default):
129                 default = field_info.default
130             elif field_definition.is_optional:
131                 default = None
132             else:
133                 default = Empty
134 
135             yield replace(
136                 DTOFieldDefinition.from_field_definition(
137                     field_definition=field_definition,
138                     dto_field=dto_field,
139                     model_name=model_type.__name__,
140                     default_factory=field_info.default_factory
141                     if field_info.default_factory and not is_pydantic_undefined(field_info.default_factory)
142                     else None,
143                 ),
144                 default=default,
145                 name=field_name,
146             )
147 
148     @classmethod
149     def detect_nested_field(cls, field_definition: FieldDefinition) -> bool:
150         if pydantic_v2 is not Empty:  # type: ignore[comparison-overlap]
151             return field_definition.is_subclass_of((pydantic_v1.BaseModel, pydantic_v2.BaseModel))
152         return field_definition.is_subclass_of(pydantic_v1.BaseModel)  # type: ignore[unreachable]
153
```
--- 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()

```

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
@@ -46,18 +46,24 @@
 
 __all__ = ("PydanticDTO",)
 
-_down_types = {
-    pydantic_v2.JsonValue: Any,
+_down_types: dict[Any, Any] = {
     pydantic_v1.EmailStr: str,
-    pydantic_v2.EmailStr: str,
     pydantic_v1.IPvAnyAddress: str,
-    pydantic_v2.IPvAnyAddress: str,
     pydantic_v1.IPvAnyInterface: str,
-    pydantic_v2.IPvAnyInterface: str,
     pydantic_v1.IPvAnyNetwork: str,
-    pydantic_v2.IPvAnyNetwork: str,
 }
 
+if pydantic_v2 is not Empty:  # type: ignore[comparison-overlap]  # pragma: no cover
+    _down_types.update(
+        {
+            pydantic_v2.JsonValue: Any,
+            pydantic_v2.EmailStr: str,
+            pydantic_v2.IPvAnyAddress: str,
+            pydantic_v2.IPvAnyInterface: str,
+            pydantic_v2.IPvAnyNetwork: str,
+        }
+    )
+
 
 def convert_validation_error(validation_error: ValidationErrorV1 | ValidationErrorV2) -> list[dict[str, Any]]:
     error_list = validation_error.errors()

{"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@@ -46,18 +46,24 @@\n \n __all__ = (\"PydanticDTO\",)\n \n-_down_types = {\n-    pydantic_v2.JsonValue: Any,\n+_down_types: dict[Any, Any] = {\n     pydantic_v1.EmailStr: str,\n-    pydantic_v2.EmailStr: str,\n     pydantic_v1.IPvAnyAddress: str,\n-    pydantic_v2.IPvAnyAddress: str,\n     pydantic_v1.IPvAnyInterface: str,\n-    pydantic_v2.IPvAnyInterface: str,\n     pydantic_v1.IPvAnyNetwork: str,\n-    pydantic_v2.IPvAnyNetwork: str,\n }\n \n+if pydantic_v2 is not Empty:  # type: ignore[comparison-overlap]  # pragma: no cover\n+    _down_types.update(\n+        {\n+            pydantic_v2.JsonValue: Any,\n+            pydantic_v2.EmailStr: str,\n+            pydantic_v2.IPvAnyAddress: str,\n+            pydantic_v2.IPvAnyInterface: str,\n+            pydantic_v2.IPvAnyNetwork: str,\n+        }\n+    )\n+\n \n def convert_validation_error(validation_error: ValidationErrorV1 | ValidationErrorV2) -> list[dict[str, Any]]:\n     error_list = validation_error.errors()\n", "issue": "Bug: App launching fails because of Pydantic version handling problem\n### Description\n\nLaunching a Litestar app fails because of a variable that has a value of type `_EmptyEnum` and is expected to have an attribute `JsonValue`.\r\n\r\nThis is [a Pydantic version handling mechanism](https://github.com/litestar-org/litestar/blob/8d6782db0a176e3d327b42f3ed36e728e199a229/litestar/contrib/pydantic/pydantic_dto_factory.py#L50) that assigns a value of `Empty` ([here](https://github.com/litestar-org/litestar/blob/8d6782db0a176e3d327b42f3ed36e728e199a229/litestar/types/empty.py#L16)) to `pydantic_v2`.\n\n### URL to code causing the issue\n\n_No response_\n\n### MCVE\n\n```python\nfrom litestar import Litestar, get\r\n\r\n\r\n@get(\"/\")\r\nasync def index() -> str:\r\n    return \"Hello, world!\"\r\n\r\n\r\n@get(\"/books/{book_id:int}\")\r\nasync def get_book(book_id: int) -> dict[str, int]:\r\n    return {\"book_id\": book_id}\r\n\r\n\r\napp = Litestar([index, get_book])\n```\n\n\n### Steps to reproduce\n\n```bash\n1. Write the MCVE code in a file and name it `app.py`.\r\n2. Run the app with `litestar --app app:app run  --host 0.0.0.0 --port 8000`\n```\n\n\n### Screenshots\n\n```bash\n\"![SCREENSHOT_DESCRIPTION](SCREENSHOT_LINK.png)\"\n```\n\n\n### Logs\n\n```bash\nUsing Litestar app from env: 'sample_app:app'\r\nTraceback (most recent call last):\r\n  File \"/home/zahran/miniconda3/envs/sample_env/bin/litestar\", line 8, in <module>\r\n    sys.exit(run_cli())\r\n  File \"/home/zahran/miniconda3/envs/sample_env/lib/python3.10/site-packages/litestar/__main__.py\", line 6, in run_cli\r\n    litestar_group()\r\n  File \"/home/zahran/miniconda3/envs/sample_env/lib/python3.10/site-packages/click/core.py\", line 1157, in __call__\r\n    return self.main(*args, **kwargs)\r\n  File \"/home/zahran/miniconda3/envs/sample_env/lib/python3.10/site-packages/rich_click/rich_command.py\", line 125, in main\r\n    with self.make_context(prog_name, args, **extra) as ctx:\r\n  File \"/home/zahran/miniconda3/envs/sample_env/lib/python3.10/site-packages/litestar/cli/_utils.py\", line 218, in make_context\r\n    self._prepare(ctx)\r\n  File \"/home/zahran/miniconda3/envs/sample_env/lib/python3.10/site-packages/litestar/cli/_utils.py\", line 200, in _prepare\r\n    env = ctx.obj = LitestarEnv.from_env(ctx.params.get(\"app_path\"), ctx.params.get(\"app_dir\"))\r\n  File \"/home/zahran/miniconda3/envs/sample_env/lib/python3.10/site-packages/litestar/cli/_utils.py\", line 106, in from_env\r\n    loaded_app = _load_app_from_path(app_path)\r\n  File \"/home/zahran/miniconda3/envs/sample_env/lib/python3.10/site-packages/litestar/cli/_utils.py\", line 271, in _load_app_from_path\r\n    module = importlib.import_module(module_path)\r\n  File \"/home/zahran/miniconda3/envs/sample_env/lib/python3.10/importlib/__init__.py\", line 126, in import_module\r\n    return _bootstrap._gcd_import(name[level:], package, level)\r\n  File \"<frozen importlib._bootstrap>\", line 1050, in _gcd_import\r\n  File \"<frozen importlib._bootstrap>\", line 1027, in _find_and_load\r\n  File \"<frozen importlib._bootstrap>\", line 1006, in _find_and_load_unlocked\r\n  File \"<frozen importlib._bootstrap>\", line 688, in _load_unlocked\r\n  File \"<frozen importlib._bootstrap_external>\", line 883, in exec_module\r\n  File \"<frozen importlib._bootstrap>\", line 241, in _call_with_frames_removed\r\n  File \"/home/ahmedzahran/projects/repos/agolo/neural-qbs/sample_app.py\", line 14, in <module>\r\n    app = Litestar([index, get_book])\r\n  File \"/home/zahran/miniconda3/envs/sample_env/lib/python3.10/site-packages/litestar/app.py\", line 361, in __init__\r\n    plugins=self._get_default_plugins(list(plugins or [])),\r\n  File \"/home/zahran/miniconda3/envs/sample_env/lib/python3.10/site-packages/litestar/app.py\", line 521, in _get_default_plugins\r\n    from litestar.contrib.pydantic import (\r\n  File \"/home/zahran/miniconda3/envs/sample_env/lib/python3.10/site-packages/litestar/contrib/pydantic/__init__.py\", line 8, in <module>\r\n    from .pydantic_dto_factory import PydanticDTO\r\n  File \"/home/zahran/miniconda3/envs/sample_env/lib/python3.10/site-packages/litestar/contrib/pydantic/pydantic_dto_factory.py\", line 50, in <module>\r\n    pydantic_v2.JsonValue: Any,\r\nAttributeError: '_EmptyEnum' object has no attribute 'JsonValue'\n```\n\n\n### Litestar Version\n\n2.8.0\n\n### Platform\n\n- [X] Linux\n- [ ] Mac\n- [ ] Windows\n- [ ] Other (Please specify in the description above)\n\n<!-- POLAR PLEDGE BADGE START -->\n---\n> [!NOTE]  \n> While we are open for sponsoring on [GitHub Sponsors](https://github.com/sponsors/litestar-org/) and \n> [OpenCollective](https://opencollective.com/litestar), we also utilize [Polar.sh](https://polar.sh/) to engage in pledge-based sponsorship.\n>\n> Check out all issues funded or available for funding [on our Polar.sh dashboard](https://polar.sh/litestar-org)\n> * If you would like to see an issue prioritized, make a pledge towards it!\n> * We receive the pledge once the issue is completed & verified\n> * This, along with engagement in the community, helps us know which features are a priority to our users.\n\n<a href=\"https://polar.sh/litestar-org/litestar/issues/3334\">\n<picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://polar.sh/api/github/litestar-org/litestar/issues/3334/pledge.svg?darkmode=1\">\n  <img alt=\"Fund with Polar\" src=\"https://polar.sh/api/github/litestar-org/litestar/issues/3334/pledge.svg\">\n</picture>\n</a>\n<!-- POLAR PLEDGE BADGE END -->\n\n", "before_files": [{"content": "from __future__ import annotations\n\nfrom dataclasses import replace\nfrom typing import TYPE_CHECKING, Any, Collection, Generic, TypeVar\nfrom warnings import warn\n\nfrom typing_extensions import Annotated, TypeAlias, override\n\nfrom litestar.contrib.pydantic.utils import is_pydantic_undefined\nfrom litestar.dto.base_dto import AbstractDTO\nfrom litestar.dto.data_structures import DTOFieldDefinition\nfrom litestar.dto.field import DTO_FIELD_META_KEY, extract_dto_field\nfrom litestar.exceptions import MissingDependencyException, ValidationException\nfrom litestar.types.empty import Empty\nfrom litestar.typing import FieldDefinition\n\nif TYPE_CHECKING:\n    from typing import Generator\n\ntry:\n    import pydantic as _  # noqa: F401\nexcept ImportError as e:\n    raise MissingDependencyException(\"pydantic\") from e\n\n\ntry:\n    import pydantic as pydantic_v2\n    from pydantic import ValidationError as ValidationErrorV2\n    from pydantic import v1 as pydantic_v1\n    from pydantic.v1 import ValidationError as ValidationErrorV1\n\n    ModelType: TypeAlias = \"pydantic_v1.BaseModel | pydantic_v2.BaseModel\"\n\nexcept ImportError:\n    import pydantic as pydantic_v1  # type: ignore[no-redef]\n\n    pydantic_v2 = Empty  # type: ignore[assignment]\n    from pydantic import ValidationError as ValidationErrorV1  # type: ignore[assignment]\n\n    ValidationErrorV2 = ValidationErrorV1  # type: ignore[assignment, misc]\n    ModelType = \"pydantic_v1.BaseModel\"  # type: ignore[misc]\n\n\nT = TypeVar(\"T\", bound=\"ModelType | Collection[ModelType]\")\n\n\n__all__ = (\"PydanticDTO\",)\n\n_down_types = {\n    pydantic_v2.JsonValue: Any,\n    pydantic_v1.EmailStr: str,\n    pydantic_v2.EmailStr: str,\n    pydantic_v1.IPvAnyAddress: str,\n    pydantic_v2.IPvAnyAddress: str,\n    pydantic_v1.IPvAnyInterface: str,\n    pydantic_v2.IPvAnyInterface: str,\n    pydantic_v1.IPvAnyNetwork: str,\n    pydantic_v2.IPvAnyNetwork: str,\n}\n\n\ndef convert_validation_error(validation_error: ValidationErrorV1 | ValidationErrorV2) -> list[dict[str, Any]]:\n    error_list = validation_error.errors()\n    for error in error_list:\n        if isinstance(exception := error.get(\"ctx\", {}).get(\"error\"), Exception):\n            error[\"ctx\"][\"error\"] = type(exception).__name__\n    return error_list  # type: ignore[return-value]\n\n\ndef downtype_for_data_transfer(field_definition: FieldDefinition) -> FieldDefinition:\n    if sub := _down_types.get(field_definition.annotation):\n        return FieldDefinition.from_kwarg(\n            annotation=Annotated[sub, field_definition.metadata], name=field_definition.name\n        )\n    return field_definition\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 (ValidationErrorV2, ValidationErrorV1) as ex:\n            raise ValidationException(extra=convert_validation_error(ex)) from ex\n\n    @override\n    def decode_bytes(self, value: bytes) -> Any:\n        try:\n            return super().decode_bytes(value)\n        except (ValidationErrorV2, ValidationErrorV1) as ex:\n            raise ValidationException(extra=convert_validation_error(ex)) from ex\n\n    @classmethod\n    def generate_field_definitions(\n        cls, model_type: type[pydantic_v1.BaseModel | pydantic_v2.BaseModel]\n    ) -> Generator[DTOFieldDefinition, None, None]:\n        model_field_definitions = cls.get_model_type_hints(model_type)\n\n        model_fields: dict[str, pydantic_v1.fields.FieldInfo | pydantic_v2.fields.FieldInfo]\n        try:\n            model_fields = dict(model_type.model_fields)  # type: ignore[union-attr]\n        except AttributeError:\n            model_fields = {\n                k: model_field.field_info\n                for k, model_field in model_type.__fields__.items()  # type: ignore[union-attr]\n            }\n\n        for field_name, field_info in model_fields.items():\n            field_definition = downtype_for_data_transfer(model_field_definitions[field_name])\n            dto_field = extract_dto_field(field_definition, field_definition.extra)\n\n            try:\n                extra = field_info.extra  # type: ignore[union-attr]\n            except AttributeError:\n                extra = field_info.json_schema_extra  # type: ignore[union-attr]\n\n            if extra is not None and extra.pop(DTO_FIELD_META_KEY, None):\n                warn(\n                    message=\"Declaring 'DTOField' via Pydantic's 'Field.extra' is deprecated. \"\n                    \"Use 'Annotated', e.g., 'Annotated[str, DTOField(mark='read-only')]' instead. \"\n                    \"Support for 'DTOField' in 'Field.extra' will be removed in v3.\",\n                    category=DeprecationWarning,\n                    stacklevel=2,\n                )\n\n            if not is_pydantic_undefined(field_info.default):\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 not is_pydantic_undefined(field_info.default_factory)\n                    else None,\n                ),\n                default=default,\n                name=field_name,\n            )\n\n    @classmethod\n    def detect_nested_field(cls, field_definition: FieldDefinition) -> bool:\n        if pydantic_v2 is not Empty:  # type: ignore[comparison-overlap]\n            return field_definition.is_subclass_of((pydantic_v1.BaseModel, pydantic_v2.BaseModel))\n        return field_definition.is_subclass_of(pydantic_v1.BaseModel)  # type: ignore[unreachable]\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, Any, Collection, Generic, TypeVar\nfrom warnings import warn\n\nfrom typing_extensions import Annotated, TypeAlias, override\n\nfrom litestar.contrib.pydantic.utils import is_pydantic_undefined\nfrom litestar.dto.base_dto import AbstractDTO\nfrom litestar.dto.data_structures import DTOFieldDefinition\nfrom litestar.dto.field import DTO_FIELD_META_KEY, extract_dto_field\nfrom litestar.exceptions import MissingDependencyException, ValidationException\nfrom litestar.types.empty import Empty\nfrom litestar.typing import FieldDefinition\n\nif TYPE_CHECKING:\n    from typing import Generator\n\ntry:\n    import pydantic as _  # noqa: F401\nexcept ImportError as e:\n    raise MissingDependencyException(\"pydantic\") from e\n\n\ntry:\n    import pydantic as pydantic_v2\n    from pydantic import ValidationError as ValidationErrorV2\n    from pydantic import v1 as pydantic_v1\n    from pydantic.v1 import ValidationError as ValidationErrorV1\n\n    ModelType: TypeAlias = \"pydantic_v1.BaseModel | pydantic_v2.BaseModel\"\n\nexcept ImportError:\n    import pydantic as pydantic_v1  # type: ignore[no-redef]\n\n    pydantic_v2 = Empty  # type: ignore[assignment]\n    from pydantic import ValidationError as ValidationErrorV1  # type: ignore[assignment]\n\n    ValidationErrorV2 = ValidationErrorV1  # type: ignore[assignment, misc]\n    ModelType = \"pydantic_v1.BaseModel\"  # type: ignore[misc]\n\n\nT = TypeVar(\"T\", bound=\"ModelType | Collection[ModelType]\")\n\n\n__all__ = (\"PydanticDTO\",)\n\n_down_types: dict[Any, Any] = {\n    pydantic_v1.EmailStr: str,\n    pydantic_v1.IPvAnyAddress: str,\n    pydantic_v1.IPvAnyInterface: str,\n    pydantic_v1.IPvAnyNetwork: str,\n}\n\nif pydantic_v2 is not Empty:  # type: ignore[comparison-overlap]  # pragma: no cover\n    _down_types.update(\n        {\n            pydantic_v2.JsonValue: Any,\n            pydantic_v2.EmailStr: str,\n            pydantic_v2.IPvAnyAddress: str,\n            pydantic_v2.IPvAnyInterface: str,\n            pydantic_v2.IPvAnyNetwork: str,\n        }\n    )\n\n\ndef convert_validation_error(validation_error: ValidationErrorV1 | ValidationErrorV2) -> list[dict[str, Any]]:\n    error_list = validation_error.errors()\n    for error in error_list:\n        if isinstance(exception := error.get(\"ctx\", {}).get(\"error\"), Exception):\n            error[\"ctx\"][\"error\"] = type(exception).__name__\n    return error_list  # type: ignore[return-value]\n\n\ndef downtype_for_data_transfer(field_definition: FieldDefinition) -> FieldDefinition:\n    if sub := _down_types.get(field_definition.annotation):\n        return FieldDefinition.from_kwarg(\n            annotation=Annotated[sub, field_definition.metadata], name=field_definition.name\n        )\n    return field_definition\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 (ValidationErrorV2, ValidationErrorV1) as ex:\n            raise ValidationException(extra=convert_validation_error(ex)) from ex\n\n    @override\n    def decode_bytes(self, value: bytes) -> Any:\n        try:\n            return super().decode_bytes(value)\n        except (ValidationErrorV2, ValidationErrorV1) as ex:\n            raise ValidationException(extra=convert_validation_error(ex)) from ex\n\n    @classmethod\n    def generate_field_definitions(\n        cls, model_type: type[pydantic_v1.BaseModel | pydantic_v2.BaseModel]\n    ) -> Generator[DTOFieldDefinition, None, None]:\n        model_field_definitions = cls.get_model_type_hints(model_type)\n\n        model_fields: dict[str, pydantic_v1.fields.FieldInfo | pydantic_v2.fields.FieldInfo]\n        try:\n            model_fields = dict(model_type.model_fields)  # type: ignore[union-attr]\n        except AttributeError:\n            model_fields = {\n                k: model_field.field_info\n                for k, model_field in model_type.__fields__.items()  # type: ignore[union-attr]\n            }\n\n        for field_name, field_info in model_fields.items():\n            field_definition = downtype_for_data_transfer(model_field_definitions[field_name])\n            dto_field = extract_dto_field(field_definition, field_definition.extra)\n\n            try:\n                extra = field_info.extra  # type: ignore[union-attr]\n            except AttributeError:\n                extra = field_info.json_schema_extra  # type: ignore[union-attr]\n\n            if extra is not None and extra.pop(DTO_FIELD_META_KEY, None):\n                warn(\n                    message=\"Declaring 'DTOField' via Pydantic's 'Field.extra' is deprecated. \"\n                    \"Use 'Annotated', e.g., 'Annotated[str, DTOField(mark='read-only')]' instead. \"\n                    \"Support for 'DTOField' in 'Field.extra' will be removed in v3.\",\n                    category=DeprecationWarning,\n                    stacklevel=2,\n                )\n\n            if not is_pydantic_undefined(field_info.default):\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 not is_pydantic_undefined(field_info.default_factory)\n                    else None,\n                ),\n                default=default,\n                name=field_name,\n            )\n\n    @classmethod\n    def detect_nested_field(cls, field_definition: FieldDefinition) -> bool:\n        if pydantic_v2 is not Empty:  # type: ignore[comparison-overlap]\n            return field_definition.is_subclass_of((pydantic_v1.BaseModel, pydantic_v2.BaseModel))\n        return field_definition.is_subclass_of(pydantic_v1.BaseModel)  # type: ignore[unreachable]\n", "path": "litestar/contrib/pydantic/pydantic_dto_factory.py"}]}