nexo-schemas 0.0.16__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nexo/schemas/__init__.py +0 -0
- nexo/schemas/application.py +292 -0
- nexo/schemas/connection.py +134 -0
- nexo/schemas/data.py +27 -0
- nexo/schemas/document.py +237 -0
- nexo/schemas/error/__init__.py +476 -0
- nexo/schemas/error/constants.py +50 -0
- nexo/schemas/error/descriptor.py +354 -0
- nexo/schemas/error/enums.py +40 -0
- nexo/schemas/error/metadata.py +15 -0
- nexo/schemas/error/spec.py +312 -0
- nexo/schemas/exception/__init__.py +0 -0
- nexo/schemas/exception/exc.py +911 -0
- nexo/schemas/exception/factory.py +1928 -0
- nexo/schemas/exception/handlers.py +110 -0
- nexo/schemas/google.py +14 -0
- nexo/schemas/key/__init__.py +0 -0
- nexo/schemas/key/rsa.py +131 -0
- nexo/schemas/metadata.py +21 -0
- nexo/schemas/mixins/__init__.py +0 -0
- nexo/schemas/mixins/filter.py +140 -0
- nexo/schemas/mixins/general.py +65 -0
- nexo/schemas/mixins/hierarchy.py +19 -0
- nexo/schemas/mixins/identity.py +387 -0
- nexo/schemas/mixins/parameter.py +50 -0
- nexo/schemas/mixins/service.py +40 -0
- nexo/schemas/mixins/sort.py +111 -0
- nexo/schemas/mixins/timestamp.py +192 -0
- nexo/schemas/model.py +240 -0
- nexo/schemas/operation/__init__.py +0 -0
- nexo/schemas/operation/action/__init__.py +9 -0
- nexo/schemas/operation/action/base.py +14 -0
- nexo/schemas/operation/action/resource.py +371 -0
- nexo/schemas/operation/action/status.py +8 -0
- nexo/schemas/operation/action/system.py +6 -0
- nexo/schemas/operation/action/websocket.py +6 -0
- nexo/schemas/operation/base.py +289 -0
- nexo/schemas/operation/constants.py +18 -0
- nexo/schemas/operation/context.py +68 -0
- nexo/schemas/operation/dependency.py +26 -0
- nexo/schemas/operation/enums.py +168 -0
- nexo/schemas/operation/extractor.py +36 -0
- nexo/schemas/operation/mixins.py +53 -0
- nexo/schemas/operation/request.py +1066 -0
- nexo/schemas/operation/resource.py +839 -0
- nexo/schemas/operation/system.py +55 -0
- nexo/schemas/operation/websocket.py +55 -0
- nexo/schemas/pagination.py +67 -0
- nexo/schemas/parameter.py +60 -0
- nexo/schemas/payload.py +116 -0
- nexo/schemas/resource.py +64 -0
- nexo/schemas/response.py +1041 -0
- nexo/schemas/security/__init__.py +0 -0
- nexo/schemas/security/api_key.py +63 -0
- nexo/schemas/security/authentication.py +848 -0
- nexo/schemas/security/authorization.py +922 -0
- nexo/schemas/security/enums.py +32 -0
- nexo/schemas/security/impersonation.py +179 -0
- nexo/schemas/security/token.py +402 -0
- nexo/schemas/security/types.py +17 -0
- nexo/schemas/success/__init__.py +0 -0
- nexo/schemas/success/descriptor.py +100 -0
- nexo/schemas/success/enums.py +23 -0
- nexo/schemas/user_agent.py +46 -0
- nexo_schemas-0.0.16.dist-info/METADATA +87 -0
- nexo_schemas-0.0.16.dist-info/RECORD +69 -0
- nexo_schemas-0.0.16.dist-info/WHEEL +5 -0
- nexo_schemas-0.0.16.dist-info/licenses/LICENSE +21 -0
- nexo_schemas-0.0.16.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
from datetime import date
|
|
2
|
+
from pydantic import BaseModel, Field, computed_field
|
|
3
|
+
from typing import Annotated, Generic, Self, TypeVar
|
|
4
|
+
from uuid import UUID as PythonUUID
|
|
5
|
+
from nexo.types.datetime import OptDate, OptDateT, OptListOfDatesT
|
|
6
|
+
from nexo.types.enum import StrEnumT, OptStrEnumT
|
|
7
|
+
from nexo.types.integer import OptIntT, OptListOfIntsT
|
|
8
|
+
from nexo.types.misc import (
|
|
9
|
+
OptIntOrUUIDT,
|
|
10
|
+
OptListOfIntsOrUUIDsT,
|
|
11
|
+
)
|
|
12
|
+
from nexo.types.string import OptStrT, OptListOfStrsT
|
|
13
|
+
from nexo.types.uuid import OptUUIDT, OptListOfUUIDsT
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class IdentifierType(BaseModel, Generic[StrEnumT]):
|
|
17
|
+
type: StrEnumT = Field(..., description="Identifier's type")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
IdentifierValueT = TypeVar("IdentifierValueT")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class IdentifierValue(BaseModel, Generic[IdentifierValueT]):
|
|
24
|
+
value: IdentifierValueT = Field(..., description="Identifier's value")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class Identifier(
|
|
28
|
+
IdentifierValue[IdentifierValueT],
|
|
29
|
+
IdentifierType[StrEnumT],
|
|
30
|
+
Generic[StrEnumT, IdentifierValueT],
|
|
31
|
+
):
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
IdentifierT = TypeVar("IdentifierT", bound=Identifier)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class IdentifierMixin(BaseModel, Generic[IdentifierT]):
|
|
39
|
+
identifier: Annotated[IdentifierT, Field(..., description="Identifier")]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# Id
|
|
43
|
+
class Id(BaseModel, Generic[OptIntOrUUIDT]):
|
|
44
|
+
id: OptIntOrUUIDT = Field(..., description="Id")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class IntId(BaseModel, Generic[OptIntT]):
|
|
48
|
+
id: OptIntT = Field(..., description="Id (Integer)", ge=1)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class UUIDId(BaseModel, Generic[OptUUIDT]):
|
|
52
|
+
id: OptUUIDT = Field(..., description="Id (UUID)")
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# Ids
|
|
56
|
+
class Ids(BaseModel, Generic[OptListOfIntsOrUUIDsT]):
|
|
57
|
+
ids: OptListOfIntsOrUUIDsT = Field(..., description="Ids")
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class IntIds(BaseModel, Generic[OptListOfIntsT]):
|
|
61
|
+
ids: OptListOfIntsT = Field(..., description="Ids (Integers)")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class UUIDIds(BaseModel, Generic[OptListOfUUIDsT]):
|
|
65
|
+
ids: OptListOfUUIDsT = Field(..., description="Ids (UUIDs)")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
# UUID
|
|
69
|
+
class UUID(BaseModel, Generic[OptUUIDT]):
|
|
70
|
+
uuid: OptUUIDT = Field(..., description="UUID")
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class UUIDs(BaseModel, Generic[OptListOfUUIDsT]):
|
|
74
|
+
uuids: OptListOfUUIDsT = Field(..., description="UUIDs")
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
# Identifier
|
|
78
|
+
class DataIdentifier(
|
|
79
|
+
UUID[PythonUUID],
|
|
80
|
+
IntId[int],
|
|
81
|
+
):
|
|
82
|
+
pass
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class EntityType(BaseModel, Generic[OptStrEnumT]):
|
|
86
|
+
type: Annotated[OptStrEnumT, Field(..., description="Entity's type")]
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class EntityIdentifier(
|
|
90
|
+
EntityType[OptStrEnumT], UUID[PythonUUID], IntId[int], Generic[OptStrEnumT]
|
|
91
|
+
):
|
|
92
|
+
pass
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
EntityIdentifierT = TypeVar("EntityIdentifierT", bound=EntityIdentifier)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class IdCard(BaseModel, Generic[OptStrT]):
|
|
99
|
+
id_card: OptStrT = Field(..., description="ID Card")
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class IdCards(BaseModel, Generic[OptListOfStrsT]):
|
|
103
|
+
id_cards: OptListOfStrsT = Field(..., description="ID Cards")
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class Passport(BaseModel, Generic[OptStrT]):
|
|
107
|
+
passport: OptStrT = Field(..., description="Passport")
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class Passports(BaseModel, Generic[OptListOfStrsT]):
|
|
111
|
+
passports: OptListOfStrsT = Field(..., description="Passports")
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class Key(BaseModel, Generic[OptStrT]):
|
|
115
|
+
key: OptStrT = Field(..., description="Key")
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class Keys(BaseModel, Generic[OptListOfStrsT]):
|
|
119
|
+
keys: OptListOfStrsT = Field(..., description="Keys")
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class FullName(BaseModel, Generic[OptStrT]):
|
|
123
|
+
full_name: OptStrT = Field(..., description="Full Name")
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
class FullNames(BaseModel, Generic[OptListOfStrsT]):
|
|
127
|
+
full_names: OptListOfStrsT = Field(..., description="Full Names")
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class Name(BaseModel, Generic[OptStrT]):
|
|
131
|
+
name: OptStrT = Field(..., description="Name")
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class Names(BaseModel, Generic[OptListOfStrsT]):
|
|
135
|
+
names: OptListOfStrsT = Field(..., description="Names")
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class Age(BaseModel):
|
|
139
|
+
raw: Annotated[float, Field(0, description="Age", ge=0.0)] = 0
|
|
140
|
+
year: Annotated[int, Field(0, description="Year", ge=0)] = 0
|
|
141
|
+
month: Annotated[int, Field(0, description="Month", ge=0)] = 0
|
|
142
|
+
day: Annotated[int, Field(0, description="Day", ge=0)] = 0
|
|
143
|
+
|
|
144
|
+
@classmethod
|
|
145
|
+
def from_date_of_birth(cls, date_of_birth: OptDate) -> Self:
|
|
146
|
+
if date_of_birth is None:
|
|
147
|
+
return cls()
|
|
148
|
+
|
|
149
|
+
today = date.today()
|
|
150
|
+
|
|
151
|
+
# Compute Y/M/D difference
|
|
152
|
+
y = today.year - date_of_birth.year
|
|
153
|
+
m = today.month - date_of_birth.month
|
|
154
|
+
d = today.day - date_of_birth.day
|
|
155
|
+
|
|
156
|
+
# Normalize negative days/months
|
|
157
|
+
if d < 0:
|
|
158
|
+
m -= 1
|
|
159
|
+
# Approx: last month's number of days
|
|
160
|
+
# If precision needed you can use calendar.monthrange
|
|
161
|
+
prev_month = (today.month - 1) or 12
|
|
162
|
+
prev_year = today.year if today.month > 1 else today.year - 1
|
|
163
|
+
from calendar import monthrange
|
|
164
|
+
|
|
165
|
+
d += monthrange(prev_year, prev_month)[1]
|
|
166
|
+
|
|
167
|
+
if m < 0:
|
|
168
|
+
y -= 1
|
|
169
|
+
m += 12
|
|
170
|
+
|
|
171
|
+
raw = y + m / 12 + d / 365.25
|
|
172
|
+
|
|
173
|
+
return cls(raw=raw, year=y, month=m, day=d)
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
OptAge = Age | None
|
|
177
|
+
OptAgeT = TypeVar("OptAgeT", bound=OptAge)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
class AgeMixin(BaseModel):
|
|
181
|
+
age: Annotated[Age, Field(default_factory=Age, description="Age")]
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class BirthDate(BaseModel, Generic[OptDateT]):
|
|
185
|
+
birth_date: OptDateT = Field(..., description="Birth Date")
|
|
186
|
+
|
|
187
|
+
@computed_field
|
|
188
|
+
@property
|
|
189
|
+
def age(self) -> Age:
|
|
190
|
+
return Age.from_date_of_birth(self.birth_date)
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
class BirthDates(BaseModel, Generic[OptListOfDatesT]):
|
|
194
|
+
birth_dates: OptListOfDatesT = Field(..., description="Birth Dates")
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
class DateOfBirth(BaseModel, Generic[OptDateT]):
|
|
198
|
+
date_of_birth: OptDateT = Field(..., description="Date of Birth")
|
|
199
|
+
|
|
200
|
+
@computed_field
|
|
201
|
+
@property
|
|
202
|
+
def age(self) -> Age:
|
|
203
|
+
return Age.from_date_of_birth(self.date_of_birth)
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
class DateOfBirths(BaseModel, Generic[OptListOfDatesT]):
|
|
207
|
+
date_of_births: OptListOfDatesT = Field(..., description="Date of Births")
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
class BirthPlace(BaseModel, Generic[OptStrT]):
|
|
211
|
+
birth_place: OptStrT = Field(..., description="Birth Place")
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
class BirthPlaces(BaseModel, Generic[OptListOfStrsT]):
|
|
215
|
+
birth_places: OptListOfStrsT = Field(..., description="Birth Places")
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
class PlaceOfBirth(BaseModel, Generic[OptStrT]):
|
|
219
|
+
place_of_birth: OptStrT = Field(..., description="Place of Birth")
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
class PlaceOfBirths(BaseModel, Generic[OptListOfStrsT]):
|
|
223
|
+
place_of_births: OptListOfStrsT = Field(..., description="Place of Births")
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
# ----- ----- ----- Organization ID ----- ----- ----- #
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
class OrganizationId(BaseModel, Generic[OptIntOrUUIDT]):
|
|
230
|
+
organization_id: OptIntOrUUIDT = Field(..., description="Organization's ID")
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
class IntOrganizationId(BaseModel, Generic[OptIntT]):
|
|
234
|
+
organization_id: OptIntT = Field(..., description="Organization's ID", ge=1)
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
class UUIDOrganizationId(BaseModel, Generic[OptUUIDT]):
|
|
238
|
+
organization_id: OptUUIDT = Field(..., description="Organization's ID")
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
class OrganizationIds(BaseModel, Generic[OptListOfIntsOrUUIDsT]):
|
|
242
|
+
organization_ids: OptListOfIntsOrUUIDsT = Field(
|
|
243
|
+
..., description="Organization's IDs"
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
class IntOrganizationIds(BaseModel, Generic[OptListOfIntsT]):
|
|
248
|
+
organization_ids: OptListOfIntsT = Field(..., description="Organization's IDs")
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
class UUIDOrganizationIds(BaseModel, Generic[OptListOfUUIDsT]):
|
|
252
|
+
organization_ids: OptListOfUUIDsT = Field(..., description="Organization's IDs")
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
# ----- ----- ----- Parent ID ----- ----- ----- #
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
class ParentId(BaseModel, Generic[OptIntOrUUIDT]):
|
|
259
|
+
parent_id: OptIntOrUUIDT = Field(..., description="Parent's ID")
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
class IntParentId(BaseModel, Generic[OptIntT]):
|
|
263
|
+
parent_id: OptIntT = Field(..., description="Parent's ID", ge=1)
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
class UUIDParentId(BaseModel, Generic[OptUUIDT]):
|
|
267
|
+
parent_id: OptUUIDT = Field(..., description="Parent's ID")
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
class ParentIds(BaseModel, Generic[OptListOfIntsOrUUIDsT]):
|
|
271
|
+
parent_ids: OptListOfIntsOrUUIDsT = Field(..., description="Parent's IDs")
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
class IntParentIds(BaseModel, Generic[OptListOfIntsT]):
|
|
275
|
+
parent_ids: OptListOfIntsT = Field(..., description="Parent's IDs")
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
class UUIDParentIds(BaseModel, Generic[OptListOfUUIDsT]):
|
|
279
|
+
parent_ids: OptListOfUUIDsT = Field(..., description="Parent's IDs")
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
# ----- ----- ----- Patient ID ----- ----- ----- #
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
class PatientId(BaseModel, Generic[OptIntOrUUIDT]):
|
|
286
|
+
patient_id: OptIntOrUUIDT = Field(..., description="Patient's ID")
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
class IntPatientId(BaseModel, Generic[OptIntT]):
|
|
290
|
+
patient_id: OptIntT = Field(..., description="Patient's ID", ge=1)
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
class UUIDPatientId(BaseModel, Generic[OptUUIDT]):
|
|
294
|
+
patient_id: OptUUIDT = Field(..., description="Patient's ID")
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
class PatientIds(BaseModel, Generic[OptListOfIntsOrUUIDsT]):
|
|
298
|
+
patient_ids: OptListOfIntsOrUUIDsT = Field(..., description="Patient's IDs")
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
class IntPatientIds(BaseModel, Generic[OptListOfIntsT]):
|
|
302
|
+
patient_ids: OptListOfIntsT = Field(..., description="Patient's IDs")
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
class UUIDPatientIds(BaseModel, Generic[OptListOfUUIDsT]):
|
|
306
|
+
patient_ids: OptListOfUUIDsT = Field(..., description="Patient's IDs")
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
# ----- ----- ----- Source ID ----- ----- ----- #
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
class SourceId(BaseModel, Generic[OptIntOrUUIDT]):
|
|
313
|
+
source_id: OptIntOrUUIDT = Field(..., description="Source's ID")
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
class IntSourceId(BaseModel, Generic[OptIntT]):
|
|
317
|
+
source_id: OptIntT = Field(..., description="Source's ID", ge=1)
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
class UUIDSourceId(BaseModel, Generic[OptUUIDT]):
|
|
321
|
+
source_id: OptUUIDT = Field(..., description="Source's ID")
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
class SourceIds(BaseModel, Generic[OptListOfIntsOrUUIDsT]):
|
|
325
|
+
source_ids: OptListOfIntsOrUUIDsT = Field(..., description="Source's IDs")
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
class IntSourceIds(BaseModel, Generic[OptListOfIntsT]):
|
|
329
|
+
source_ids: OptListOfIntsT = Field(..., description="Source's IDs")
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
class UUIDSourceIds(BaseModel, Generic[OptListOfUUIDsT]):
|
|
333
|
+
source_ids: OptListOfUUIDsT = Field(..., description="Source's IDs")
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
# ----- ----- ----- Target ID ----- ----- ----- #
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
class TargetId(BaseModel, Generic[OptIntOrUUIDT]):
|
|
340
|
+
target_id: OptIntOrUUIDT = Field(..., description="Target's ID")
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
class IntTargetId(BaseModel, Generic[OptIntT]):
|
|
344
|
+
target_id: OptIntT = Field(..., description="Target's ID", ge=1)
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
class UUIDTargetId(BaseModel, Generic[OptUUIDT]):
|
|
348
|
+
target_id: OptUUIDT = Field(..., description="Target's ID")
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
class TargetIds(BaseModel, Generic[OptListOfIntsOrUUIDsT]):
|
|
352
|
+
target_ids: OptListOfIntsOrUUIDsT = Field(..., description="Target's IDs")
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
class IntTargetIds(BaseModel, Generic[OptListOfIntsT]):
|
|
356
|
+
target_ids: OptListOfIntsT = Field(..., description="Target's IDs")
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
class UUIDTargetIds(BaseModel, Generic[OptListOfUUIDsT]):
|
|
360
|
+
target_ids: OptListOfUUIDsT = Field(..., description="Target's IDs")
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
# ----- ----- ----- User ID ----- ----- ----- #
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
class UserId(BaseModel, Generic[OptIntOrUUIDT]):
|
|
367
|
+
user_id: OptIntOrUUIDT = Field(..., description="User's ID")
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
class IntUserId(BaseModel, Generic[OptIntT]):
|
|
371
|
+
user_id: OptIntT = Field(..., description="User's ID", ge=1)
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
class UUIDUserId(BaseModel, Generic[OptUUIDT]):
|
|
375
|
+
user_id: OptUUIDT = Field(..., description="User's ID")
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
class UserIds(BaseModel, Generic[OptListOfIntsOrUUIDsT]):
|
|
379
|
+
user_ids: OptListOfIntsOrUUIDsT = Field(..., description="User's IDs")
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
class IntUserIds(BaseModel, Generic[OptListOfIntsT]):
|
|
383
|
+
user_ids: OptListOfIntsT = Field(..., description="User's IDs")
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
class UUIDUserIds(BaseModel, Generic[OptListOfUUIDsT]):
|
|
387
|
+
user_ids: OptListOfUUIDsT = Field(..., description="User's IDs")
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
from pydantic import BaseModel, Field
|
|
2
|
+
from typing import Annotated, Generic
|
|
3
|
+
from nexo.enums.status import (
|
|
4
|
+
ListOfDataStatuses,
|
|
5
|
+
OptListOfDataStatuses,
|
|
6
|
+
SimpleDataStatusesMixin,
|
|
7
|
+
FULL_DATA_STATUSES,
|
|
8
|
+
)
|
|
9
|
+
from nexo.types.enum import OptListOfStrEnumsT
|
|
10
|
+
from nexo.types.string import OptStr
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class OptionalSimpleDataStatusesMixin(SimpleDataStatusesMixin[OptListOfDataStatuses]):
|
|
14
|
+
statuses: Annotated[
|
|
15
|
+
OptListOfDataStatuses,
|
|
16
|
+
Field(None, description="Data statuses", min_length=1),
|
|
17
|
+
] = None
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class MandatorySimpleDataStatusesMixin(SimpleDataStatusesMixin[ListOfDataStatuses]):
|
|
21
|
+
statuses: Annotated[
|
|
22
|
+
ListOfDataStatuses,
|
|
23
|
+
Field(FULL_DATA_STATUSES, description="Data statuses", min_length=1),
|
|
24
|
+
] = FULL_DATA_STATUSES
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class Search(BaseModel):
|
|
28
|
+
search: Annotated[OptStr, Field(None, description="Search string")] = None
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class UseCache(BaseModel):
|
|
32
|
+
use_cache: Annotated[bool, Field(True, description="Whether to use cache")] = True
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class IncludeURL(BaseModel):
|
|
36
|
+
include_url: Annotated[bool, Field(False, description="Whether to include URL")] = (
|
|
37
|
+
False
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class Include(BaseModel, Generic[OptListOfStrEnumsT]):
|
|
42
|
+
include: Annotated[OptListOfStrEnumsT, Field(..., description="Included field(s)")]
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class Exclude(BaseModel, Generic[OptListOfStrEnumsT]):
|
|
46
|
+
exclude: Annotated[OptListOfStrEnumsT, Field(..., description="Excluded field(s)")]
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class Expand(BaseModel, Generic[OptListOfStrEnumsT]):
|
|
50
|
+
expand: Annotated[OptListOfStrEnumsT, Field(..., description="Expanded field(s)")]
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from pydantic import BaseModel, Field
|
|
2
|
+
from typing import Annotated, Generic
|
|
3
|
+
from nexo.types.service import (
|
|
4
|
+
OptServiceKeyT,
|
|
5
|
+
OptServiceKeysT,
|
|
6
|
+
OptServiceNameT,
|
|
7
|
+
OptServiceNamesT,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class SimpleServiceKeyMixin(BaseModel, Generic[OptServiceKeyT]):
|
|
12
|
+
key: Annotated[OptServiceKeyT, Field(..., description="Service Key")]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class FullServiceKeyMixin(BaseModel, Generic[OptServiceKeyT]):
|
|
16
|
+
service_key: Annotated[OptServiceKeyT, Field(..., description="Service Key")]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class SimpleServiceKeysMixin(BaseModel, Generic[OptServiceKeysT]):
|
|
20
|
+
keys: Annotated[OptServiceKeysT, Field(..., description="Service Keys")]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class FullServiceKeysMixin(BaseModel, Generic[OptServiceKeysT]):
|
|
24
|
+
service_keys: Annotated[OptServiceKeysT, Field(..., description="Service Keys")]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class SimpleServiceNameMixin(BaseModel, Generic[OptServiceNameT]):
|
|
28
|
+
name: Annotated[OptServiceNameT, Field(..., description="Service Name")]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class FullServiceNameMixin(BaseModel, Generic[OptServiceNameT]):
|
|
32
|
+
service_name: Annotated[OptServiceNameT, Field(..., description="Service Name")]
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class SimpleServiceNamesMixin(BaseModel, Generic[OptServiceNamesT]):
|
|
36
|
+
names: Annotated[OptServiceNamesT, Field(..., description="Service Names")]
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class FullServiceNamesMixin(BaseModel, Generic[OptServiceNamesT]):
|
|
40
|
+
service_names: Annotated[OptServiceNamesT, Field(..., description="Service Names")]
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from pydantic import BaseModel, Field, field_validator
|
|
3
|
+
from typing import Annotated, TypeGuard, overload
|
|
4
|
+
from nexo.enums.order import Order as OrderEnum
|
|
5
|
+
from nexo.types.string import ListOfStrs
|
|
6
|
+
from .general import Order
|
|
7
|
+
from .identity import Name
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
SORT_COLUMN_REGEX = r"^(?P<name>[a-z_]+)\.(?P<order>asc|desc)$"
|
|
11
|
+
SORT_COLUMN_PATTERN = re.compile(SORT_COLUMN_REGEX)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class SortColumn(
|
|
15
|
+
Order[OrderEnum],
|
|
16
|
+
Name[str],
|
|
17
|
+
):
|
|
18
|
+
name: Annotated[str, Field(..., description="Name", min_length=1)]
|
|
19
|
+
|
|
20
|
+
@classmethod
|
|
21
|
+
def from_string(cls, sort: str) -> "SortColumn":
|
|
22
|
+
match = SORT_COLUMN_PATTERN.match(sort)
|
|
23
|
+
if not match:
|
|
24
|
+
raise ValueError(f"Invalid sort format: {sort!r}")
|
|
25
|
+
|
|
26
|
+
name = match.group("name")
|
|
27
|
+
order_raw = match.group("order")
|
|
28
|
+
order = OrderEnum(order_raw)
|
|
29
|
+
|
|
30
|
+
return cls(name=name, order=order)
|
|
31
|
+
|
|
32
|
+
def to_string(self) -> str:
|
|
33
|
+
return f"{self.name}.{self.order}"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
OptSortColumn = SortColumn | None
|
|
37
|
+
ListOfSortColumns = list[SortColumn]
|
|
38
|
+
OptListOfSortColumns = ListOfSortColumns | None
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
AnySorts = ListOfSortColumns | ListOfStrs
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def is_sort_columns(
|
|
45
|
+
sorts: AnySorts,
|
|
46
|
+
) -> TypeGuard[ListOfSortColumns]:
|
|
47
|
+
return all(isinstance(sort, SortColumn) for sort in sorts)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def is_sorts(
|
|
51
|
+
sorts: AnySorts,
|
|
52
|
+
) -> TypeGuard[ListOfStrs]:
|
|
53
|
+
return all(isinstance(sort, str) for sort in sorts)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class Sorts(BaseModel):
|
|
57
|
+
sorts: Annotated[
|
|
58
|
+
ListOfStrs,
|
|
59
|
+
Field(
|
|
60
|
+
["id.asc"],
|
|
61
|
+
description="Column sorts with '<COLUMN_NAME>.<ASC|DESC>' format",
|
|
62
|
+
),
|
|
63
|
+
] = ["id.asc"]
|
|
64
|
+
|
|
65
|
+
@field_validator("sorts", mode="after")
|
|
66
|
+
@classmethod
|
|
67
|
+
def validate_sorts_pattern(cls, value: ListOfStrs) -> ListOfStrs:
|
|
68
|
+
for v in value:
|
|
69
|
+
match = SORT_COLUMN_PATTERN.match(v)
|
|
70
|
+
if not match:
|
|
71
|
+
raise ValueError(f"Invalid sort column format: {v!r}")
|
|
72
|
+
return value
|
|
73
|
+
|
|
74
|
+
@classmethod
|
|
75
|
+
def from_sort_columns(cls, sort_columns: ListOfSortColumns) -> "Sorts":
|
|
76
|
+
return cls(sorts=[sort.to_string() for sort in sort_columns])
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def sort_columns(self) -> ListOfSortColumns:
|
|
80
|
+
return [SortColumn.from_string(sort) for sort in self.sorts]
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class SortColumns(BaseModel):
|
|
84
|
+
sort_columns: Annotated[
|
|
85
|
+
ListOfSortColumns,
|
|
86
|
+
Field(
|
|
87
|
+
[SortColumn(name="id", order=OrderEnum.ASC)],
|
|
88
|
+
description="List of columns to be sorted",
|
|
89
|
+
),
|
|
90
|
+
] = [SortColumn(name="id", order=OrderEnum.ASC)]
|
|
91
|
+
|
|
92
|
+
@classmethod
|
|
93
|
+
def from_sorts(cls, sorts: ListOfStrs) -> "SortColumns":
|
|
94
|
+
return cls(sort_columns=[SortColumn.from_string(sort) for sort in sorts])
|
|
95
|
+
|
|
96
|
+
@property
|
|
97
|
+
def sorts(self) -> ListOfStrs:
|
|
98
|
+
return [sort.to_string() for sort in self.sort_columns]
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
@overload
|
|
102
|
+
def convert(sorts: ListOfSortColumns) -> ListOfStrs: ...
|
|
103
|
+
@overload
|
|
104
|
+
def convert(sorts: ListOfStrs) -> ListOfSortColumns: ...
|
|
105
|
+
def convert(sorts: AnySorts) -> AnySorts:
|
|
106
|
+
if is_sort_columns(sorts):
|
|
107
|
+
return [sort.to_string() for sort in sorts]
|
|
108
|
+
elif is_sorts(sorts):
|
|
109
|
+
return [SortColumn.from_string(sort) for sort in sorts]
|
|
110
|
+
else:
|
|
111
|
+
raise ValueError("Sort type is neither SortColumn nor string")
|