Skip to content

Commit

Permalink
Fix using Optional in named tuples
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexander Tikhonov committed Mar 20, 2022
1 parent a40ac29 commit 15d002e
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 6 deletions.
2 changes: 2 additions & 0 deletions mashumaro/core/meta/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -1726,6 +1726,7 @@ def _pack_named_tuple(
parent,
f"{value_name}[{idx}]",
metadata=metadata,
could_be_none=True,
)
packers.append(packer)
if as_dict:
Expand Down Expand Up @@ -1762,6 +1763,7 @@ def _unpack_named_tuple(
parent,
f"{value_name}[{idx}]",
metadata=metadata,
could_be_none=True,
)
unpackers.append(unpacker)

Expand Down
5 changes: 5 additions & 0 deletions tests/entities.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,11 @@ class MyNamedTupleWithDefaults(NamedTuple):
f: float = 2.0


class MyNamedTupleWithOptional(NamedTuple):
i: Optional[int]
f: int


MyUntypedNamedTuple = namedtuple("MyUntypedNamedTuple", ("i", "f"))


Expand Down
32 changes: 26 additions & 6 deletions tests/test_data_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
MyIntFlag,
MyNamedTuple,
MyNamedTupleWithDefaults,
MyNamedTupleWithOptional,
MyStrEnum,
MyUntypedNamedTuple,
SerializableTypeDataClass,
Expand Down Expand Up @@ -1241,18 +1242,37 @@ def test_tuple_with_optional():
class DataClass(DataClassDictMixin):
x: Tuple[Optional[int], int] = field(default_factory=lambda: (None, 7))

assert DataClass.from_dict({'x': [None, 42]}) == DataClass((None, 42))
assert DataClass((None, 42)).to_dict() == {'x': [None, 42]}
assert DataClass.from_dict({"x": [None, 42]}) == DataClass((None, 42))
assert DataClass((None, 42)).to_dict() == {"x": [None, 42]}
assert DataClass.from_dict({}) == DataClass((None, 7))
assert DataClass().to_dict() == {'x': [None, 7]}
assert DataClass().to_dict() == {"x": [None, 7]}


def test_tuple_with_optional_and_ellipsis():
@dataclass
class DataClass(DataClassDictMixin):
x: Tuple[Optional[int], ...] = field(default_factory=lambda: (None, 7))

assert DataClass.from_dict({'x': [None, 42]}) == DataClass((None, 42))
assert DataClass((None, 42)).to_dict() == {'x': [None, 42]}
assert DataClass.from_dict({"x": [None, 42]}) == DataClass((None, 42))
assert DataClass((None, 42)).to_dict() == {"x": [None, 42]}
assert DataClass.from_dict({}) == DataClass((None, 7))
assert DataClass().to_dict() == {'x': [None, 7]}
assert DataClass().to_dict() == {"x": [None, 7]}


def test_named_tuple_with_optional():
@dataclass
class DataClass(DataClassDictMixin):
x: MyNamedTupleWithOptional = field(
default_factory=lambda: MyNamedTupleWithOptional(None, 7)
)

assert DataClass.from_dict({"x": [None, 42]}) == DataClass(
MyNamedTupleWithOptional(None, 42)
)
assert DataClass(MyNamedTupleWithOptional(None, 42)).to_dict() == {
"x": [None, 42]
}
assert DataClass.from_dict({}) == DataClass(
MyNamedTupleWithOptional(None, 7)
)
assert DataClass().to_dict() == {"x": [None, 7]}

0 comments on commit 15d002e

Please sign in to comment.