Python's typing library has a nice type called NamedTuple, which doesn't seem to be supported.
from pydantic import BaseModel
from typing import List, NamedTuple
class Event(NamedTuple):
a: int
b: int
c: str
class Message(BaseModel):
events: List[Event]
msg = Message.parse_raw(b'{"events": [[1,2, "c"]]}')
# will raise exception because it's a regular tuple and not a named one.
msg.events[0].a
The best solution is to use pydantic's dataclass.
Named tuples are a hacky mess which are effectively superceded by dataclasses, so I'm not that keen to support them, but we do need a solution to support (or explicitly reject) standard dataclasses at types.
I'll consider this of it gets a large number of up votes.
The best solution is to use pydantic's
dataclass.Named tuples are a hacky mess which are effectively superceded by dataclasses, so I'm not that keen to support them, but we do need a solution to support (or explicitly reject) standard dataclasses at types.
I don't care too much about NamedTuple, rather then by the use case they provide.
I want load a tuple with static order and have each item a name for easy access.
Dataclasses doesn't provide this, atleast not when used with Pydantic.
If you have another suggestion how to solve that use case it'd be great :)
There is a workaround that allows you to do exactly what you want. I extended it a little to also include optional fields.
class Event(NamedTuple):
a: int
b: int
c: Optional[str] = None
EventType = Union[Tuple[int, int, str], Tuple[int, int]]
class Message(BaseModel):
events: List[EventType]
message_a = Message(events=[[1,1,'Hello']])
message_b = Message(events=[Event(a=1, b=1, c='World')])
message_a.events[0].a will still raise an error, but message_b.events[0].a works. Most importantly serialization doesn't throw an error anymore. Works for me, hope it works for you also. Proper support for NamedTuples would be preferred though.
my temporaty solution:
Position = namedtuple("Pos", "x y")
class Model(BaseModel):
tmp_pos: tuple = Field(..., alias="pos")
@property
def pos(self):
return Position(*self.tmp_pos)
m = Model(**{"pos": [1, 2]})
m.json(by_alias=True) # out: {"pos": [1, 2]}
Adding basic support for NamedTuple is easy and doesn't cost much. Seeing the large number of up votes, I reckon it can be added. I opened a PR for this. Feedback more than welcome
Most helpful comment
Adding basic support for
NamedTupleis easy and doesn't cost much. Seeing the large number of up votes, I reckon it can be added. I opened a PR for this. Feedback more than welcome