Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

InitVar causes exception #425

Open
morrison12 opened this issue Aug 18, 2023 · 3 comments
Open

InitVar causes exception #425

morrison12 opened this issue Aug 18, 2023 · 3 comments
Labels
enhancement New feature or request

Comments

@morrison12
Copy link

I might be misunderstanding the intended use but when I trial to serialise a dataclass containing an InitVar (e.g. as in the example below) I get this exception:

Traceback (most recent call last):
  File ".../examples/ts2.py", line 10, in <module>
    class Foo:
  File ".../lib/python3.10/site-packages/serde/__init__.py", line 180, in serde
    return wrap(_cls)
  File ".../lib/python3.10/site-packages/serde/__init__.py", line 151, in wrap
    if should_impl_dataclass(cls):
  File ".../lib/python3.10/site-packages/serde/core.py", line 888, in should_impl_dataclass
    field_names = [field.name for field in dataclass_fields(cls)]
  File ".../lib/python3.10/site-packages/serde/compat.py", line 331, in dataclass_fields
    raise SerdeError(
serde.compat.SerdeError: Failed to resolve type hints for Foo:
TypeError: Forward references must evaluate to types. Got dataclasses.InitVar[str].

rather than output like:
{"a":1,"b":{"x":"one", "z":"three"},"c":"end"}

from __future__ import annotations
from dataclasses import dataclass, InitVar
from serde import serde
from serde.json import to_json

@serde
@dataclass
class Foo:
    x: str
    y: InitVar[str]
    z: str

    def __post_init__(self, y: str):
        self.z = self.y

@serde
@dataclass
class Bar:
    a: int
    b: Foo
    c: float

print(to_json(Bar(1, Foo("one", "two", "three"), 2.25)))

# with Python 3.10.2 and pyserde==0.12.2 gives
# but would have expect
# {"a":1,"b":{"x":"one", "z":"three"},"c":"end"}

with python 3.10.2 and pyserde==0.12.2

@yukinarit
Copy link
Owner

Hi @morrison12!

Sorry for the delay, it seems there is an issue of InitVar with from __future__ import annotations. Let me look into it.

@yukinarit yukinarit added the bug Bug report or fix label Sep 2, 2023
@yukinarit
Copy link
Owner

It's very interesting

just adding this line resolved the issue!

InitVar.__call__ = lambda *args: None

Running this example, produces this output

from __future__ import annotations
from dataclasses import dataclass, InitVar
from serde import serde
from serde.json import to_json

InitVar.__call__ = lambda *args: None

@serde
@dataclass
class Foo:
    x: str
    y: InitVar[str]
    z: str

    def __post_init__(self, y: str):
        self.z = y

@serde
@dataclass
class Bar:
    a: int
    b: Foo
    c: float

print(to_json(Bar(1, Foo("one", "two", "three"), 2.25)))
$ python 425.py
{"a":1,"b":{"x":"one","z":"two"},"c":2.25}

This behaviour is very well explained this stackoverflow post. For now, please use this workaround. I will try to see if we can have this workaround inside pyserde.

@morrison12
Copy link
Author

Thanks.. The workaround worked like a charm.

@yukinarit yukinarit added enhancement New feature or request and removed bug Bug report or fix labels Sep 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants