|
4 | 4 | from collections.abc import Callable, Iterable, Mapping |
5 | 5 | from typing import TYPE_CHECKING, Any, Final, Literal, TypeVar |
6 | 6 |
|
7 | | -from attrs import NOTHING, Attribute, Factory |
| 7 | +from attrs import NOTHING, Attribute, Converter, Factory |
8 | 8 | from typing_extensions import NoDefault |
9 | 9 |
|
10 | 10 | from .._compat import ( |
@@ -99,6 +99,10 @@ def make_dict_unstructure_fn_from_attrs( |
99 | 99 | .. versionchanged:: 25.2.0 |
100 | 100 | The `_cattrs_use_alias` parameter takes its value from the given converter |
101 | 101 | by default. |
| 102 | + .. versionchanged:: NEXT |
| 103 | + When `_cattrs_omit_if_default` is true and the attribute has an attrs converter |
| 104 | + specified, the converter is applied to the default value before checking if it |
| 105 | + is equal to the attribute's value. |
102 | 106 | """ |
103 | 107 |
|
104 | 108 | fn_name = "unstructure_" + cl.__name__ |
@@ -177,16 +181,32 @@ def make_dict_unstructure_fn_from_attrs( |
177 | 181 | if isinstance(d, Factory): |
178 | 182 | globs[def_name] = d.factory |
179 | 183 | internal_arg_parts[def_name] = d.factory |
180 | | - if d.takes_self: |
181 | | - lines.append(f" if instance.{attr_name} != {def_name}(instance):") |
182 | | - else: |
183 | | - lines.append(f" if instance.{attr_name} != {def_name}():") |
184 | | - lines.append(f" res['{kn}'] = {invoke}") |
| 184 | + def_str = f"{def_name}(instance)" if d.takes_self else f"{def_name}()" |
185 | 185 | else: |
186 | 186 | globs[def_name] = d |
187 | 187 | internal_arg_parts[def_name] = d |
188 | | - lines.append(f" if instance.{attr_name} != {def_name}:") |
189 | | - lines.append(f" res['{kn}'] = {invoke}") |
| 188 | + def_str = def_name |
| 189 | + |
| 190 | + c = a.converter |
| 191 | + if c is not None: |
| 192 | + conv_name = f"__c_conv_{attr_name}" |
| 193 | + if isinstance(c, Converter): |
| 194 | + globs[conv_name] = c |
| 195 | + internal_arg_parts[conv_name] = c |
| 196 | + field_name = f"__c_field_{attr_name}" |
| 197 | + globs[field_name] = a |
| 198 | + internal_arg_parts[field_name] = a |
| 199 | + def_str = f"{conv_name}({def_str}, instance, {field_name})" |
| 200 | + elif isinstance(d, Factory): |
| 201 | + globs[conv_name] = c |
| 202 | + internal_arg_parts[conv_name] = c |
| 203 | + def_str = f"{conv_name}({def_str})" |
| 204 | + else: |
| 205 | + globs[def_name] = c(d) |
| 206 | + internal_arg_parts[def_name] = c(d) |
| 207 | + |
| 208 | + lines.append(f" if instance.{attr_name} != {def_str}:") |
| 209 | + lines.append(f" res['{kn}'] = {invoke}") |
190 | 210 |
|
191 | 211 | else: |
192 | 212 | # No default or no override. |
|
0 commit comments