|
10 | 10 | from lazy_object_proxy import Proxy
|
11 | 11 |
|
12 | 12 | from spec_classes.errors import FrozenInstanceError
|
13 |
| -from spec_classes.types import MISSING, Attr |
| 13 | +from spec_classes.types import EMPTY, MISSING, UNCHANGED, Attr |
14 | 14 |
|
15 | 15 | from .type_checking import check_type, type_label
|
16 | 16 |
|
@@ -94,7 +94,7 @@ def mutate_attr(
|
94 | 94 | instance. If `inplace` is `False`, copy the instance before assigning
|
95 | 95 | the new attribute value.
|
96 | 96 | """
|
97 |
| - if value is MISSING: |
| 97 | + if value in (MISSING, EMPTY, UNCHANGED): |
98 | 98 | return obj
|
99 | 99 |
|
100 | 100 | metadata = getattr(obj, "__spec_class__", None)
|
@@ -217,14 +217,17 @@ def mutate_value(
|
217 | 217 | Returns:
|
218 | 218 | The mutated object.
|
219 | 219 | """
|
| 220 | + if new_value is UNCHANGED: |
| 221 | + return old_value.__wrapped__ if isinstance(old_value, Proxy) else old_value |
| 222 | + |
220 | 223 | mutate_safe = inplace
|
221 | 224 | used_attrs = set()
|
222 | 225 |
|
223 | 226 | # If `new_value` is not `MISSING`, use it; otherwise use `old_value` if not
|
224 | 227 | # `replace`; otherwise use MISSING.
|
225 |
| - if new_value is not MISSING: |
| 228 | + if new_value not in (MISSING, EMPTY, UNCHANGED): |
226 | 229 | value = new_value
|
227 |
| - elif not replace: |
| 230 | + elif new_value is UNCHANGED or not replace: |
228 | 231 | value = old_value
|
229 | 232 | prepare = None # Old values have already been prepared, so we suppress further preparation.
|
230 | 233 | else:
|
@@ -275,7 +278,7 @@ def mutate_value(
|
275 | 278 | value = constructor()
|
276 | 279 |
|
277 | 280 | # If there are any left-over attributes to apply to our value, we do so here.
|
278 |
| - if value is not None and value is not MISSING and attrs: |
| 281 | + if value not in (None, MISSING) and attrs: |
279 | 282 | if not mutate_safe:
|
280 | 283 | value = protect_via_deepcopy(value)
|
281 | 284 | mutate_safe = True
|
|
0 commit comments