Skip to content

FakeHint returned instead of expected type when deserialising with JsonConverter  #12

@callumPearce

Description

@callumPearce
from __future__ import annotations
from dataclasses import dataclass
from typing import Annotated, Any
from databind.core import Context, Converter
from databind.json import JsonConverter, load
from typeapi import TypeHint


@dataclass(frozen=True)
class Inner:
    one: str
    two: str

    def __str__(self) -> str:
        f"{self.one}.{self.two}"

    @classmethod
    def from_string(cls, val: str) -> Inner:
        vals = val.split(".")
        return Inner(one=vals[0], two=vals[1])


class InnerConverter(Converter):
    def convert(self, ctx: Context) -> Any:
        if not isinstance(ctx.value, str):
            raise TypeError("expected a string to deserialize Inner")
        if not isinstance(ctx.datatype, TypeHint):
            raise NotImplementedError
        if ctx.direction.is_serialize():
            return str(ctx.value)
        elif ctx.direction.is_deserialize():
            if isinstance(ctx.value, str):
                return Inner.from_string(ctx.value)
            raise NotImplementedError
        assert False, "invalid direction"


@dataclass(frozen=True)
class Outer:
    number: int
    inner: Annotated[Inner, JsonConverter(InnerConverter)]


dict = {"number": 3, "inner": "hello.world"}
loaded = load(dict, Outer)
if not isinstance(loaded.inner, Inner):
    print(type(loaded.inner))

Expected Behaviour

No output is printed as the inner field has type Inner after being deserialised.

Actual Behaviour

Prints type:

<class 'typeapi.future.fake.FakeHint'>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions