We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Bug: Premature instantiation of nested models
### Description

Assume two dataclasses `Person `and `Address`. `Person `contains an `address` (see MCVE).
Using `DataDTO[Person]` in a route handler results in a `TypeError(\"Address.__init__() missing 1 required positional argument: 'id'\")` because it tries to initialize the nested `Address` (which fails because the `address.id` is excluded from the `WriteDTO`).

### URL to code causing the issue

https://discord.com/channels/919193495116337154/1110854577575698463

### MCVE

```python
from dataclasses import dataclass
import uuid

from litestar import Litestar, post
from litestar.dto.factory import DTOConfig, DTOData
from litestar.dto.factory.stdlib import DataclassDTO

@dataclass
class Address:
    id: uuid.UUID
    street: str
    city: str

@dataclass
class Person:
    id: uuid.UUID
    name: str
    email: str
    address: Address

class WriteDTO(DataclassDTO[Person]):
    config = DTOConfig(exclude={"id", "address.id"})

@post("/person", dto=WriteDTO, return_dto=None, sync_to_thread=False)
def create_person(data: DTOData[Person]) -> str:
    return "Success"

app = Litestar([create_person])
```


### Steps to reproduce

```bash
curl -X 'POST' \
  'http://127.0.0.1:8000/person' \
  -H 'accept: text/plain' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "test",
  "email": "test",
  "address": {
    "street": "test",
    "city": "test"
  }
}'
```


### Screenshots

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


### Logs

```bash
INFO:     127.0.0.1:36960 - "POST /person HTTP/1.1" 500 Internal Server Error
```


### Litestar Version

2.0.0a7

### Platform

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

