desert icon indicating copy to clipboard operation
desert copied to clipboard

desert crash on optional types when using custom fields

Open sveinse opened this issue 3 years ago • 1 comments

Using an optional field with any custom marshmallow field class cause desert to crash on de-serialization. E.g. a field with b: Optional[B] = desert.ib(BField(), default=None) does not work.

from typing import Optional
import desert
import marshmallow
import attr

class B:
    pass

class BField(marshmallow.fields.Field):
    pass

@attr.s
class A:
    a: int = attr.ib()
    b: Optional[B] = desert.ib(BField(), default=None)

a = A(42)
print(a)

s = desert.schema(A)
d = s.dump(a)
print(d)

a2 = s.load(d)
print(a2)

This results in:

A(a=42, b=None)
{'a': 42, 'b': None}
Traceback (most recent call last):
  File "C:\Svein\Prosjekt\elns\__work\desertbug.py", line 24, in <module>
    a2 = s.load(d)
  File "C:\Svein\Prosjekt\elns\venv\lib\site-packages\marshmallow\schema.py", line 717, in load
    return self._do_load(
  File "C:\Svein\Prosjekt\elns\venv\lib\site-packages\marshmallow\schema.py", line 900, in _do_load
    raise exc
marshmallow.exceptions.ValidationError: {'b': ['Field may not be null.']}

sveinse avatar May 21 '22 17:05 sveinse

I've found a fix or workaround (I'm not sure which it is): If I change to

    b: Optional[B] = desert.ib(BField(allow_none=True), default=None)

I.e. when using custom fields, one must manually declare if the field can be none. The typehint Optional[B] is ignored. So is the consequence of using a custom field that it voids the desert-ness?

sveinse avatar May 22 '22 08:05 sveinse