|
2 | 2 | {% set isGeneric = definition.additionalProperties or hasGenericProperty %} |
3 | 3 | from typing import Any, Dict, List, Optional, Union, cast{% if isGeneric %}, Generic, TypeVar, Type{% endif %} |
4 | 4 |
|
5 | | -from pydantic import Field, PrivateAttr{{ definition.additionalProperties ? ', model_serializer' : '' }} |
| 5 | +from pydantic import Field, PrivateAttr{{ definition.additionalProperties ? ', TypeAdapter, model_serializer' : '' }} |
6 | 6 |
|
7 | 7 | from .base_model import AppwriteModel |
8 | 8 | {% set added = [] %} |
@@ -31,6 +31,10 @@ from .{{ subSchema | caseSnake }} import {{ subSchema | caseUcfirst }} |
31 | 31 |
|
32 | 32 | T = TypeVar('T') |
33 | 33 | {% endif %} |
| 34 | +{% if definition.additionalProperties %} |
| 35 | + |
| 36 | +_PAYLOAD_ADAPTER = TypeAdapter(Dict[str, Any]) |
| 37 | +{% endif %} |
34 | 38 |
|
35 | 39 | class {{ definition.name | caseUcfirst }}(AppwriteModel{% if isGeneric %}, Generic[T]{% endif %}): |
36 | 40 | """ |
@@ -113,26 +117,71 @@ class {{ definition.name | caseUcfirst }}(AppwriteModel{% if isGeneric %}, Gener |
113 | 117 | def {{ 'data' | caseSnake | removeDollarSign }}(self, value: T) -> None: |
114 | 118 | object.__setattr__(self, '_{{ 'data' | caseSnake | removeDollarSign }}', value) |
115 | 119 |
|
116 | | - def _serialize_data(self, info): |
| 120 | + def _serialize_data(self, info, include=None, exclude=None): |
117 | 121 | if hasattr(self._{{ 'data' | caseSnake | removeDollarSign }}, 'model_dump'): |
118 | 122 | return self._{{ 'data' | caseSnake | removeDollarSign }}.model_dump( |
119 | 123 | mode=info.mode, |
120 | 124 | by_alias=info.by_alias, |
121 | 125 | exclude_unset=info.exclude_unset, |
122 | 126 | exclude_defaults=info.exclude_defaults, |
123 | 127 | exclude_none=info.exclude_none, |
| 128 | + include=include, |
| 129 | + exclude=exclude, |
| 130 | + ) |
| 131 | + |
| 132 | + if isinstance(self._{{ 'data' | caseSnake | removeDollarSign }}, dict) and (include is not None or exclude is not None): |
| 133 | + return _PAYLOAD_ADAPTER.dump_python( |
| 134 | + self._{{ 'data' | caseSnake | removeDollarSign }}, |
| 135 | + mode=info.mode, |
| 136 | + by_alias=info.by_alias, |
| 137 | + exclude_unset=info.exclude_unset, |
| 138 | + exclude_defaults=info.exclude_defaults, |
| 139 | + exclude_none=info.exclude_none, |
| 140 | + include=include, |
| 141 | + exclude=exclude, |
124 | 142 | ) |
125 | 143 |
|
126 | 144 | return self._{{ 'data' | caseSnake | removeDollarSign }} |
| 145 | +{% if definition.properties | length > 0 %} |
| 146 | + |
| 147 | + @staticmethod |
| 148 | + def _select_data(selector): |
| 149 | + """ |
| 150 | + Resolves a pydantic include/exclude selector against the '{{ 'data' }}' key, which is |
| 151 | + serialized here rather than declared as a field. Returns whether the key was |
| 152 | + named, and any nested selector to apply within it. |
| 153 | + """ |
| 154 | + if selector is None: |
| 155 | + return False, None |
| 156 | + |
| 157 | + if isinstance(selector, dict): |
| 158 | + if '{{ 'data' }}' not in selector: |
| 159 | + return False, None |
| 160 | + |
| 161 | + nested = selector['{{ 'data' }}'] |
| 162 | + |
| 163 | + return True, nested if isinstance(nested, (dict, set, frozenset, list, tuple)) else None |
| 164 | + |
| 165 | + return '{{ 'data' }}' in selector, None |
| 166 | +{% endif %} |
127 | 167 |
|
128 | 168 | @model_serializer(mode='wrap') |
129 | 169 | def _serialize_model(self, handler, info): |
130 | 170 | result = handler(self) |
131 | | - data = self._serialize_data(info) |
132 | 171 | {% if definition.properties | length > 0 %} |
133 | | - result['{{ 'data' }}'] = data |
| 172 | + included, include_fields = self._select_data(info.include) |
| 173 | + excluded, exclude_fields = self._select_data(info.exclude) |
| 174 | + |
| 175 | + if info.include is not None and not included: |
| 176 | + return result |
| 177 | + |
| 178 | + if excluded and exclude_fields is None: |
| 179 | + return result |
| 180 | + |
| 181 | + result['{{ 'data' }}'] = self._serialize_data(info, include_fields, exclude_fields) |
134 | 182 | return result |
135 | 183 | {% else %} |
| 184 | + data = self._serialize_data(info, info.include, info.exclude) |
136 | 185 | if isinstance(result, dict) and isinstance(data, dict): |
137 | 186 | return {**result, **data} |
138 | 187 |
|
|
0 commit comments