|
23 | 23 | from scim2_models.annotations import Required |
24 | 24 | from scim2_models.annotations import Returned |
25 | 25 | from scim2_models.context import Context |
| 26 | +from scim2_models.utils import UNION_TYPES |
| 27 | +from scim2_models.utils import find_field_name |
26 | 28 | from scim2_models.utils import normalize_attribute_name |
27 | 29 | from scim2_models.utils import to_camel |
28 | 30 |
|
29 | | -from .utils import UNION_TYPES |
30 | | - |
31 | 31 |
|
32 | 32 | def contains_attribute_or_subattributes( |
33 | 33 | attribute_urns: list[str], attribute_urn: str |
@@ -152,15 +152,44 @@ def normalize_attribute_names( |
152 | 152 | transformed in lowercase so any case is handled the same way. |
153 | 153 | """ |
154 | 154 |
|
155 | | - def normalize_value(value: Any) -> Any: |
156 | | - if isinstance(value, dict): |
157 | | - return { |
158 | | - normalize_attribute_name(k): normalize_value(v) |
159 | | - for k, v in value.items() |
160 | | - } |
161 | | - return value |
| 155 | + def normalize_dict_keys( |
| 156 | + input_dict: dict, model_class: type["BaseModel"] |
| 157 | + ) -> dict: |
| 158 | + """Normalize dictionary keys, preserving case for Any fields.""" |
| 159 | + result = {} |
| 160 | + |
| 161 | + for key, val in input_dict.items(): |
| 162 | + field_name = find_field_name(model_class, key) |
| 163 | + field_type = ( |
| 164 | + model_class.get_field_root_type(field_name) if field_name else None |
| 165 | + ) |
| 166 | + |
| 167 | + # Don't normalize keys for attributes typed with Any |
| 168 | + # This way, agnostic dicts such as PatchOp.operations.value |
| 169 | + # are preserved |
| 170 | + if field_name and field_type == Any: |
| 171 | + result[key] = normalize_value(val) |
| 172 | + else: |
| 173 | + result[normalize_attribute_name(key)] = normalize_value( |
| 174 | + val, field_type |
| 175 | + ) |
| 176 | + |
| 177 | + return result |
| 178 | + |
| 179 | + def normalize_value( |
| 180 | + val: Any, model_class: Optional[type["BaseModel"]] = None |
| 181 | + ) -> Any: |
| 182 | + """Normalize input value based on model class.""" |
| 183 | + if not isinstance(val, dict): |
| 184 | + return val |
| 185 | + |
| 186 | + # If no model_class, preserve original keys |
| 187 | + if not model_class: |
| 188 | + return {k: normalize_value(v) for k, v in val.items()} |
| 189 | + |
| 190 | + return normalize_dict_keys(val, model_class) |
162 | 191 |
|
163 | | - normalized_value = normalize_value(value) |
| 192 | + normalized_value = normalize_value(value, cls) |
164 | 193 | obj = handler(normalized_value) |
165 | 194 | assert isinstance(obj, cls) |
166 | 195 | return obj |
|
0 commit comments