--- 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/dto/factory/_backends/utils.py`
Content:
```
1 from __future__ import annotations
2 
3 from typing import TYPE_CHECKING, Collection, Mapping, TypeVar, cast
4 
5 from msgspec import UNSET
6 from typing_extensions import get_origin
7 
8 from litestar.dto.factory import Mark
9 
10 from .types import (
11     CollectionType,
12     CompositeType,
13     MappingType,
14     NestedFieldInfo,
15     SimpleType,
16     TransferType,
17     TupleType,
18     UnionType,
19 )
20 
21 if TYPE_CHECKING:
22     from typing import AbstractSet, Any, Iterable
23 
24     from litestar.dto.factory.types import FieldDefinition, RenameStrategy
25     from litestar.dto.types import ForType
26 
27     from .types import FieldDefinitionsType
28 
29 __all__ = (
30     "RenameStrategies",
31     "build_annotation_for_backend",
32     "create_transfer_model_type_annotation",
33     "should_exclude_field",
34     "transfer_data",
35 )
36 
37 T = TypeVar("T")
38 
39 
40 def build_annotation_for_backend(annotation: Any, model: type[T]) -> type[T] | type[Iterable[T]]:
41     """A helper to re-build a generic outer type with new inner type.
42 
43     Args:
44         annotation: The original annotation on the handler signature
45         model: The data container type
46 
47     Returns:
48         Annotation with new inner type if applicable.
49     """
50     origin = get_origin(annotation)
51     if not origin:
52         return model
53     try:
54         return origin[model]  # type:ignore[no-any-return]
55     except TypeError:  # pragma: no cover
56         return annotation.copy_with((model,))  # type:ignore[no-any-return]
57 
58 
59 def should_exclude_field(field_definition: FieldDefinition, exclude: AbstractSet[str], dto_for: ForType) -> bool:
60     """Returns ``True`` where a field should be excluded from data transfer.
61 
62     Args:
63         field_definition: defined DTO field
64         exclude: names of fields to exclude
65         dto_for: indicates whether the DTO is for the request body or response.
66 
67     Returns:
68         ``True`` if the field should not be included in any data transfer.
69     """
70     field_name = field_definition.name
71     dto_field = field_definition.dto_field
72     excluded = field_name in exclude
73     private = dto_field and dto_field.mark is Mark.PRIVATE
74     read_only_for_write = dto_for == "data" and dto_field and dto_field.mark is Mark.READ_ONLY
75     return bool(excluded or private or read_only_for_write)
76 
77 
78 class RenameStrategies:
79     """Useful renaming strategies than be used with :class:`DTOConfig`"""
80 
81     def __init__(self, renaming_strategy: RenameStrategy) -> None:
82         self.renaming_strategy = renaming_strategy
83 
84     def __call__(self, field_name: str) -> str:
85         if not isinstance(self.renaming_strategy, str):
86             return self.renaming_strategy(field_name)
87 
88         return cast(str, getattr(self, self.renaming_strategy)(field_name))
89 
90     @staticmethod
91     def upper(field_name: str) -> str:
92         return field_name.upper()
93 
94     @staticmethod
95     def lower(field_name: str) -> str:
96         return field_name.lower()
97 
98     @staticmethod
99     def camel(field_name: str) -> str:
100         return RenameStrategies._camelize(field_name)
101 
102     @staticmethod
103     def pascal(field_name: str) -> str:
104         return RenameStrategies._camelize(field_name, capitalize_first_letter=True)
105 
106     @staticmethod
107     def _camelize(string: str, capitalize_first_letter: bool = False) -> str:
108         """Convert a string to camel case.
109 
110         Args:
111             string (str): The string to convert
112             capitalize_first_letter (bool): Default is False, a True value will convert to PascalCase
113         Returns:
114             str: The string converted to camel case or Pascal case
115         """
116         return "".join(
117             word if index == 0 and not capitalize_first_letter else word.capitalize()
118             for index, word in enumerate(string.split("_"))
119         )
120 
121 
122 def transfer_data(
123     destination_type: type[T],
124     source_data: Any | Collection[Any],
125     field_definitions: FieldDefinitionsType,
126     dto_for: ForType = "data",
127 ) -> T | Collection[T]:
128     """Create instance or iterable of instances of ``destination_type``.
129 
130     Args:
131         destination_type: the model type received by the DTO on type narrowing.
132         source_data: data that has been parsed and validated via the backend.
133         field_definitions: model field definitions.
134         dto_for: indicates whether the DTO is for the request body or response.
135 
136     Returns:
137         Data parsed into ``destination_type``.
138     """
139     if not isinstance(source_data, Mapping) and isinstance(source_data, Collection):
140         return type(source_data)(
141             transfer_data(destination_type, item, field_definitions, dto_for)  # type:ignore[call-arg]
142             for item in source_data
143         )
144     return transfer_instance_data(destination_type, source_data, field_definitions, dto_for)
145 
146 
147 def transfer_instance_data(
148     destination_type: type[T], source_instance: Any, field_definitions: FieldDefinitionsType, dto_for: ForType
149 ) -> T:
150     """Create instance of ``destination_type`` with data from ``source_instance``.
151 
152     Args:
153         destination_type: the model type received by the DTO on type narrowing.
154         source_instance: primitive data that has been parsed and validated via the backend.
155         field_definitions: model field definitions.
156         dto_for: indicates whether the DTO is for the request body or response.
157 
158     Returns:
159         Data parsed into ``model_type``.
160     """
161     unstructured_data = {}
162     source_is_mapping = isinstance(source_instance, Mapping)
163 
164     def filter_missing(value: Any) -> bool:
165         return value is UNSET
166 
167     for field_definition in field_definitions:
168         transfer_type = field_definition.transfer_type
169         source_name = field_definition.serialization_name if dto_for == "data" else field_definition.name
170         destination_name = field_definition.name if dto_for == "data" else field_definition.serialization_name
171         source_value = source_instance[source_name] if source_is_mapping else getattr(source_instance, source_name)
172         if field_definition.is_partial and dto_for == "data" and filter_missing(source_value):
173             continue
174         unstructured_data[destination_name] = transfer_type_data(source_value, transfer_type, dto_for)
175     return destination_type(**unstructured_data)
176 
177 
178 def transfer_type_data(source_value: Any, transfer_type: TransferType, dto_for: ForType) -> Any:
179     if isinstance(transfer_type, SimpleType) and transfer_type.nested_field_info:
180         dest_type = transfer_type.parsed_type.annotation if dto_for == "data" else transfer_type.nested_field_info.model
181         return transfer_nested_simple_type_data(dest_type, transfer_type.nested_field_info, dto_for, source_value)
182     if isinstance(transfer_type, UnionType) and transfer_type.has_nested:
183         return transfer_nested_union_type_data(transfer_type, dto_for, source_value)
184     if isinstance(transfer_type, CollectionType) and transfer_type.has_nested:
185         return transfer_nested_collection_type_data(
186             transfer_type.parsed_type.origin, transfer_type, dto_for, source_value
187         )
188     return source_value
189 
190 
191 def transfer_nested_collection_type_data(
192     origin_type: type[Any], transfer_type: CollectionType, dto_for: ForType, source_value: Any
193 ) -> Any:
194     return origin_type(transfer_type_data(item, transfer_type.inner_type, dto_for) for item in source_value)
195 
196 
197 def transfer_nested_simple_type_data(
198     destination_type: type[Any], nested_field_info: NestedFieldInfo, dto_for: ForType, source_value: Any
199 ) -> Any:
200     return transfer_instance_data(
201         destination_type,
202         source_value,
203         nested_field_info.field_definitions,
204         dto_for,
205     )
206 
207 
208 def transfer_nested_union_type_data(transfer_type: UnionType, dto_for: ForType, source_value: Any) -> Any:
209     for inner_type in transfer_type.inner_types:
210         if isinstance(inner_type, CompositeType):
211             raise RuntimeError("Composite inner types not (yet) supported for nested unions.")
212 
213         if inner_type.nested_field_info and isinstance(
214             source_value,
215             inner_type.nested_field_info.model if dto_for == "data" else inner_type.parsed_type.annotation,
216         ):
217             return transfer_instance_data(
218                 inner_type.parsed_type.annotation if dto_for == "data" else inner_type.nested_field_info.model,
219                 source_value,
220                 inner_type.nested_field_info.field_definitions,
221                 dto_for,
222             )
223     return source_value
224 
225 
226 def create_transfer_model_type_annotation(transfer_type: TransferType) -> Any:
227     """Create a type annotation for a transfer model.
228 
229     Uses the parsed type that originates from the data model and the transfer model generated to represent a nested
230     type to reconstruct the type annotation for the transfer model.
231     """
232     if isinstance(transfer_type, SimpleType):
233         if transfer_type.nested_field_info:
234             return transfer_type.nested_field_info.model
235         return transfer_type.parsed_type.annotation
236 
237     if isinstance(transfer_type, CollectionType):
238         return create_transfer_model_collection_type(transfer_type)
239 
240     if isinstance(transfer_type, MappingType):
241         return create_transfer_model_mapping_type(transfer_type)
242 
243     if isinstance(transfer_type, TupleType):
244         return create_transfer_model_tuple_type(transfer_type)
245 
246     if isinstance(transfer_type, UnionType):
247         return create_transfer_model_union_type(transfer_type)
248 
249     raise RuntimeError(f"Unexpected transfer type: {type(transfer_type)}")
250 
251 
252 def create_transfer_model_collection_type(transfer_type: CollectionType) -> Any:
253     generic_collection_type = transfer_type.parsed_type.safe_generic_origin
254     inner_type = create_transfer_model_type_annotation(transfer_type.inner_type)
255     if transfer_type.parsed_type.origin is tuple:
256         return generic_collection_type[inner_type, ...]
257     return generic_collection_type[inner_type]
258 
259 
260 def create_transfer_model_tuple_type(transfer_type: TupleType) -> Any:
261     inner_types = tuple(create_transfer_model_type_annotation(t) for t in transfer_type.inner_types)
262     return transfer_type.parsed_type.safe_generic_origin[inner_types]
263 
264 
265 def create_transfer_model_union_type(transfer_type: UnionType) -> Any:
266     inner_types = tuple(create_transfer_model_type_annotation(t) for t in transfer_type.inner_types)
267     return transfer_type.parsed_type.safe_generic_origin[inner_types]
268 
269 
270 def create_transfer_model_mapping_type(transfer_type: MappingType) -> Any:
271     key_type = create_transfer_model_type_annotation(transfer_type.key_type)
272     value_type = create_transfer_model_type_annotation(transfer_type.value_type)
273     return transfer_type.parsed_type.safe_generic_origin[key_type, value_type]
274
```
--- 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/dto/factory/_backends/utils.py b/litestar/dto/factory/_backends/utils.py
--- a/litestar/dto/factory/_backends/utils.py
+++ b/litestar/dto/factory/_backends/utils.py
@@ -171,13 +171,23 @@
         source_value = source_instance[source_name] if source_is_mapping else getattr(source_instance, source_name)
         if field_definition.is_partial and dto_for == "data" and filter_missing(source_value):
             continue
-        unstructured_data[destination_name] = transfer_type_data(source_value, transfer_type, dto_for)
+        unstructured_data[destination_name] = transfer_type_data(
+            source_value, transfer_type, dto_for, nested_as_dict=destination_type is dict
+        )
     return destination_type(**unstructured_data)
 
 
-def transfer_type_data(source_value: Any, transfer_type: TransferType, dto_for: ForType) -> Any:
+def transfer_type_data(
+    source_value: Any, transfer_type: TransferType, dto_for: ForType, nested_as_dict: bool = False
+) -> Any:
     if isinstance(transfer_type, SimpleType) and transfer_type.nested_field_info:
-        dest_type = transfer_type.parsed_type.annotation if dto_for == "data" else transfer_type.nested_field_info.model
+        if nested_as_dict:
+            dest_type = dict
+        else:
+            dest_type = (
+                transfer_type.parsed_type.annotation if dto_for == "data" else transfer_type.nested_field_info.model
+            )
+
         return transfer_nested_simple_type_data(dest_type, transfer_type.nested_field_info, dto_for, source_value)
     if isinstance(transfer_type, UnionType) and transfer_type.has_nested:
         return transfer_nested_union_type_data(transfer_type, dto_for, source_value)

{"golden_diff": "diff --git a/litestar/dto/factory/_backends/utils.py b/litestar/dto/factory/_backends/utils.py\n--- a/litestar/dto/factory/_backends/utils.py\n+++ b/litestar/dto/factory/_backends/utils.py\n@@ -171,13 +171,23 @@\n         source_value = source_instance[source_name] if source_is_mapping else getattr(source_instance, source_name)\n         if field_definition.is_partial and dto_for == \"data\" and filter_missing(source_value):\n             continue\n-        unstructured_data[destination_name] = transfer_type_data(source_value, transfer_type, dto_for)\n+        unstructured_data[destination_name] = transfer_type_data(\n+            source_value, transfer_type, dto_for, nested_as_dict=destination_type is dict\n+        )\n     return destination_type(**unstructured_data)\n \n \n-def transfer_type_data(source_value: Any, transfer_type: TransferType, dto_for: ForType) -> Any:\n+def transfer_type_data(\n+    source_value: Any, transfer_type: TransferType, dto_for: ForType, nested_as_dict: bool = False\n+) -> Any:\n     if isinstance(transfer_type, SimpleType) and transfer_type.nested_field_info:\n-        dest_type = transfer_type.parsed_type.annotation if dto_for == \"data\" else transfer_type.nested_field_info.model\n+        if nested_as_dict:\n+            dest_type = dict\n+        else:\n+            dest_type = (\n+                transfer_type.parsed_type.annotation if dto_for == \"data\" else transfer_type.nested_field_info.model\n+            )\n+\n         return transfer_nested_simple_type_data(dest_type, transfer_type.nested_field_info, dto_for, source_value)\n     if isinstance(transfer_type, UnionType) and transfer_type.has_nested:\n         return transfer_nested_union_type_data(transfer_type, dto_for, source_value)\n", "issue": "Bug: Premature instantiation of nested models\n### Description\n\nAssume two dataclasses `Person `and `Address`. `Person `contains an `address` (see MCVE).\r\nUsing `DataDTO[Person]` in a route handler results in a `TypeError(\\\"Address.__init__() missing 1 required positional argument: 'id'\\\")` because it tries to initialize the nested `Address` (which fails because the `address.id` is excluded from the `WriteDTO`).\n\n### URL to code causing the issue\n\nhttps://discord.com/channels/919193495116337154/1110854577575698463\n\n### MCVE\n\n```python\nfrom dataclasses import dataclass\r\nimport uuid\r\n\r\nfrom litestar import Litestar, post\r\nfrom litestar.dto.factory import DTOConfig, DTOData\r\nfrom litestar.dto.factory.stdlib import DataclassDTO\r\n\r\n@dataclass\r\nclass Address:\r\n    id: uuid.UUID\r\n    street: str\r\n    city: str\r\n\r\n@dataclass\r\nclass Person:\r\n    id: uuid.UUID\r\n    name: str\r\n    email: str\r\n    address: Address\r\n\r\nclass WriteDTO(DataclassDTO[Person]):\r\n    config = DTOConfig(exclude={\"id\", \"address.id\"})\r\n\r\n@post(\"/person\", dto=WriteDTO, return_dto=None, sync_to_thread=False)\r\ndef create_person(data: DTOData[Person]) -> str:\r\n    return \"Success\"\r\n\r\napp = Litestar([create_person])\n```\n\n\n### Steps to reproduce\n\n```bash\ncurl -X 'POST' \\\r\n  'http://127.0.0.1:8000/person' \\\r\n  -H 'accept: text/plain' \\\r\n  -H 'Content-Type: application/json' \\\r\n  -d '{\r\n  \"name\": \"test\",\r\n  \"email\": \"test\",\r\n  \"address\": {\r\n    \"street\": \"test\",\r\n    \"city\": \"test\"\r\n  }\r\n}'\n```\n\n\n### Screenshots\n\n```bash\n\"![SCREENSHOT_DESCRIPTION](SCREENSHOT_LINK.png)\"\n```\n\n\n### Logs\n\n```bash\nINFO:     127.0.0.1:36960 - \"POST /person HTTP/1.1\" 500 Internal Server Error\n```\n\n\n### Litestar Version\n\n2.0.0a7\n\n### Platform\n\n- [X] Linux\n- [X] Mac\n- [X] Windows\n- [ ] Other (Please specify in the description above)\n", "before_files": [{"content": "from __future__ import annotations\n\nfrom typing import TYPE_CHECKING, Collection, Mapping, TypeVar, cast\n\nfrom msgspec import UNSET\nfrom typing_extensions import get_origin\n\nfrom litestar.dto.factory import Mark\n\nfrom .types import (\n    CollectionType,\n    CompositeType,\n    MappingType,\n    NestedFieldInfo,\n    SimpleType,\n    TransferType,\n    TupleType,\n    UnionType,\n)\n\nif TYPE_CHECKING:\n    from typing import AbstractSet, Any, Iterable\n\n    from litestar.dto.factory.types import FieldDefinition, RenameStrategy\n    from litestar.dto.types import ForType\n\n    from .types import FieldDefinitionsType\n\n__all__ = (\n    \"RenameStrategies\",\n    \"build_annotation_for_backend\",\n    \"create_transfer_model_type_annotation\",\n    \"should_exclude_field\",\n    \"transfer_data\",\n)\n\nT = TypeVar(\"T\")\n\n\ndef build_annotation_for_backend(annotation: Any, model: type[T]) -> type[T] | type[Iterable[T]]:\n    \"\"\"A helper to re-build a generic outer type with new inner type.\n\n    Args:\n        annotation: The original annotation on the handler signature\n        model: The data container type\n\n    Returns:\n        Annotation with new inner type if applicable.\n    \"\"\"\n    origin = get_origin(annotation)\n    if not origin:\n        return model\n    try:\n        return origin[model]  # type:ignore[no-any-return]\n    except TypeError:  # pragma: no cover\n        return annotation.copy_with((model,))  # type:ignore[no-any-return]\n\n\ndef should_exclude_field(field_definition: FieldDefinition, exclude: AbstractSet[str], dto_for: ForType) -> bool:\n    \"\"\"Returns ``True`` where a field should be excluded from data transfer.\n\n    Args:\n        field_definition: defined DTO field\n        exclude: names of fields to exclude\n        dto_for: indicates whether the DTO is for the request body or response.\n\n    Returns:\n        ``True`` if the field should not be included in any data transfer.\n    \"\"\"\n    field_name = field_definition.name\n    dto_field = field_definition.dto_field\n    excluded = field_name in exclude\n    private = dto_field and dto_field.mark is Mark.PRIVATE\n    read_only_for_write = dto_for == \"data\" and dto_field and dto_field.mark is Mark.READ_ONLY\n    return bool(excluded or private or read_only_for_write)\n\n\nclass RenameStrategies:\n    \"\"\"Useful renaming strategies than be used with :class:`DTOConfig`\"\"\"\n\n    def __init__(self, renaming_strategy: RenameStrategy) -> None:\n        self.renaming_strategy = renaming_strategy\n\n    def __call__(self, field_name: str) -> str:\n        if not isinstance(self.renaming_strategy, str):\n            return self.renaming_strategy(field_name)\n\n        return cast(str, getattr(self, self.renaming_strategy)(field_name))\n\n    @staticmethod\n    def upper(field_name: str) -> str:\n        return field_name.upper()\n\n    @staticmethod\n    def lower(field_name: str) -> str:\n        return field_name.lower()\n\n    @staticmethod\n    def camel(field_name: str) -> str:\n        return RenameStrategies._camelize(field_name)\n\n    @staticmethod\n    def pascal(field_name: str) -> str:\n        return RenameStrategies._camelize(field_name, capitalize_first_letter=True)\n\n    @staticmethod\n    def _camelize(string: str, capitalize_first_letter: bool = False) -> str:\n        \"\"\"Convert a string to camel case.\n\n        Args:\n            string (str): The string to convert\n            capitalize_first_letter (bool): Default is False, a True value will convert to PascalCase\n        Returns:\n            str: The string converted to camel case or Pascal case\n        \"\"\"\n        return \"\".join(\n            word if index == 0 and not capitalize_first_letter else word.capitalize()\n            for index, word in enumerate(string.split(\"_\"))\n        )\n\n\ndef transfer_data(\n    destination_type: type[T],\n    source_data: Any | Collection[Any],\n    field_definitions: FieldDefinitionsType,\n    dto_for: ForType = \"data\",\n) -> T | Collection[T]:\n    \"\"\"Create instance or iterable of instances of ``destination_type``.\n\n    Args:\n        destination_type: the model type received by the DTO on type narrowing.\n        source_data: data that has been parsed and validated via the backend.\n        field_definitions: model field definitions.\n        dto_for: indicates whether the DTO is for the request body or response.\n\n    Returns:\n        Data parsed into ``destination_type``.\n    \"\"\"\n    if not isinstance(source_data, Mapping) and isinstance(source_data, Collection):\n        return type(source_data)(\n            transfer_data(destination_type, item, field_definitions, dto_for)  # type:ignore[call-arg]\n            for item in source_data\n        )\n    return transfer_instance_data(destination_type, source_data, field_definitions, dto_for)\n\n\ndef transfer_instance_data(\n    destination_type: type[T], source_instance: Any, field_definitions: FieldDefinitionsType, dto_for: ForType\n) -> T:\n    \"\"\"Create instance of ``destination_type`` with data from ``source_instance``.\n\n    Args:\n        destination_type: the model type received by the DTO on type narrowing.\n        source_instance: primitive data that has been parsed and validated via the backend.\n        field_definitions: model field definitions.\n        dto_for: indicates whether the DTO is for the request body or response.\n\n    Returns:\n        Data parsed into ``model_type``.\n    \"\"\"\n    unstructured_data = {}\n    source_is_mapping = isinstance(source_instance, Mapping)\n\n    def filter_missing(value: Any) -> bool:\n        return value is UNSET\n\n    for field_definition in field_definitions:\n        transfer_type = field_definition.transfer_type\n        source_name = field_definition.serialization_name if dto_for == \"data\" else field_definition.name\n        destination_name = field_definition.name if dto_for == \"data\" else field_definition.serialization_name\n        source_value = source_instance[source_name] if source_is_mapping else getattr(source_instance, source_name)\n        if field_definition.is_partial and dto_for == \"data\" and filter_missing(source_value):\n            continue\n        unstructured_data[destination_name] = transfer_type_data(source_value, transfer_type, dto_for)\n    return destination_type(**unstructured_data)\n\n\ndef transfer_type_data(source_value: Any, transfer_type: TransferType, dto_for: ForType) -> Any:\n    if isinstance(transfer_type, SimpleType) and transfer_type.nested_field_info:\n        dest_type = transfer_type.parsed_type.annotation if dto_for == \"data\" else transfer_type.nested_field_info.model\n        return transfer_nested_simple_type_data(dest_type, transfer_type.nested_field_info, dto_for, source_value)\n    if isinstance(transfer_type, UnionType) and transfer_type.has_nested:\n        return transfer_nested_union_type_data(transfer_type, dto_for, source_value)\n    if isinstance(transfer_type, CollectionType) and transfer_type.has_nested:\n        return transfer_nested_collection_type_data(\n            transfer_type.parsed_type.origin, transfer_type, dto_for, source_value\n        )\n    return source_value\n\n\ndef transfer_nested_collection_type_data(\n    origin_type: type[Any], transfer_type: CollectionType, dto_for: ForType, source_value: Any\n) -> Any:\n    return origin_type(transfer_type_data(item, transfer_type.inner_type, dto_for) for item in source_value)\n\n\ndef transfer_nested_simple_type_data(\n    destination_type: type[Any], nested_field_info: NestedFieldInfo, dto_for: ForType, source_value: Any\n) -> Any:\n    return transfer_instance_data(\n        destination_type,\n        source_value,\n        nested_field_info.field_definitions,\n        dto_for,\n    )\n\n\ndef transfer_nested_union_type_data(transfer_type: UnionType, dto_for: ForType, source_value: Any) -> Any:\n    for inner_type in transfer_type.inner_types:\n        if isinstance(inner_type, CompositeType):\n            raise RuntimeError(\"Composite inner types not (yet) supported for nested unions.\")\n\n        if inner_type.nested_field_info and isinstance(\n            source_value,\n            inner_type.nested_field_info.model if dto_for == \"data\" else inner_type.parsed_type.annotation,\n        ):\n            return transfer_instance_data(\n                inner_type.parsed_type.annotation if dto_for == \"data\" else inner_type.nested_field_info.model,\n                source_value,\n                inner_type.nested_field_info.field_definitions,\n                dto_for,\n            )\n    return source_value\n\n\ndef create_transfer_model_type_annotation(transfer_type: TransferType) -> Any:\n    \"\"\"Create a type annotation for a transfer model.\n\n    Uses the parsed type that originates from the data model and the transfer model generated to represent a nested\n    type to reconstruct the type annotation for the transfer model.\n    \"\"\"\n    if isinstance(transfer_type, SimpleType):\n        if transfer_type.nested_field_info:\n            return transfer_type.nested_field_info.model\n        return transfer_type.parsed_type.annotation\n\n    if isinstance(transfer_type, CollectionType):\n        return create_transfer_model_collection_type(transfer_type)\n\n    if isinstance(transfer_type, MappingType):\n        return create_transfer_model_mapping_type(transfer_type)\n\n    if isinstance(transfer_type, TupleType):\n        return create_transfer_model_tuple_type(transfer_type)\n\n    if isinstance(transfer_type, UnionType):\n        return create_transfer_model_union_type(transfer_type)\n\n    raise RuntimeError(f\"Unexpected transfer type: {type(transfer_type)}\")\n\n\ndef create_transfer_model_collection_type(transfer_type: CollectionType) -> Any:\n    generic_collection_type = transfer_type.parsed_type.safe_generic_origin\n    inner_type = create_transfer_model_type_annotation(transfer_type.inner_type)\n    if transfer_type.parsed_type.origin is tuple:\n        return generic_collection_type[inner_type, ...]\n    return generic_collection_type[inner_type]\n\n\ndef create_transfer_model_tuple_type(transfer_type: TupleType) -> Any:\n    inner_types = tuple(create_transfer_model_type_annotation(t) for t in transfer_type.inner_types)\n    return transfer_type.parsed_type.safe_generic_origin[inner_types]\n\n\ndef create_transfer_model_union_type(transfer_type: UnionType) -> Any:\n    inner_types = tuple(create_transfer_model_type_annotation(t) for t in transfer_type.inner_types)\n    return transfer_type.parsed_type.safe_generic_origin[inner_types]\n\n\ndef create_transfer_model_mapping_type(transfer_type: MappingType) -> Any:\n    key_type = create_transfer_model_type_annotation(transfer_type.key_type)\n    value_type = create_transfer_model_type_annotation(transfer_type.value_type)\n    return transfer_type.parsed_type.safe_generic_origin[key_type, value_type]\n", "path": "litestar/dto/factory/_backends/utils.py"}], "after_files": [{"content": "from __future__ import annotations\n\nfrom typing import TYPE_CHECKING, Collection, Mapping, TypeVar, cast\n\nfrom msgspec import UNSET\nfrom typing_extensions import get_origin\n\nfrom litestar.dto.factory import Mark\n\nfrom .types import (\n    CollectionType,\n    CompositeType,\n    MappingType,\n    NestedFieldInfo,\n    SimpleType,\n    TransferType,\n    TupleType,\n    UnionType,\n)\n\nif TYPE_CHECKING:\n    from typing import AbstractSet, Any, Iterable\n\n    from litestar.dto.factory.types import FieldDefinition, RenameStrategy\n    from litestar.dto.types import ForType\n\n    from .types import FieldDefinitionsType\n\n__all__ = (\n    \"RenameStrategies\",\n    \"build_annotation_for_backend\",\n    \"create_transfer_model_type_annotation\",\n    \"should_exclude_field\",\n    \"transfer_data\",\n)\n\nT = TypeVar(\"T\")\n\n\ndef build_annotation_for_backend(annotation: Any, model: type[T]) -> type[T] | type[Iterable[T]]:\n    \"\"\"A helper to re-build a generic outer type with new inner type.\n\n    Args:\n        annotation: The original annotation on the handler signature\n        model: The data container type\n\n    Returns:\n        Annotation with new inner type if applicable.\n    \"\"\"\n    origin = get_origin(annotation)\n    if not origin:\n        return model\n    try:\n        return origin[model]  # type:ignore[no-any-return]\n    except TypeError:  # pragma: no cover\n        return annotation.copy_with((model,))  # type:ignore[no-any-return]\n\n\ndef should_exclude_field(field_definition: FieldDefinition, exclude: AbstractSet[str], dto_for: ForType) -> bool:\n    \"\"\"Returns ``True`` where a field should be excluded from data transfer.\n\n    Args:\n        field_definition: defined DTO field\n        exclude: names of fields to exclude\n        dto_for: indicates whether the DTO is for the request body or response.\n\n    Returns:\n        ``True`` if the field should not be included in any data transfer.\n    \"\"\"\n    field_name = field_definition.name\n    dto_field = field_definition.dto_field\n    excluded = field_name in exclude\n    private = dto_field and dto_field.mark is Mark.PRIVATE\n    read_only_for_write = dto_for == \"data\" and dto_field and dto_field.mark is Mark.READ_ONLY\n    return bool(excluded or private or read_only_for_write)\n\n\nclass RenameStrategies:\n    \"\"\"Useful renaming strategies than be used with :class:`DTOConfig`\"\"\"\n\n    def __init__(self, renaming_strategy: RenameStrategy) -> None:\n        self.renaming_strategy = renaming_strategy\n\n    def __call__(self, field_name: str) -> str:\n        if not isinstance(self.renaming_strategy, str):\n            return self.renaming_strategy(field_name)\n\n        return cast(str, getattr(self, self.renaming_strategy)(field_name))\n\n    @staticmethod\n    def upper(field_name: str) -> str:\n        return field_name.upper()\n\n    @staticmethod\n    def lower(field_name: str) -> str:\n        return field_name.lower()\n\n    @staticmethod\n    def camel(field_name: str) -> str:\n        return RenameStrategies._camelize(field_name)\n\n    @staticmethod\n    def pascal(field_name: str) -> str:\n        return RenameStrategies._camelize(field_name, capitalize_first_letter=True)\n\n    @staticmethod\n    def _camelize(string: str, capitalize_first_letter: bool = False) -> str:\n        \"\"\"Convert a string to camel case.\n\n        Args:\n            string (str): The string to convert\n            capitalize_first_letter (bool): Default is False, a True value will convert to PascalCase\n        Returns:\n            str: The string converted to camel case or Pascal case\n        \"\"\"\n        return \"\".join(\n            word if index == 0 and not capitalize_first_letter else word.capitalize()\n            for index, word in enumerate(string.split(\"_\"))\n        )\n\n\ndef transfer_data(\n    destination_type: type[T],\n    source_data: Any | Collection[Any],\n    field_definitions: FieldDefinitionsType,\n    dto_for: ForType = \"data\",\n) -> T | Collection[T]:\n    \"\"\"Create instance or iterable of instances of ``destination_type``.\n\n    Args:\n        destination_type: the model type received by the DTO on type narrowing.\n        source_data: data that has been parsed and validated via the backend.\n        field_definitions: model field definitions.\n        dto_for: indicates whether the DTO is for the request body or response.\n\n    Returns:\n        Data parsed into ``destination_type``.\n    \"\"\"\n    if not isinstance(source_data, Mapping) and isinstance(source_data, Collection):\n        return type(source_data)(\n            transfer_data(destination_type, item, field_definitions, dto_for)  # type:ignore[call-arg]\n            for item in source_data\n        )\n    return transfer_instance_data(destination_type, source_data, field_definitions, dto_for)\n\n\ndef transfer_instance_data(\n    destination_type: type[T], source_instance: Any, field_definitions: FieldDefinitionsType, dto_for: ForType\n) -> T:\n    \"\"\"Create instance of ``destination_type`` with data from ``source_instance``.\n\n    Args:\n        destination_type: the model type received by the DTO on type narrowing.\n        source_instance: primitive data that has been parsed and validated via the backend.\n        field_definitions: model field definitions.\n        dto_for: indicates whether the DTO is for the request body or response.\n\n    Returns:\n        Data parsed into ``model_type``.\n    \"\"\"\n    unstructured_data = {}\n    source_is_mapping = isinstance(source_instance, Mapping)\n\n    def filter_missing(value: Any) -> bool:\n        return value is UNSET\n\n    for field_definition in field_definitions:\n        transfer_type = field_definition.transfer_type\n        source_name = field_definition.serialization_name if dto_for == \"data\" else field_definition.name\n        destination_name = field_definition.name if dto_for == \"data\" else field_definition.serialization_name\n        source_value = source_instance[source_name] if source_is_mapping else getattr(source_instance, source_name)\n        if field_definition.is_partial and dto_for == \"data\" and filter_missing(source_value):\n            continue\n        unstructured_data[destination_name] = transfer_type_data(\n            source_value, transfer_type, dto_for, nested_as_dict=destination_type is dict\n        )\n    return destination_type(**unstructured_data)\n\n\ndef transfer_type_data(\n    source_value: Any, transfer_type: TransferType, dto_for: ForType, nested_as_dict: bool = False\n) -> Any:\n    if isinstance(transfer_type, SimpleType) and transfer_type.nested_field_info:\n        if nested_as_dict:\n            dest_type = dict\n        else:\n            dest_type = (\n                transfer_type.parsed_type.annotation if dto_for == \"data\" else transfer_type.nested_field_info.model\n            )\n\n        return transfer_nested_simple_type_data(dest_type, transfer_type.nested_field_info, dto_for, source_value)\n    if isinstance(transfer_type, UnionType) and transfer_type.has_nested:\n        return transfer_nested_union_type_data(transfer_type, dto_for, source_value)\n    if isinstance(transfer_type, CollectionType) and transfer_type.has_nested:\n        return transfer_nested_collection_type_data(\n            transfer_type.parsed_type.origin, transfer_type, dto_for, source_value\n        )\n    return source_value\n\n\ndef transfer_nested_collection_type_data(\n    origin_type: type[Any], transfer_type: CollectionType, dto_for: ForType, source_value: Any\n) -> Any:\n    return origin_type(transfer_type_data(item, transfer_type.inner_type, dto_for) for item in source_value)\n\n\ndef transfer_nested_simple_type_data(\n    destination_type: type[Any], nested_field_info: NestedFieldInfo, dto_for: ForType, source_value: Any\n) -> Any:\n    return transfer_instance_data(\n        destination_type,\n        source_value,\n        nested_field_info.field_definitions,\n        dto_for,\n    )\n\n\ndef transfer_nested_union_type_data(transfer_type: UnionType, dto_for: ForType, source_value: Any) -> Any:\n    for inner_type in transfer_type.inner_types:\n        if isinstance(inner_type, CompositeType):\n            raise RuntimeError(\"Composite inner types not (yet) supported for nested unions.\")\n\n        if inner_type.nested_field_info and isinstance(\n            source_value,\n            inner_type.nested_field_info.model if dto_for == \"data\" else inner_type.parsed_type.annotation,\n        ):\n            return transfer_instance_data(\n                inner_type.parsed_type.annotation if dto_for == \"data\" else inner_type.nested_field_info.model,\n                source_value,\n                inner_type.nested_field_info.field_definitions,\n                dto_for,\n            )\n    return source_value\n\n\ndef create_transfer_model_type_annotation(transfer_type: TransferType) -> Any:\n    \"\"\"Create a type annotation for a transfer model.\n\n    Uses the parsed type that originates from the data model and the transfer model generated to represent a nested\n    type to reconstruct the type annotation for the transfer model.\n    \"\"\"\n    if isinstance(transfer_type, SimpleType):\n        if transfer_type.nested_field_info:\n            return transfer_type.nested_field_info.model\n        return transfer_type.parsed_type.annotation\n\n    if isinstance(transfer_type, CollectionType):\n        return create_transfer_model_collection_type(transfer_type)\n\n    if isinstance(transfer_type, MappingType):\n        return create_transfer_model_mapping_type(transfer_type)\n\n    if isinstance(transfer_type, TupleType):\n        return create_transfer_model_tuple_type(transfer_type)\n\n    if isinstance(transfer_type, UnionType):\n        return create_transfer_model_union_type(transfer_type)\n\n    raise RuntimeError(f\"Unexpected transfer type: {type(transfer_type)}\")\n\n\ndef create_transfer_model_collection_type(transfer_type: CollectionType) -> Any:\n    generic_collection_type = transfer_type.parsed_type.safe_generic_origin\n    inner_type = create_transfer_model_type_annotation(transfer_type.inner_type)\n    if transfer_type.parsed_type.origin is tuple:\n        return generic_collection_type[inner_type, ...]\n    return generic_collection_type[inner_type]\n\n\ndef create_transfer_model_tuple_type(transfer_type: TupleType) -> Any:\n    inner_types = tuple(create_transfer_model_type_annotation(t) for t in transfer_type.inner_types)\n    return transfer_type.parsed_type.safe_generic_origin[inner_types]\n\n\ndef create_transfer_model_union_type(transfer_type: UnionType) -> Any:\n    inner_types = tuple(create_transfer_model_type_annotation(t) for t in transfer_type.inner_types)\n    return transfer_type.parsed_type.safe_generic_origin[inner_types]\n\n\ndef create_transfer_model_mapping_type(transfer_type: MappingType) -> Any:\n    key_type = create_transfer_model_type_annotation(transfer_type.key_type)\n    value_type = create_transfer_model_type_annotation(transfer_type.value_type)\n    return transfer_type.parsed_type.safe_generic_origin[key_type, value_type]\n", "path": "litestar/dto/factory/_backends/utils.py"}]}