44from dataclasses import dataclass , field
55from datetime import date , datetime
66from enum import Enum
7- from typing import (
8- TYPE_CHECKING ,
9- Any ,
10- ClassVar ,
11- Dict ,
12- Generic ,
13- List ,
14- Literal ,
15- Optional ,
16- Type ,
17- TypeVar ,
18- cast ,
19- )
7+ from typing import Any , Dict , List , Literal , Optional , Type , cast
208from uuid import UUID
219
2210import marshmallow_dataclass
2311from marshmallow import (
24- EXCLUDE ,
25- Schema ,
2612 ValidationError ,
2713 fields ,
2814 post_dump ,
2915 post_load ,
3016 pre_load ,
3117 validate ,
3218)
33- from typing_extensions import Self
3419
3520from .config import (
3621 DEFAULT_PRE_COMMIT_MESSAGE ,
3924 DOCUMENT_SIZE_THRESHOLD_BYTES ,
4025 MULTI_DOCUMENT_LIMIT ,
4126)
42-
43-
44- if TYPE_CHECKING :
45- import requests
46-
47-
48- class ToDictMixin :
49- """
50- Provides a type-safe `to_dict()` method for classes using Marshmallow
51- """
52-
53- SCHEMA : ClassVar [Schema ]
54-
55- def to_dict (self ) -> Dict [str , Any ]:
56- return cast (Dict [str , Any ], self .SCHEMA .dump (self ))
57-
58-
59- class FromDictMixin :
60- """This class must be used as an additional base class for all classes whose schema
61- implements a `post_load` function turning the received dict into a class instance.
62-
63- It makes it possible to deserialize an object using `MyClass.from_dict(dct)` instead
64- of `MyClass.SCHEMA.load(dct)`. The `from_dict()` method is shorter, but more
65- importantly, type-safe: its return type is an instance of `MyClass`, not
66- `list[Any] | Any`.
67-
68- Reference: https://marshmallow.readthedocs.io/en/stable/quickstart.html#deserializing-to-objects E501
69- """
70-
71- SCHEMA : ClassVar [Schema ]
72-
73- @classmethod
74- def from_dict (cls , dct : Dict [str , Any ]) -> Self :
75- return cast (Self , cls .SCHEMA .load (dct ))
76-
77-
78- class BaseSchema (Schema ):
79- class Meta :
80- ordered = True
81- unknown = EXCLUDE
82-
83-
84- class Base (ToDictMixin ):
85- def __init__ (self , status_code : Optional [int ] = None ) -> None :
86- self .status_code = status_code
87-
88- def to_json (self ) -> str :
89- """
90- to_json converts model to JSON string.
91- """
92- return cast (str , self .SCHEMA .dumps (self ))
93-
94- @property
95- def success (self ) -> bool :
96- return self .__bool__ ()
97-
98- def __bool__ (self ) -> bool :
99- return self .status_code == 200
27+ from .models_utils import (
28+ Base ,
29+ BaseSchema ,
30+ FromDictMixin ,
31+ PaginationParameter ,
32+ SearchParameter ,
33+ ToDictMixin ,
34+ )
10035
10136
10237class DocumentSchema (BaseSchema ):
@@ -1148,44 +1083,6 @@ class AccessLevel(str, Enum):
11481083 RESTRICTED = "restricted"
11491084
11501085
1151- class PaginationParameter (ToDictMixin ):
1152- """Pagination mixin used for endpoints that support pagination."""
1153-
1154- cursor : str = ""
1155- per_page : int = 20
1156-
1157-
1158- class SearchParameter (ToDictMixin ):
1159- search : Optional [str ] = None
1160-
1161-
1162- PaginatedData = TypeVar ("PaginatedData" , bound = FromDictMixin )
1163-
1164-
1165- @dataclass
1166- class CursorPaginatedResponse (Generic [PaginatedData ]):
1167- status_code : int
1168- data : List [PaginatedData ]
1169- prev : Optional [str ] = None
1170- next : Optional [str ] = None
1171-
1172- @classmethod
1173- def from_response (
1174- cls , response : "requests.Response" , data_type : Type [PaginatedData ]
1175- ) -> "CursorPaginatedResponse[PaginatedData]" :
1176- data = cast (
1177- List [PaginatedData ], [data_type .from_dict (obj ) for obj in response .json ()]
1178- )
1179- paginated_response = cls (status_code = response .status_code , data = data )
1180-
1181- if previous_page := response .links .get ("prev" ):
1182- paginated_response .prev = previous_page ["url" ]
1183- if next_page := response .links .get ("next" ):
1184- paginated_response .prev = next_page ["url" ]
1185-
1186- return paginated_response
1187-
1188-
11891086@dataclass
11901087class MembersParameters (PaginationParameter , SearchParameter , ToDictMixin ):
11911088 """
@@ -1228,6 +1125,11 @@ class Member(Base, FromDictMixin):
12281125
12291126
12301127class MemberSchema (BaseSchema ):
1128+ """
1129+ This schema cannot be done through marshmallow_dataclass as we want to use the
1130+ values of the AccessLevel enum to create the enum field
1131+ """
1132+
12311133 id = fields .Int (required = True )
12321134 access_level = fields .Enum (AccessLevel , by_value = True , required = True )
12331135 email = fields .Str (required = True )
@@ -1249,6 +1151,11 @@ def return_member(
12491151
12501152
12511153class UpdateMemberSchema (BaseSchema ):
1154+ """
1155+ This schema cannot be done through marshmallow_dataclass as we want to use the
1156+ values of the AccessLevel enum to create the enum field
1157+ """
1158+
12521159 id = fields .Int (required = True )
12531160 access_level = fields .Enum (AccessLevel , by_value = True , allow_none = True )
12541161 active = fields .Bool (allow_none = True )
@@ -1323,14 +1230,10 @@ class CreateTeam(Base, FromDictMixin):
13231230 description : Optional [str ] = ""
13241231
13251232
1326- class CreateTeamSchema (BaseSchema ):
1327- many = False
1328-
1329- name = fields .Str (required = True )
1330- description = fields .Str (allow_none = True )
1331-
1332- class Meta :
1333- exclude_none = True
1233+ CreateTeamSchema = cast (
1234+ Type [BaseSchema ],
1235+ marshmallow_dataclass .class_schema (CreateTeam , base_schema = BaseSchema ),
1236+ )
13341237
13351238
13361239CreateTeam .SCHEMA = CreateTeamSchema ()
0 commit comments