Skip to content

Commit

Permalink
Enhance Dataclass to unify decorator and class
Browse files Browse the repository at this point in the history
The intention is to avoid having both the `dataclass` decorator and the `Dataclass` which feels a bit redundant.
  • Loading branch information
eos87 committed Dec 2, 2024
1 parent 8108f95 commit e125189
Showing 1 changed file with 32 additions and 8 deletions.
40 changes: 32 additions & 8 deletions superdesk/core/resources/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,27 +65,29 @@ def dataclass(*args, **kwargs):
return pydataclass(*args, **kwargs, config=config)


class Dataclass:
class DataclassBase:
"""Provides type-safe utility methods for Dataclass."""

@model_serializer(mode="wrap")
def ser_model(self, nxt: SerializerFunctionWrapHandler):
aliased_fields = get_model_aliased_fields(self.__class__)
def ser_model(self, nxt: SerializerFunctionWrapHandler) -> dict[str, Any]:
"""
Serialize the model, including extra fields not part of the schema.
"""
result = nxt(self)

# Include extra fields that were not part of the schema for this class
for key, value in self.__dict__.items():
if key not in result and key not in aliased_fields:
# If this key is not already in the result dictionary, and is not an aliased field
# then add it to the key, as an unknown field
if key not in result:
result[key] = value

return result

@classmethod
def from_dict(cls, values: dict[str, Any], **kwargs) -> Self:
def from_dict(cls: type[Self], values: dict[str, Any], **kwargs) -> Self:
return RootModel.model_validate(values, **kwargs).root

@classmethod
def from_json(cls, data: str | bytes | bytearray, **kwargs) -> Self:
def from_json(cls: type[Self], data: str | bytes | bytearray, **kwargs) -> Self:
return RootModel.model_validate_json(data, **kwargs).root

def to_dict(self, **kwargs) -> dict[str, Any]:
Expand All @@ -99,6 +101,28 @@ def to_json(self, **kwargs) -> str:
return RootModel(self).model_dump_json(**default_params)


class DataclassMeta(type):
"""Metaclass to enhance Dataclass functionality."""

def __new__(cls, name, bases, dct):
custom_config = dct.pop("Config", {})

# merge with default configuration
config = deepcopy(default_model_config)
config.update(custom_config)

# create the class and apply the Pydantic dataclass decorator
new_cls = super().__new__(cls, name, bases, dct)
new_cls = pydataclass(new_cls, config=config)
return new_cls


class Dataclass(DataclassBase, metaclass=DataclassMeta):
"""Unified base class for dataclasses with Pydantic features."""

pass


class ResourceModel(BaseModel):
"""Base ResourceModel class to be used for all registered resources"""

Expand Down

0 comments on commit e125189

Please sign in to comment.