Skip to content

Instantly share code, notes, and snippets.

@viniciusao
Last active July 4, 2023 23:14
Show Gist options
  • Save viniciusao/4861a111eb2ab51b06d535e5623e2dbe to your computer and use it in GitHub Desktop.
Save viniciusao/4861a111eb2ab51b06d535e5623e2dbe to your computer and use it in GitHub Desktop.
typing.NamedTuple with pydantic.
from contextlib import suppress
from typing import NamedTuple
from pydantic import create_model_from_namedtuple, BaseModel, root_validator
class FunctionNumber101(NamedTuple):
width: float
height: float
def area(cls, values=None):
try:
values = cls._asdict()
except AttributeError:
values = {x: y for x, y in zip(cls.__fields__, values.values())}
if values['width'] <= 0 or values['height'] <= 0:
raise ValueError("width and height must be positive")
if not hasattr(cls, '__fields__'):
return values['width'] * values['height']
return values
def namedtuple_to_basemodel(nt, *args):
nt_methods = {}
nt_input = {x: y for x, y in zip(nt._fields, args)}
tuple_methods = 'count', 'index'
for method_name in dir(nt):
method = getattr(nt, method_name)
callable_ = callable(method)
not_tuple_method = method_name not in tuple_methods
if method_name.isalpha() and callable_ and not_tuple_method:
nt_methods[method_name] = root_validator(method)
pydantic_model = create_model_from_namedtuple(nt, __validators__=nt_methods)
return pydantic_model(**nt_input)
def get_rectangle_area(width: float, height: float):
model = namedtuple_to_basemodel(FunctionNumber101, width, height)
assert isinstance(model, BaseModel)
get_rectangle_area(10, 1)
square = FunctionNumber101(10, 10)
assert square.area() == 100
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment