-
-
Notifications
You must be signed in to change notification settings - Fork 47
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
Generic dataclasses with Hashable typevar bound do not work #170
Comments
Unbounded from dataclasses import dataclass
from typing import Generic, Hashable, TypeVar
from mashumaro import pass_through
from mashumaro.config import BaseConfig
from mashumaro.mixins.dict import DataClassDictMixin
T_b = TypeVar("T_b", bound=Hashable)
@dataclass
class Bar(
Generic[T_b], DataClassDictMixin
):
bar: T_b
class Config(BaseConfig):
serialization_strategy = {
Hashable: pass_through
} |
Got it. I see where this is coming from historically. Seems like either no one even bothered, or no one ever uses Generic base classes directly, instead specifying ser_strategy for different concrete versions...or no one ever used that with non serializable types...because the current logic does exhibit an "unexpected" behavior: from dataclasses import dataclass
from datetime import datetime
from typing import Generic, Hashable, TypeVar
from mashumaro.mixins.json import DataClassJSONMixin
T = TypeVar("T")
@dataclass
class Foo(Generic[T], DataClassJSONMixin):
foo: T
FooStr = Foo[str]
FooDict = Foo[datetime]
print(FooStr(foo="foo").to_json())
print(FooDict(foo=datetime.now()).to_json()) # TypeError: Object of type datetime is not JSON serializable mashumaro is perfectly capable of handling datetime, but not in this case... One way would be to stop making assumptions and only create serialization methods on concrete versions (I haven't played with it, but probably it can be handled by overriding Another is to treat any unsupported bound as Any. Supported as in - out of the box, or via serialization strategy. I think this approach should not break any existing code, and unify the behavior. Not doing anything is also an option. In my case using a config is perfectly fine. Thanks for the tip here. |
You're right. This library is based on pre-compilation of (de)serialization method for concrete models. I have written about generic dataclass usage patterns here, but basically you need a new class that will keep its FooStr = Foo[str]
FooDict = Foo[datetime] there can't be different
You can play with from dataclasses import dataclass
from datetime import datetime
from typing import Generic, TypeVar
from mashumaro.codecs.json import JSONEncoder, json_encode
T = TypeVar("T")
@dataclass
class Foo(Generic[T]):
foo: T
FooDict = Foo[datetime]
json_encoder = JSONEncoder(FooDict)
print(json_encoder.encode(FooDict(datetime.now())))
# or for one-time encoding:
print(json_encode(FooDict(datetime.now()), FooDict))
I like the idea of using |
Description
Apparently adding a bound to TypeVar breaks mashumaro:
although the second one is obviously a narrower type, so if the first one is ok, the second should definitely be fine.
The text was updated successfully, but these errors were encountered: