Last active
July 3, 2023 19:34
-
-
Save cwells/5ace2c66d8f6ddfdbc9407293dec7813 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import json | |
from typing import Any, TypedDict, Union, Callable, Optional | |
from typeguard import CollectionCheckStrategy, check_type | |
Serializer = Optional[Callable] | |
def typed_object_factory(object_type: Any, serializer: Serializer=None): | |
class TypedObject: | |
def __init__(self, obj: Any) -> None: | |
self.object_type: Any = object_type | |
self._serializer: Serializer = serializer | |
self._object: Any = self.validate(obj) | |
def validate(self, value: Any) -> Any: | |
check_type( | |
value, | |
self.object_type, | |
collection_check_strategy=CollectionCheckStrategy.ALL_ITEMS, | |
) | |
return value | |
def serialize(self): | |
if self._serializer: | |
return self._serializer(self._object) | |
raise NotImplementedError("No serializer defined.") | |
return TypedObject | |
class TagType(TypedDict): | |
name: str | |
value: Union[str, int] | |
class ThingType(TypedDict): | |
name: str | |
id: int | |
tags: list[TagType] | |
Thing: object = typed_object_factory(ThingType, serializer=lambda v: json.dumps(v, indent=2)) | |
thing: Thing = Thing( # succeeds | |
{ | |
"name": "Foobar 2000", | |
"id": 100, | |
"tags": [ | |
{"name": "industry", "value": "Foo"}, | |
{"name": "utility", "value": "Foo preparation"}, | |
] | |
} | |
) | |
print(thing.serialize()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment