Pydantic: Support NamedTuples

Created on 19 Mar 2020  路  6Comments  路  Source: samuelcolvin/pydantic

Feature Request

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 
feature request

Most helpful comment

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

All 6 comments

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

Was this page helpful?
0 / 5 - 0 ratings

Related issues

gangefors picture gangefors  路  3Comments

iwoloschin picture iwoloschin  路  3Comments

mgresko picture mgresko  路  3Comments

dconathan picture dconathan  路  3Comments

sbv-trueenergy picture sbv-trueenergy  路  3Comments