1313 pre_load ,
1414 validate ,
1515)
16+ from typing_extensions import Self
1617
1718from .config import DOCUMENT_SIZE_THRESHOLD_BYTES , MULTI_DOCUMENT_LIMIT
1819
1920
21+ class ToDictMixin :
22+ """
23+ Provides a type-safe `to_dict()` method for classes using Marshmallow
24+ """
25+
26+ SCHEMA : ClassVar [Schema ]
27+
28+ def to_dict (self ) -> Dict [str , Any ]:
29+ return cast (Dict [str , Any ], self .SCHEMA .dump (self ))
30+
31+
32+ class FromDictMixin :
33+ """This class must be used as an additional base class for all classes whose schema
34+ implements a `post_load` function turning the received dict into a class instance.
35+
36+ It makes it possible to deserialize an object using `MyClass.from_dict(dct)` instead
37+ of `MyClass.SCHEMA.load(dct)`. The `from_dict()` method is shorter, but more
38+ importantly, type-safe: its return type is an instance of `MyClass`, not
39+ `list[Any] | Any`.
40+
41+ Reference: https://marshmallow.readthedocs.io/en/stable/quickstart.html#deserializing-to-objects E501
42+ """
43+
44+ SCHEMA : ClassVar [Schema ]
45+
46+ @classmethod
47+ def from_dict (cls , dct : Dict [str , Any ]) -> Self :
48+ return cast (Self , cls .SCHEMA .load (dct ))
49+
50+
2051class BaseSchema (Schema ):
2152 class Meta :
2253 ordered = True
2354 unknown = EXCLUDE
2455
2556
26- class Base :
27- SCHEMA : ClassVar [BaseSchema ]
28-
57+ class Base (ToDictMixin ):
2958 def __init__ (self , status_code : Optional [int ] = None ) -> None :
3059 self .status_code = status_code
3160
@@ -35,12 +64,6 @@ def to_json(self) -> str:
3564 """
3665 return cast (str , self .SCHEMA .dumps (self ))
3766
38- def to_dict (self ) -> Dict :
39- """
40- to_dict converts model to a dictionary representation.
41- """
42- return cast (Dict , self .SCHEMA .dump (self ))
43-
4467 @property
4568 def success (self ) -> bool :
4669 return self .__bool__ ()
@@ -122,7 +145,7 @@ def make_detail_response(self, data: Dict[str, Any], **kwargs: Any) -> "Detail":
122145 return Detail (** data )
123146
124147
125- class Detail (Base ):
148+ class Detail (Base , FromDictMixin ):
126149 """Detail is a response object mostly returned on error or when the
127150 api output is a simple string.
128151
@@ -155,7 +178,7 @@ def make_match(self, data: Dict[str, Any], **kwargs: Any) -> "Match":
155178 return Match (** data )
156179
157180
158- class Match (Base ):
181+ class Match (Base , FromDictMixin ):
159182 """
160183 Match describes a found issue by GitGuardian.
161184 With info such as match location and type.
@@ -219,7 +242,7 @@ def make_policy_break(self, data: Dict[str, Any], **kwargs: Any) -> "PolicyBreak
219242 return PolicyBreak (** data )
220243
221244
222- class PolicyBreak (Base ):
245+ class PolicyBreak (Base , FromDictMixin ):
223246 """
224247 PolicyBreak describes a GitGuardian policy break found
225248 in a scan.
@@ -269,7 +292,7 @@ def make_scan_result(self, data: Dict[str, Any], **kwargs: Any) -> "ScanResult":
269292 return ScanResult (** data )
270293
271294
272- class ScanResult (Base ):
295+ class ScanResult (Base , FromDictMixin ):
273296 """ScanResult is a response object returned on a Content Scan
274297
275298 Attributes:
@@ -355,7 +378,7 @@ def make_scan_result(
355378 return MultiScanResult (** data )
356379
357380
358- class MultiScanResult (Base ):
381+ class MultiScanResult (Base , FromDictMixin ):
359382 """ScanResult is a response object returned on a Content Scan
360383
361384 Attributes:
@@ -425,7 +448,7 @@ def make_quota(self, data: Dict[str, Any], **kwargs: Any) -> "Quota":
425448 return Quota (** data )
426449
427450
428- class Quota (Base ):
451+ class Quota (Base , FromDictMixin ):
429452 """
430453 Quota describes a quota category in the GitGuardian API.
431454 Allows you to check your current available quota.
@@ -468,7 +491,7 @@ def make_quota_response(
468491 return QuotaResponse (** data )
469492
470493
471- class QuotaResponse (Base ):
494+ class QuotaResponse (Base , FromDictMixin ):
472495 """
473496 Quota describes a quota category in the GitGuardian API.
474497 Allows you to check your current available quota.
@@ -515,7 +538,7 @@ def make_honeytoken_response(
515538 return HoneytokenResponse (** data )
516539
517540
518- class HoneytokenResponse (Base ):
541+ class HoneytokenResponse (Base , FromDictMixin ):
519542 """
520543 honeytoken creation in the GitGuardian API.
521544 Allows users to create and get a honeytoken.
@@ -633,14 +656,15 @@ class SecretScanPreferences:
633656
634657
635658@dataclass
636- class ServerMetadata (Base ):
659+ class ServerMetadata (Base , FromDictMixin ):
637660 version : str
638661 preferences : Dict [str , Any ]
639662 secret_scan_preferences : SecretScanPreferences = field (
640663 default_factory = SecretScanPreferences
641664 )
642665
643666
644- ServerMetadata .SCHEMA = marshmallow_dataclass .class_schema (
645- ServerMetadata , base_schema = BaseSchema
646- )()
667+ ServerMetadata .SCHEMA = cast (
668+ BaseSchema ,
669+ marshmallow_dataclass .class_schema (ServerMetadata , base_schema = BaseSchema )(),
670+ )
0 commit comments