Skip to content

Commit

Permalink
Add msgpack mixin to dbtClassMixin (#125)
Browse files Browse the repository at this point in the history
* Add msgpack mixin to dbtClassMixin

* missing Optional

* Changie
  • Loading branch information
gshank authored May 7, 2024
1 parent f0e2df6 commit f89a516
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 14 deletions.
6 changes: 6 additions & 0 deletions .changes/unreleased/Features-20240506-170058.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: Features
body: Enable serialization contexts
time: 2024-05-06T17:00:58.272104-04:00
custom:
Author: gshank
Issue: "126"
10 changes: 5 additions & 5 deletions dbt_common/contracts/config/properties.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from dataclasses import dataclass, field
from typing import Dict, Any
from typing import Dict, Any, Optional

from dbt_common.dataclass_schema import ExtensibleDbtClassMixin
from dbt_common.dataclass_schema import ExtensibleDbtClassMixin, dbtClassMixin


class AdditionalPropertiesMixin:
class AdditionalPropertiesMixin(dbtClassMixin):
"""Make this class an extensible property.
The underlying class definition must include a type definition for a field
Expand Down Expand Up @@ -41,8 +41,8 @@ def __pre_deserialize__(cls, data):
data = super().__pre_deserialize__(data)
return data

def __post_serialize__(self, dct):
data = super().__post_serialize__(dct)
def __post_serialize__(self, dct: Dict, context: Optional[Dict] = None):
data = super().__post_serialize__(dct, context)
data.update(self.extra)
if "_extra" in data:
del data["_extra"]
Expand Down
16 changes: 12 additions & 4 deletions dbt_common/dataclass_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,17 @@
from dateutil.parser import parse

# type: ignore
from mashumaro import DataClassDictMixin
from mashumaro.config import TO_DICT_ADD_OMIT_NONE_FLAG, BaseConfig as MashBaseConfig
from mashumaro.config import (
TO_DICT_ADD_OMIT_NONE_FLAG,
ADD_SERIALIZATION_CONTEXT,
BaseConfig as MashBaseConfig,
)
from mashumaro.types import SerializableType, SerializationStrategy
from mashumaro.jsonschema import build_json_schema

# following includes DataClassDictMixin
from mashumaro.mixins.msgpack import DataClassMessagePackMixin

import functools


Expand All @@ -34,6 +40,7 @@ def deserialize(self, value) -> datetime:
class dbtMashConfig(MashBaseConfig):
code_generation_options = [
TO_DICT_ADD_OMIT_NONE_FLAG,
ADD_SERIALIZATION_CONTEXT,
]
serialization_strategy = {
datetime: DateTimeSerialization(),
Expand All @@ -47,7 +54,8 @@ class dbtMashConfig(MashBaseConfig):

# This class pulls in DataClassDictMixin from Mashumaro. The 'to_dict'
# and 'from_dict' methods come from Mashumaro.
class dbtClassMixin(DataClassDictMixin):
# Note: DataClassMessagePackMixin inherits from DataClassDictMixin
class dbtClassMixin(DataClassMessagePackMixin):
"""Convert and validate JSON schemas.
The Mixin adds methods to generate a JSON schema and
Expand All @@ -73,7 +81,7 @@ def __pre_deserialize__(cls, data):
# This is called by the mashumaro to_dict in order to handle
# nested classes. We no longer do any munging here, but leaving here
# so that subclasses can leave super() in place for possible future needs.
def __post_serialize__(self, data):
def __post_serialize__(self, data, context: Optional[Dict]):
return data

@classmethod
Expand Down
42 changes: 42 additions & 0 deletions tests/unit/test_dataclass_schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from dataclasses import dataclass
from typing import Dict, Optional

from dbt_common.dataclass_schema import dbtClassMixin


@dataclass
class MySubObject(dbtClassMixin):
name: str

def __post_serialize__(self, dct: Dict, context: Optional[Dict] = None):
if context and "artifact" in context:
dct["name"] = "xxxx"
return dct


@dataclass
class MyObject(dbtClassMixin):
sub_object: MySubObject
unique_id: str

def __post_serialize__(self, dct: Dict, context: Optional[Dict] = None):
if context and "artifact" in context:
dct["unique_id"] = "my.xxxx.object"
return dct


def test_serialization_context():
sub_obj = MySubObject("testing")

obj = MyObject(sub_object=sub_obj, unique_id="my.test.object")

assert obj

dct = obj.to_dict()
assert dct == {"unique_id": "my.test.object", "sub_object": {"name": "testing"}}

mod_dct = obj.to_dict(context={"artifact": True})
assert mod_dct == {"unique_id": "my.xxxx.object", "sub_object": {"name": "xxxx"}}

obj = MyObject.from_dict(dct)
assert obj.sub_object.name == "testing"
4 changes: 2 additions & 2 deletions third-party-stubs/mashumaro/jsonschema/models.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ class JSONSchema(DataClassJSONMixin):
serialize_by_alias: bool
aliases: Incomplete
serialization_strategy: Incomplete
def __pre_serialize__(self) -> JSONSchema: ...
def __post_serialize__(self, d: Dict[Any, Any]) -> Dict[Any, Any]: ...
def __pre_serialize__(self, context: Optional[Dict]) -> JSONSchema: ...
def __post_serialize__(self, d: Dict[Any, Any], context: Optional[Dict]) -> Dict[Any, Any]: ...
def __init__(
self,
schema,
Expand Down
6 changes: 3 additions & 3 deletions third-party-stubs/mashumaro/mixins/dict.pyi
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Dict, Mapping, Type, TypeVar
from typing import Any, Dict, Mapping, Type, TypeVar, Optional

T = TypeVar("T", bound="DataClassDictMixin")

Expand All @@ -11,5 +11,5 @@ class DataClassDictMixin:
def __pre_deserialize__(cls: Type[T], d: Dict[Any, Any]) -> Dict[Any, Any]: ...
@classmethod
def __post_deserialize__(cls: Type[T], obj: T) -> T: ...
def __pre_serialize__(self: T) -> T: ...
def __post_serialize__(self, d: Dict[Any, Any]) -> Dict[Any, Any]: ...
def __pre_serialize__(self: T, context: Optional[Dict]) -> T: ...
def __post_serialize__(self, d: Dict[Any, Any], context: Optional[Dict]) -> Dict[Any, Any]: ...

0 comments on commit f89a516

Please sign in to comment.