Skip to content

Commit

Permalink
Fix generic merged field in 3.6
Browse files Browse the repository at this point in the history
  • Loading branch information
wyfo committed Oct 15, 2020
1 parent 3f6c4b9 commit b6d12bd
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 9 deletions.
14 changes: 7 additions & 7 deletions apischema/dataclasses/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,9 +390,13 @@ def _serialization(
)


def _deserialization_merged_aliases(cls: Type) -> AbstractSet[str]:
def _deserialization_merged_aliases(cls: Type, field_name: str) -> AbstractSet[str]:
"""Return all aliases used in cls deserialization."""
cls = getattr(cls, "__origin__", None) or cls
if not dataclasses.is_dataclass(cls):
raise TypeError(
f"{cls.__name__}.{field_name}: Merged field must have a dataclass type"
)
types = get_type_hints(cls, include_extras=True)
result: Set[str] = set()
for field in fields_items(cls).values():
Expand All @@ -401,7 +405,7 @@ def _deserialization_merged_aliases(cls: Type) -> AbstractSet[str]:
if MERGED_METADATA in field.metadata:
# No need to check overlapping here because it will be checked
# when merged dataclass will be cached
result |= _deserialization_merged_aliases(types[field.name])
result |= _deserialization_merged_aliases(types[field.name], field.name)
elif PROPERTIES_METADATA in field.metadata:
raise TypeError("Merged dataclass cannot have properties field")
else:
Expand Down Expand Up @@ -530,11 +534,7 @@ def cache_fields(cls: Type):
if MERGED_METADATA in metadata:
if any(key in metadata for key in INCOMPATIBLE_WITH_MERGED):
raise TypeError(f"{error_prefix}Incompatible metadata with merged")
if not dataclasses.is_dataclass(field_type):
raise TypeError(
f"{error_prefix}Merged field must have a dataclass type"
)
merged_aliases = _deserialization_merged_aliases(field_type)
merged_aliases = _deserialization_merged_aliases(field_type, field.name)
lists.merged.append((merged_aliases, new_field))
elif PROPERTIES_METADATA in metadata:
if any(key in metadata for key in INCOMPATIBLE_WITH_PROPERTIES):
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setup(
name="apischema",
version="0.10.1",
version="0.10.2",
url="https://github.com/wyfo/apischema",
author="Joseph Perez",
author_email="[email protected]",
Expand Down
2 changes: 1 addition & 1 deletion tests/test_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ class D(Generic[T]):


def test_merged_aliases():
assert _deserialization_merged_aliases(A) == {"a", "g", "h", "i", "e"}
assert _deserialization_merged_aliases(A, "") == {"a", "g", "h", "i", "e"}
23 changes: 23 additions & 0 deletions tests/test_metadata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from dataclasses import dataclass, field
from typing import Generic, TypeVar

from apischema import deserialize
from apischema.metadata import merged

T = TypeVar("T")


@dataclass
class A(Generic[T]):
pass


@dataclass
class B(Generic[T]):
a1: A = field(metadata=merged)
a2: A[T] = field(metadata=merged)
a3: A[int] = field(metadata=merged)


def test_merged_generic_dataclass():
deserialize(B, {}) # it works

0 comments on commit b6d12bd

Please sign in to comment.