everysk-lib 1.10.2__cp312-cp312-win_amd64.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.
- everysk/__init__.py +30 -0
- everysk/_version.py +683 -0
- everysk/api/__init__.py +61 -0
- everysk/api/api_requestor.py +167 -0
- everysk/api/api_resources/__init__.py +23 -0
- everysk/api/api_resources/api_resource.py +371 -0
- everysk/api/api_resources/calculation.py +779 -0
- everysk/api/api_resources/custom_index.py +42 -0
- everysk/api/api_resources/datastore.py +81 -0
- everysk/api/api_resources/file.py +42 -0
- everysk/api/api_resources/market_data.py +223 -0
- everysk/api/api_resources/parser.py +66 -0
- everysk/api/api_resources/portfolio.py +43 -0
- everysk/api/api_resources/private_security.py +42 -0
- everysk/api/api_resources/report.py +65 -0
- everysk/api/api_resources/report_template.py +39 -0
- everysk/api/api_resources/tests.py +115 -0
- everysk/api/api_resources/worker_execution.py +64 -0
- everysk/api/api_resources/workflow.py +65 -0
- everysk/api/api_resources/workflow_execution.py +93 -0
- everysk/api/api_resources/workspace.py +42 -0
- everysk/api/http_client.py +63 -0
- everysk/api/tests.py +32 -0
- everysk/api/utils.py +262 -0
- everysk/config.py +451 -0
- everysk/core/_tests/serialize/test_json.py +336 -0
- everysk/core/_tests/serialize/test_orjson.py +295 -0
- everysk/core/_tests/serialize/test_pickle.py +48 -0
- everysk/core/cloud_function/main.py +78 -0
- everysk/core/cloud_function/tests.py +86 -0
- everysk/core/compress.py +245 -0
- everysk/core/datetime/__init__.py +12 -0
- everysk/core/datetime/calendar.py +144 -0
- everysk/core/datetime/date.py +424 -0
- everysk/core/datetime/date_expression.py +299 -0
- everysk/core/datetime/date_mixin.py +1475 -0
- everysk/core/datetime/date_settings.py +30 -0
- everysk/core/datetime/datetime.py +713 -0
- everysk/core/exceptions.py +435 -0
- everysk/core/fields.py +1176 -0
- everysk/core/firestore.py +555 -0
- everysk/core/fixtures/_settings.py +29 -0
- everysk/core/fixtures/other/_settings.py +18 -0
- everysk/core/fixtures/user_agents.json +88 -0
- everysk/core/http.py +691 -0
- everysk/core/lists.py +92 -0
- everysk/core/log.py +709 -0
- everysk/core/number.py +37 -0
- everysk/core/object.py +1469 -0
- everysk/core/redis.py +1021 -0
- everysk/core/retry.py +51 -0
- everysk/core/serialize.py +674 -0
- everysk/core/sftp.py +414 -0
- everysk/core/signing.py +53 -0
- everysk/core/slack.py +127 -0
- everysk/core/string.py +199 -0
- everysk/core/tests.py +240 -0
- everysk/core/threads.py +199 -0
- everysk/core/undefined.py +70 -0
- everysk/core/unittests.py +73 -0
- everysk/core/workers.py +241 -0
- everysk/sdk/__init__.py +23 -0
- everysk/sdk/base.py +98 -0
- everysk/sdk/brutils/cnpj.py +391 -0
- everysk/sdk/brutils/cnpj_pd.py +129 -0
- everysk/sdk/engines/__init__.py +26 -0
- everysk/sdk/engines/cache.py +185 -0
- everysk/sdk/engines/compliance.py +37 -0
- everysk/sdk/engines/cryptography.py +69 -0
- everysk/sdk/engines/expression.cp312-win_amd64.pyd +0 -0
- everysk/sdk/engines/expression.pyi +55 -0
- everysk/sdk/engines/helpers.cp312-win_amd64.pyd +0 -0
- everysk/sdk/engines/helpers.pyi +26 -0
- everysk/sdk/engines/lock.py +120 -0
- everysk/sdk/engines/market_data.py +244 -0
- everysk/sdk/engines/settings.py +19 -0
- everysk/sdk/entities/__init__.py +23 -0
- everysk/sdk/entities/base.py +784 -0
- everysk/sdk/entities/base_list.py +131 -0
- everysk/sdk/entities/custom_index/base.py +209 -0
- everysk/sdk/entities/custom_index/settings.py +29 -0
- everysk/sdk/entities/datastore/base.py +160 -0
- everysk/sdk/entities/datastore/settings.py +17 -0
- everysk/sdk/entities/fields.py +375 -0
- everysk/sdk/entities/file/base.py +215 -0
- everysk/sdk/entities/file/settings.py +63 -0
- everysk/sdk/entities/portfolio/base.py +248 -0
- everysk/sdk/entities/portfolio/securities.py +241 -0
- everysk/sdk/entities/portfolio/security.py +580 -0
- everysk/sdk/entities/portfolio/settings.py +97 -0
- everysk/sdk/entities/private_security/base.py +226 -0
- everysk/sdk/entities/private_security/settings.py +17 -0
- everysk/sdk/entities/query.py +603 -0
- everysk/sdk/entities/report/base.py +214 -0
- everysk/sdk/entities/report/settings.py +23 -0
- everysk/sdk/entities/script.py +310 -0
- everysk/sdk/entities/secrets/base.py +128 -0
- everysk/sdk/entities/secrets/script.py +119 -0
- everysk/sdk/entities/secrets/settings.py +17 -0
- everysk/sdk/entities/settings.py +48 -0
- everysk/sdk/entities/tags.py +174 -0
- everysk/sdk/entities/worker_execution/base.py +307 -0
- everysk/sdk/entities/worker_execution/settings.py +63 -0
- everysk/sdk/entities/workflow_execution/base.py +113 -0
- everysk/sdk/entities/workflow_execution/settings.py +32 -0
- everysk/sdk/entities/workspace/base.py +99 -0
- everysk/sdk/entities/workspace/settings.py +27 -0
- everysk/sdk/settings.py +67 -0
- everysk/sdk/tests.py +105 -0
- everysk/sdk/worker_base.py +47 -0
- everysk/server/__init__.py +9 -0
- everysk/server/applications.py +63 -0
- everysk/server/endpoints.py +516 -0
- everysk/server/example_api.py +69 -0
- everysk/server/middlewares.py +80 -0
- everysk/server/requests.py +62 -0
- everysk/server/responses.py +119 -0
- everysk/server/routing.py +64 -0
- everysk/server/settings.py +36 -0
- everysk/server/tests.py +36 -0
- everysk/settings.py +98 -0
- everysk/sql/__init__.py +9 -0
- everysk/sql/connection.py +232 -0
- everysk/sql/model.py +376 -0
- everysk/sql/query.py +417 -0
- everysk/sql/row_factory.py +63 -0
- everysk/sql/settings.py +49 -0
- everysk/sql/utils.py +129 -0
- everysk/tests.py +23 -0
- everysk/utils.py +81 -0
- everysk/version.py +15 -0
- everysk_lib-1.10.2.dist-info/.gitignore +5 -0
- everysk_lib-1.10.2.dist-info/METADATA +326 -0
- everysk_lib-1.10.2.dist-info/RECORD +137 -0
- everysk_lib-1.10.2.dist-info/WHEEL +5 -0
- everysk_lib-1.10.2.dist-info/licenses/LICENSE.txt +9 -0
- everysk_lib-1.10.2.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,784 @@
|
|
|
1
|
+
###############################################################################
|
|
2
|
+
#
|
|
3
|
+
# (C) Copyright 2023 EVERYSK TECHNOLOGIES
|
|
4
|
+
#
|
|
5
|
+
# This is an unpublished work containing confidential and proprietary
|
|
6
|
+
# information of EVERYSK TECHNOLOGIES. Disclosure, use, or reproduction
|
|
7
|
+
# without authorization of EVERYSK TECHNOLOGIES is prohibited.
|
|
8
|
+
#
|
|
9
|
+
###############################################################################
|
|
10
|
+
from typing import Self, Any
|
|
11
|
+
|
|
12
|
+
from everysk.config import settings
|
|
13
|
+
from everysk.core.datetime import DateTime, Date
|
|
14
|
+
from everysk.core.exceptions import SDKValueError, FieldValueError
|
|
15
|
+
from everysk.core.fields import StrField, DateTimeField, ListField
|
|
16
|
+
from everysk.core.object import MetaClass as ObjMetaClass, BaseDictConfig
|
|
17
|
+
from everysk.core.string import is_string_object
|
|
18
|
+
from everysk.core.lists import split_in_slices
|
|
19
|
+
from everysk.sdk.base import BaseSDK, BaseDict
|
|
20
|
+
from everysk.sdk.engines.cryptography import generate_random_id
|
|
21
|
+
from everysk.sdk.entities.query import Query
|
|
22
|
+
from everysk.sdk.entities.script import Script
|
|
23
|
+
from everysk.sdk.entities.tags import Tags
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
###############################################################################
|
|
27
|
+
# QueryMetaClass Class Implementation
|
|
28
|
+
###############################################################################
|
|
29
|
+
class QueryMetaClass(ObjMetaClass):
|
|
30
|
+
"""
|
|
31
|
+
Metaclass for the Query class that allows for the query attribute to be accessed
|
|
32
|
+
directly from the entity class.
|
|
33
|
+
|
|
34
|
+
Example:
|
|
35
|
+
To access the query attribute from the entity class:
|
|
36
|
+
>>> MyClass.query
|
|
37
|
+
Query()
|
|
38
|
+
"""
|
|
39
|
+
def __getattribute__(cls, __name: str) -> Any:
|
|
40
|
+
"""
|
|
41
|
+
Get the query attribute from the entity class.
|
|
42
|
+
"""
|
|
43
|
+
if __name == 'query':
|
|
44
|
+
return Query(cls)
|
|
45
|
+
return super().__getattribute__(__name)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
###############################################################################
|
|
49
|
+
# ScriptMetaClass Class Implementation
|
|
50
|
+
###############################################################################
|
|
51
|
+
class ScriptMetaClass(QueryMetaClass):
|
|
52
|
+
"""
|
|
53
|
+
Metaclass for the Script class that allows for the script attribute to be accessed
|
|
54
|
+
directly from the entity class.
|
|
55
|
+
|
|
56
|
+
Example:
|
|
57
|
+
To access the script attribute from the entity class:
|
|
58
|
+
>>> MyClass.script
|
|
59
|
+
Script()
|
|
60
|
+
|
|
61
|
+
Notes:
|
|
62
|
+
This metaclass overrides the __getatrribute__ method to enable direct access
|
|
63
|
+
"""
|
|
64
|
+
def __getattribute__(cls, __name: str) -> Any:
|
|
65
|
+
"""
|
|
66
|
+
Get the script attribute from the entity class.
|
|
67
|
+
"""
|
|
68
|
+
if __name == 'script':
|
|
69
|
+
return Script(cls)
|
|
70
|
+
return super().__getattribute__(__name)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
###############################################################################
|
|
74
|
+
# BaseEntityConfig Class Implementation
|
|
75
|
+
###############################################################################
|
|
76
|
+
class BaseEntityConfig(BaseDictConfig):
|
|
77
|
+
exclude_keys: frozenset[str] = frozenset(['query', 'script', '_is_frozen', '_silent', '_errors', '_orderable_attributes'])
|
|
78
|
+
keys_blacklist: frozenset[str] = frozenset(['query', 'script'])
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
###############################################################################
|
|
82
|
+
# BaseEntity Class Implementation
|
|
83
|
+
###############################################################################
|
|
84
|
+
class BaseEntity(BaseSDK, BaseDict, metaclass=QueryMetaClass):
|
|
85
|
+
"""
|
|
86
|
+
Base class for all entities in the SDK library that provides common functionality. This class
|
|
87
|
+
should not be instantiated directly, but rather should be subclassed by other entity classes.
|
|
88
|
+
|
|
89
|
+
Attributes:
|
|
90
|
+
id (str): The unique identifier of the entity.
|
|
91
|
+
version (str): The version of the entity.
|
|
92
|
+
created_on (DateTime): The date and time the entity was created.
|
|
93
|
+
updated_on (DateTime): The date and time the entity was last updated.
|
|
94
|
+
|
|
95
|
+
Example:
|
|
96
|
+
To create a new entity:
|
|
97
|
+
>>> my_entity = MyEntity(id="my_id", workspace="my_workspace", name="my_name", description="my_description")
|
|
98
|
+
"""
|
|
99
|
+
class Config(BaseEntityConfig):
|
|
100
|
+
pass
|
|
101
|
+
|
|
102
|
+
_config: Config = None
|
|
103
|
+
_orderable_attributes = ListField(default=['id', 'created_on', 'updated_on'], readonly=True)
|
|
104
|
+
_allowed_query_attributes_for_all_operators = ListField(default=settings.ENTITY_ALLOWED_QUERY_ATTRIBUTES_FOR_ALL_OPERATORS, readonly=True)
|
|
105
|
+
|
|
106
|
+
id = StrField(default=None)
|
|
107
|
+
|
|
108
|
+
query: Query = None
|
|
109
|
+
|
|
110
|
+
created_on = DateTimeField(default=Undefined, empty_is_none=True, required_lazy=True)
|
|
111
|
+
updated_on = DateTimeField(default=Undefined, empty_is_none=True, required_lazy=True)
|
|
112
|
+
|
|
113
|
+
version = StrField(default=settings.ENTITY_DEFAULT_VERSION, required_lazy=True)
|
|
114
|
+
|
|
115
|
+
def __after_init__(self) -> None:
|
|
116
|
+
"""
|
|
117
|
+
Method that runs after the __init__ method.
|
|
118
|
+
This method must return None.
|
|
119
|
+
"""
|
|
120
|
+
super().__after_init__()
|
|
121
|
+
if self.created_on is Undefined:
|
|
122
|
+
self.created_on = DateTime.now()
|
|
123
|
+
if self.updated_on is Undefined:
|
|
124
|
+
self.updated_on = self.created_on
|
|
125
|
+
|
|
126
|
+
def _process_date(self, value: DateTime | None) -> str | None:
|
|
127
|
+
"""
|
|
128
|
+
Process the date value.
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
value (DateTime): The date value to process.
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
str: The processed date value.
|
|
135
|
+
"""
|
|
136
|
+
return Date.strftime_or_null(value)
|
|
137
|
+
|
|
138
|
+
def _process_tags(self, value: Tags | None) -> list | None:
|
|
139
|
+
"""
|
|
140
|
+
Convert the entity to a JSON-serializable dictionary.
|
|
141
|
+
This method converts the entity object into a dictionary that can be easily
|
|
142
|
+
serialized to JSON.
|
|
143
|
+
|
|
144
|
+
Args:
|
|
145
|
+
value (Tags): The tags value to process.
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
list: The processed tags value.
|
|
149
|
+
"""
|
|
150
|
+
return value.to_list() if isinstance(value, Tags) else value
|
|
151
|
+
|
|
152
|
+
def to_dict(self, add_class_path: bool = False, recursion: bool = False) -> dict:
|
|
153
|
+
"""
|
|
154
|
+
This method is used to convert the object to a dictionary.
|
|
155
|
+
"""
|
|
156
|
+
dct: dict = super().to_dict(add_class_path=add_class_path, recursion=recursion)
|
|
157
|
+
|
|
158
|
+
if add_class_path is False:
|
|
159
|
+
if 'date' in self:
|
|
160
|
+
dct['date_time'] = DateTime.strftime_or_null(self.date) # pylint: disable=no-member
|
|
161
|
+
|
|
162
|
+
if 'created_on' in self:
|
|
163
|
+
dct.pop('created_on')
|
|
164
|
+
dct['created'] = self.created_on.timestamp() if self.created_on is not None else None
|
|
165
|
+
|
|
166
|
+
if 'updated_on' in self:
|
|
167
|
+
dct.pop('updated_on')
|
|
168
|
+
dct['updated'] = self.updated_on.timestamp() if self.updated_on is not None else None
|
|
169
|
+
|
|
170
|
+
dct.pop('query', None)
|
|
171
|
+
dct.pop('script', None)
|
|
172
|
+
|
|
173
|
+
return dct
|
|
174
|
+
|
|
175
|
+
@staticmethod
|
|
176
|
+
def get_id_prefix() -> str:
|
|
177
|
+
"""
|
|
178
|
+
Get the prefix for the unique identifier for this entity.
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
str: The prefix for the unique identifier.
|
|
182
|
+
|
|
183
|
+
Raises:
|
|
184
|
+
NotImplementedError: This method should be overridden in subclasses.
|
|
185
|
+
"""
|
|
186
|
+
raise NotImplementedError()
|
|
187
|
+
|
|
188
|
+
def generate_id(self) -> str:
|
|
189
|
+
"""
|
|
190
|
+
Generate a unique ID for an entity instance.
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
str: The generated unique ID.
|
|
194
|
+
|
|
195
|
+
Example:
|
|
196
|
+
To generate a unique ID for an entity instance:
|
|
197
|
+
>>> unique_id = MyEntity().generate_id()
|
|
198
|
+
"""
|
|
199
|
+
prefix: str = self.get_id_prefix()
|
|
200
|
+
unique_id: str = generate_random_id(length=settings.ENTITY_ID_LENGTH)
|
|
201
|
+
return f'{prefix}{unique_id}'
|
|
202
|
+
|
|
203
|
+
@classmethod
|
|
204
|
+
def validate_id(cls, entity_id: str) -> bool:
|
|
205
|
+
"""
|
|
206
|
+
Validate an entity's ID.
|
|
207
|
+
|
|
208
|
+
Args:
|
|
209
|
+
entity_id str: The ID to be validated.
|
|
210
|
+
|
|
211
|
+
Returns:
|
|
212
|
+
bool: True if the ID is valid, False otherwise.
|
|
213
|
+
|
|
214
|
+
Example:
|
|
215
|
+
To validate an entity's ID:
|
|
216
|
+
>>> is_valid = MyEntity.validate_id(my_id)
|
|
217
|
+
"""
|
|
218
|
+
if entity_id:
|
|
219
|
+
try:
|
|
220
|
+
cls(id=entity_id)
|
|
221
|
+
return True
|
|
222
|
+
except Exception: # pylint: disable=broad-exception-caught
|
|
223
|
+
pass
|
|
224
|
+
return False
|
|
225
|
+
|
|
226
|
+
def validate(self) -> bool:
|
|
227
|
+
"""
|
|
228
|
+
Validate the entity's attributes.
|
|
229
|
+
|
|
230
|
+
This method performs validation checks on the entity's attributes to ensure they meet
|
|
231
|
+
the required criteria. If all required fields are present, the validation is considered
|
|
232
|
+
successful and the method returns True. If any required field is missing, it raises a
|
|
233
|
+
RequiredFieldError exception.
|
|
234
|
+
|
|
235
|
+
Args:
|
|
236
|
+
self (Self): The entity instance to validate.
|
|
237
|
+
|
|
238
|
+
Returns:
|
|
239
|
+
bool: True if the validation is successful.
|
|
240
|
+
|
|
241
|
+
Raises:
|
|
242
|
+
RequiredFieldError: If any required field is missing.
|
|
243
|
+
|
|
244
|
+
Example:
|
|
245
|
+
To validate an entity:
|
|
246
|
+
|
|
247
|
+
>>> is_valid = my_entity.validate()
|
|
248
|
+
>>> if is_valid:
|
|
249
|
+
>>> # Handle the valid entity
|
|
250
|
+
>>> else:
|
|
251
|
+
>>> # Handle the invalid entity
|
|
252
|
+
"""
|
|
253
|
+
self.validate_required_fields()
|
|
254
|
+
return True
|
|
255
|
+
|
|
256
|
+
def _pre_validate(self) -> None:
|
|
257
|
+
self.id = self.generate_id() # pylint: disable=attribute-defined-outside-init
|
|
258
|
+
|
|
259
|
+
def _pos_validate(self) -> None:
|
|
260
|
+
self.id = None # pylint: disable=attribute-defined-outside-init
|
|
261
|
+
self.created_on = None
|
|
262
|
+
self.updated_on = None
|
|
263
|
+
|
|
264
|
+
@classmethod
|
|
265
|
+
def validate_transient(cls, entity_dict: dict) -> Self:
|
|
266
|
+
"""
|
|
267
|
+
Validate the entity properties.
|
|
268
|
+
|
|
269
|
+
Args:
|
|
270
|
+
entity_dict (dict): The entity properties.
|
|
271
|
+
|
|
272
|
+
Returns:
|
|
273
|
+
BaseEntity: The entity object.
|
|
274
|
+
|
|
275
|
+
Example:
|
|
276
|
+
>>> entity_dict = {'name': 'My Entity'}
|
|
277
|
+
>>> BaseEntity.validate_transient(entity_dict)
|
|
278
|
+
"""
|
|
279
|
+
# Set the entity properties
|
|
280
|
+
entity = cls(**entity_dict)
|
|
281
|
+
entity._pre_validate()
|
|
282
|
+
entity.validate()
|
|
283
|
+
entity._pos_validate()
|
|
284
|
+
|
|
285
|
+
return entity
|
|
286
|
+
|
|
287
|
+
@classmethod
|
|
288
|
+
def check(cls, entity_dict: dict) -> Self:
|
|
289
|
+
"""
|
|
290
|
+
Check the entity properties.
|
|
291
|
+
|
|
292
|
+
Args:
|
|
293
|
+
entity_dict (dict): The entity properties.
|
|
294
|
+
|
|
295
|
+
Returns:
|
|
296
|
+
BaseEntity: The entity object.
|
|
297
|
+
|
|
298
|
+
Raises:
|
|
299
|
+
FieldValueError: If the entity properties are invalid.
|
|
300
|
+
RequiredFieldError: If a required field is missing.
|
|
301
|
+
"""
|
|
302
|
+
entity: Self = cls(**entity_dict)
|
|
303
|
+
entity.validate()
|
|
304
|
+
return entity
|
|
305
|
+
|
|
306
|
+
def _check_query(self, query: Query) -> bool:
|
|
307
|
+
"""
|
|
308
|
+
Check the query object.
|
|
309
|
+
|
|
310
|
+
Args:
|
|
311
|
+
query (Query): The query object.
|
|
312
|
+
|
|
313
|
+
Returns:
|
|
314
|
+
bool: True if the query object is valid.
|
|
315
|
+
"""
|
|
316
|
+
# pylint: disable=no-member
|
|
317
|
+
if self.name and 'date' in query.order:
|
|
318
|
+
raise SDKValueError("Can't filter by Name and Date at the same time, must order by updated_on")
|
|
319
|
+
|
|
320
|
+
return True
|
|
321
|
+
|
|
322
|
+
def _check_entity_to_query(self) -> bool:
|
|
323
|
+
"""
|
|
324
|
+
Check the entity object to query.
|
|
325
|
+
|
|
326
|
+
Returns:
|
|
327
|
+
bool: True if the entity object is valid.
|
|
328
|
+
"""
|
|
329
|
+
# pylint: disable=no-member
|
|
330
|
+
if self.name and self.tags:
|
|
331
|
+
raise SDKValueError("Can't filter by Name and Tags at the same time")
|
|
332
|
+
if self.name and self.link_uid:
|
|
333
|
+
raise SDKValueError("Can't filter by Name and Link UID at the same time")
|
|
334
|
+
|
|
335
|
+
return True
|
|
336
|
+
|
|
337
|
+
def _mount_query(self, query: Query) -> Query:
|
|
338
|
+
"""
|
|
339
|
+
Mount the query object.
|
|
340
|
+
|
|
341
|
+
Args:
|
|
342
|
+
query (Query): The query object.
|
|
343
|
+
|
|
344
|
+
Returns:
|
|
345
|
+
Query: The query object.
|
|
346
|
+
"""
|
|
347
|
+
# pylint: disable=no-member
|
|
348
|
+
if self.workspace is not None:
|
|
349
|
+
query = query.where('workspace', self.workspace)
|
|
350
|
+
if self.link_uid is not None:
|
|
351
|
+
query = query.where('link_uid', self.link_uid)
|
|
352
|
+
if self.name is not None:
|
|
353
|
+
query = query.where('name', self.name)
|
|
354
|
+
if self.date is not None:
|
|
355
|
+
query = query.where('date', self.date)
|
|
356
|
+
if self.tags:
|
|
357
|
+
query = query.where('tags', self.tags)
|
|
358
|
+
|
|
359
|
+
return query
|
|
360
|
+
|
|
361
|
+
def to_query(self, order: list | None = None, projection: list | None = None, distinct_on: list | None = None,
|
|
362
|
+
limit: int | None = None, offset: int | None = None, page_size: int | None = None, page_token: str | None = None) -> Query:
|
|
363
|
+
"""
|
|
364
|
+
This method converts the entity object into a query object.
|
|
365
|
+
|
|
366
|
+
Args:
|
|
367
|
+
order (List[str], optional): The order to apply to the query. Defaults to None.
|
|
368
|
+
projection (List[str], optional): The projection to apply to the query. Defaults to None.
|
|
369
|
+
distinct_on (List[str], optional): The distinct_on to apply to the query. Defaults to None.
|
|
370
|
+
limit (int, optional): The limit to apply to the query. Defaults to None.
|
|
371
|
+
offset (int, optional): The offset to apply to the query. Defaults to None.
|
|
372
|
+
page_size (int, optional): The page size to apply to the query. Defaults to None.
|
|
373
|
+
page_token (str, optional): The page token to apply to the query. Defaults to None.
|
|
374
|
+
|
|
375
|
+
Returns:
|
|
376
|
+
Query: A query object representing the entity.
|
|
377
|
+
|
|
378
|
+
Example:
|
|
379
|
+
To convert an entity object into a query object:
|
|
380
|
+
>>> entity = MyClass(property1="value1", property2="value2")
|
|
381
|
+
>>> query = entity.to_query(order=['property1'], limit=10)
|
|
382
|
+
"""
|
|
383
|
+
self._check_entity_to_query()
|
|
384
|
+
|
|
385
|
+
query: Query = Query(
|
|
386
|
+
self.__class__,
|
|
387
|
+
order=order,
|
|
388
|
+
projection=projection,
|
|
389
|
+
distinct_on=distinct_on,
|
|
390
|
+
limit=limit,
|
|
391
|
+
offset=offset,
|
|
392
|
+
page_size=page_size,
|
|
393
|
+
page_token=page_token
|
|
394
|
+
)
|
|
395
|
+
|
|
396
|
+
self._check_query(query)
|
|
397
|
+
return self._mount_query(query)
|
|
398
|
+
|
|
399
|
+
@classmethod
|
|
400
|
+
def _normalize_projection(cls, projection: str | list[str]) -> list[str]:
|
|
401
|
+
"""
|
|
402
|
+
Validate the projection attributes for the query and return the instance.
|
|
403
|
+
|
|
404
|
+
This method validate the desired properties that should be returned in entity.
|
|
405
|
+
The properties can either be set to include (using the property name) or to exclude
|
|
406
|
+
(prefixing the property name with '-'). Both inclusion and exclusion should not be set
|
|
407
|
+
in the same projection.
|
|
408
|
+
|
|
409
|
+
Args:
|
|
410
|
+
- projection (Union[List, str]): A property name as a string or a list of property names
|
|
411
|
+
indicating which properties to include or exclude in the entity.
|
|
412
|
+
|
|
413
|
+
Returns:
|
|
414
|
+
- Query: The instance of the current object.
|
|
415
|
+
|
|
416
|
+
Raises:
|
|
417
|
+
- ValueError: If both projection and inverse projection are set in the same projection or
|
|
418
|
+
if the projection properties do not belong to the entity kind.
|
|
419
|
+
|
|
420
|
+
Example:
|
|
421
|
+
To create a projection with a projection condition:
|
|
422
|
+
>>> projection = self._validate_projection('property_name')
|
|
423
|
+
|
|
424
|
+
To create a query with an inverse projection condition:
|
|
425
|
+
>>> projection = self._validate_projection('-property_name')
|
|
426
|
+
|
|
427
|
+
To create a query with a projection condition using a list:
|
|
428
|
+
>>> projection = self._validate_projection(['property_name_1', 'property_name_2'])
|
|
429
|
+
"""
|
|
430
|
+
if projection is None:
|
|
431
|
+
return []
|
|
432
|
+
|
|
433
|
+
if is_string_object(projection):
|
|
434
|
+
projection = [projection]
|
|
435
|
+
|
|
436
|
+
count: int = sum(property_name.startswith('-') for property_name in projection)
|
|
437
|
+
if not (count == 0 or count == len(projection)):
|
|
438
|
+
raise ValueError('Projection and Inverse Projection should not be set in the same query')
|
|
439
|
+
|
|
440
|
+
entity_properties: set = set(cls.__attributes__.keys()) # pylint: disable=protected-access
|
|
441
|
+
projection_properties: set = set([property_name.replace('-', '') for property_name in projection])
|
|
442
|
+
difference: set = projection_properties.difference(entity_properties)
|
|
443
|
+
|
|
444
|
+
if difference:
|
|
445
|
+
difference_: str = ', '.join(difference)
|
|
446
|
+
raise ValueError(f'Projection properties does not belongs to {cls.__name__}: {difference_}')
|
|
447
|
+
|
|
448
|
+
return projection
|
|
449
|
+
|
|
450
|
+
@classmethod
|
|
451
|
+
def retrieve(cls, entity_id: str, projection: list | str | None = None) -> Self | None:
|
|
452
|
+
"""
|
|
453
|
+
Retrieve an entity by its ID.
|
|
454
|
+
|
|
455
|
+
Args:
|
|
456
|
+
entity_id (str): The unique identifier of the entity to retrieve.
|
|
457
|
+
projection (Union[List, str], optional): A property name as a string or a list of property names
|
|
458
|
+
|
|
459
|
+
Returns:
|
|
460
|
+
Self: An instance of the class representing the retrieved entity.
|
|
461
|
+
None: If not found
|
|
462
|
+
|
|
463
|
+
Example:
|
|
464
|
+
To retrieve an entity by its ID:
|
|
465
|
+
|
|
466
|
+
>>> entity = MyClass.retrieve("entity_id_here")
|
|
467
|
+
>>> if entity:
|
|
468
|
+
>>> # Handle the retrieved entity
|
|
469
|
+
>>> else:
|
|
470
|
+
>>> # Entity not found
|
|
471
|
+
"""
|
|
472
|
+
if projection is not None:
|
|
473
|
+
projection = cls._normalize_projection(projection)
|
|
474
|
+
|
|
475
|
+
entity_dict: dict | None = cls.get_response(
|
|
476
|
+
params={'entity_id': entity_id, 'projection': projection})
|
|
477
|
+
|
|
478
|
+
if entity_dict is None:
|
|
479
|
+
return None
|
|
480
|
+
|
|
481
|
+
return cls(**entity_dict)
|
|
482
|
+
|
|
483
|
+
@classmethod
|
|
484
|
+
def create(cls, entity_dict: dict) -> Self:
|
|
485
|
+
"""
|
|
486
|
+
Create a new entity using provided attributes from a dictionary.
|
|
487
|
+
|
|
488
|
+
Args:
|
|
489
|
+
entity_dict (dict): A dictionary representing the entity's attributes.
|
|
490
|
+
|
|
491
|
+
Returns:
|
|
492
|
+
Self: An instance of the class representing the newly created entity.
|
|
493
|
+
|
|
494
|
+
Example:
|
|
495
|
+
To create a new entity with attributes from a dictionary and optional keyword arguments:
|
|
496
|
+
|
|
497
|
+
>>> entity_data = {'property1': value1, 'property2': value2}
|
|
498
|
+
>>> new_entity = MyClass.create(entity_data)
|
|
499
|
+
"""
|
|
500
|
+
entity_dict_: dict = cls.get_response(params={'entity_dict': entity_dict})
|
|
501
|
+
|
|
502
|
+
return cls(**entity_dict_)
|
|
503
|
+
|
|
504
|
+
@classmethod
|
|
505
|
+
def modify(cls, entity_id: str, overwrites: dict) -> Self | None:
|
|
506
|
+
"""
|
|
507
|
+
Modify an existing entity by updating its attributes using the provided overwrites.
|
|
508
|
+
|
|
509
|
+
Args:
|
|
510
|
+
entity_id (str): The unique identifier of the entity to modify.
|
|
511
|
+
overwrites (dict): A dictionary containing attribute updates to apply to the entity.
|
|
512
|
+
|
|
513
|
+
Returns:
|
|
514
|
+
Self: An instance of the class representing the modified entity.
|
|
515
|
+
None: If not found
|
|
516
|
+
|
|
517
|
+
Example:
|
|
518
|
+
To modify an existing entity by updating its attributes with overwrites:
|
|
519
|
+
|
|
520
|
+
>>> entity_id_to_modify = "entity_id_here"
|
|
521
|
+
>>> attribute_updates = {'property1': new_value1, 'property2': new_value2}
|
|
522
|
+
>>> modified_entity = MyClass.modify(entity_id_to_modify, attribute_updates)
|
|
523
|
+
"""
|
|
524
|
+
entity_dict: dict | None = cls.get_response(params={'entity_id': entity_id, 'overwrites': overwrites})
|
|
525
|
+
|
|
526
|
+
if entity_dict is None:
|
|
527
|
+
return None
|
|
528
|
+
|
|
529
|
+
return cls(**entity_dict)
|
|
530
|
+
|
|
531
|
+
@classmethod
|
|
532
|
+
def remove(cls, entity_id: str) -> Self | None:
|
|
533
|
+
"""
|
|
534
|
+
Remove an entity by its unique identifier.
|
|
535
|
+
|
|
536
|
+
Args:
|
|
537
|
+
entity_id (str): The unique identifier of the entity to remove.
|
|
538
|
+
|
|
539
|
+
Returns:
|
|
540
|
+
Self: An instance of the class representing the removed entity.
|
|
541
|
+
None: If not found
|
|
542
|
+
|
|
543
|
+
Example:
|
|
544
|
+
To remove an entity by its unique identifier:
|
|
545
|
+
|
|
546
|
+
removed_entity = MyClass.remove("entity_id_here")
|
|
547
|
+
>>> if removed_entity:
|
|
548
|
+
>>> # Handle the removed entity
|
|
549
|
+
>>> else:
|
|
550
|
+
>>> # Entity not found
|
|
551
|
+
"""
|
|
552
|
+
entity_dict: dict | None = cls.get_response(params={'entity_id': entity_id})
|
|
553
|
+
|
|
554
|
+
if entity_dict is None:
|
|
555
|
+
return None
|
|
556
|
+
|
|
557
|
+
return cls(**entity_dict)
|
|
558
|
+
|
|
559
|
+
@classmethod
|
|
560
|
+
def clone(cls, entity_id: str, overwrites: dict) -> Self | None:
|
|
561
|
+
"""
|
|
562
|
+
Clone an existing entity by creating a new one based on provided overwrites.
|
|
563
|
+
|
|
564
|
+
Args:
|
|
565
|
+
entity_id (str): The unique identifier of the entity to clone.
|
|
566
|
+
overwrites (dict): A dictionary containing attribute updates to apply to the new cloned entity.
|
|
567
|
+
|
|
568
|
+
Returns:
|
|
569
|
+
Self: An instance of the class representing the newly cloned entity.
|
|
570
|
+
None: If not found.
|
|
571
|
+
|
|
572
|
+
Example:
|
|
573
|
+
To clone an existing entity by creating a new one with attribute overwrites and optional keyword arguments:
|
|
574
|
+
|
|
575
|
+
>>> entity_id_to_clone = "entity_id_here"
|
|
576
|
+
>>> attribute_overwrites = {'property1': new_value1, 'property2': new_value2}
|
|
577
|
+
>>> cloned_entity = MyClass.clone(entity_id_to_clone, attribute_overwrites)
|
|
578
|
+
"""
|
|
579
|
+
entity_dict: dict | None = cls.get_response(params={'entity_id': entity_id, 'overwrites': overwrites})
|
|
580
|
+
|
|
581
|
+
if entity_dict is None:
|
|
582
|
+
return None
|
|
583
|
+
|
|
584
|
+
return cls(**entity_dict)
|
|
585
|
+
|
|
586
|
+
@classmethod
|
|
587
|
+
def retrieve_many(cls, entity_id_list: list[str], projection: str | list[str] | None = None) -> list[Self | None]:
|
|
588
|
+
"""
|
|
589
|
+
Retrieve multiple entities by their unique identifiers.
|
|
590
|
+
|
|
591
|
+
Args:
|
|
592
|
+
entity_id_list (List[str]): A list of unique identifiers for the entities to retrieve.
|
|
593
|
+
projection (Union[List, str], optional): A property name as a string or a list of property names.
|
|
594
|
+
|
|
595
|
+
Returns:
|
|
596
|
+
List[Self | None]: A list of instances of the class representing the retrieved entities, or None for entities not found.
|
|
597
|
+
|
|
598
|
+
Example:
|
|
599
|
+
To retrieve multiple entities by their unique identifiers:
|
|
600
|
+
|
|
601
|
+
>>> entity_ids_to_retrieve = ["entity_id1", "entity_id2"]
|
|
602
|
+
>>> retrieved_entities = MyClass.retrieve_many(entity_ids_to_retrieve)
|
|
603
|
+
"""
|
|
604
|
+
if not isinstance(entity_id_list, list):
|
|
605
|
+
raise FieldValueError(f"The argument 'entity_id_list' most be a instance of 'list' and not {type(entity_id_list)}.")
|
|
606
|
+
|
|
607
|
+
if projection is not None:
|
|
608
|
+
projection = cls._normalize_projection(projection)
|
|
609
|
+
|
|
610
|
+
chunks: list[slice] = split_in_slices(len(entity_id_list), settings.ENTITY_RETRIEVE_BATCH_SIZE)
|
|
611
|
+
entities: list[Self | None] = []
|
|
612
|
+
for chunk in chunks:
|
|
613
|
+
entities.extend(cls.inner_retrieve_many(entity_id_list[chunk], projection))
|
|
614
|
+
|
|
615
|
+
return entities
|
|
616
|
+
|
|
617
|
+
@classmethod
|
|
618
|
+
def inner_retrieve_many(cls, entity_id_list: list[str], projection: str | list[str] | None = None) -> list[Self | None]:
|
|
619
|
+
"""
|
|
620
|
+
Retrieve multiple entities by their unique identifiers.
|
|
621
|
+
|
|
622
|
+
Args:
|
|
623
|
+
entity_id_list (List[str]): A list of unique identifiers for the entities to retrieve.
|
|
624
|
+
projection (Union[List, str], optional): A property name as a string or a list of property names.
|
|
625
|
+
|
|
626
|
+
Returns:
|
|
627
|
+
List[Self | None]: A list of instances of the class representing the retrieved entities, or None for entities not found.
|
|
628
|
+
"""
|
|
629
|
+
|
|
630
|
+
entities: list[dict | None] = cls.get_response(params={'entity_id_list': entity_id_list, 'projection': projection})
|
|
631
|
+
|
|
632
|
+
return [cls(**entity_dict) if entity_dict is not None else None for entity_dict in entities]
|
|
633
|
+
|
|
634
|
+
@classmethod
|
|
635
|
+
def create_many(cls, entity_dict_list: list[dict]) -> list[Self | None]:
|
|
636
|
+
"""
|
|
637
|
+
Create multiple new entities using provided dictionaries..
|
|
638
|
+
|
|
639
|
+
Args:
|
|
640
|
+
entity_dict_list (List[dict]): A list of dictionaries, each representing an entity's attributes.
|
|
641
|
+
|
|
642
|
+
Returns:
|
|
643
|
+
List[Self | None]: A list of instances of the class representing the newly created entities, or None for entities not found.
|
|
644
|
+
|
|
645
|
+
Example:
|
|
646
|
+
To create multiple entities using a list of dictionaries:
|
|
647
|
+
|
|
648
|
+
>>> entity_data_list = [{'property1': value1}, {'property2': value2}]
|
|
649
|
+
>>> created_entities = MyClass.create_many(entity_data_list)
|
|
650
|
+
"""
|
|
651
|
+
entities: list[dict | None] = cls.get_response(params={'entity_dict_list': entity_dict_list})
|
|
652
|
+
|
|
653
|
+
return [cls(**entity_dict) if entity_dict is not None else None for entity_dict in entities]
|
|
654
|
+
|
|
655
|
+
@classmethod
|
|
656
|
+
def modify_many(cls, entity_id_list: list[str], overwrites: dict | list[dict]) -> list[Self | None]:
|
|
657
|
+
"""
|
|
658
|
+
Modify multiple existing entities by updating their attributes using the provided overwrites.
|
|
659
|
+
|
|
660
|
+
Args:
|
|
661
|
+
entity_id_list (List[str]): A list of unique identifiers for the entities to modify.
|
|
662
|
+
overwrites (Union[dict, List[dict]]): A dictionary or a list of dictionaries containing attribute updates
|
|
663
|
+
to apply to the entities.
|
|
664
|
+
|
|
665
|
+
Returns:
|
|
666
|
+
List[Self | None]: A list of instances of the class representing the modified entities, or None for entities not found.
|
|
667
|
+
|
|
668
|
+
Example:
|
|
669
|
+
To modify multiple existing entities by updating their attributes with overwrites:
|
|
670
|
+
|
|
671
|
+
>>> entity_ids_to_modify = ["entity_id1", "entity_id2"]
|
|
672
|
+
>>> attribute_overwrites = [{'property1': new_value1}, {'property2': new_value2}]
|
|
673
|
+
>>> modified_entities = MyClass.modify_many(entity_ids_to_modify, attribute_overwrites)
|
|
674
|
+
"""
|
|
675
|
+
entities: list[dict | None] = cls.get_response(params={'entity_id_list': entity_id_list, 'overwrites': overwrites})
|
|
676
|
+
|
|
677
|
+
return [cls(**entity_dict) if entity_dict is not None else None for entity_dict in entities]
|
|
678
|
+
|
|
679
|
+
@classmethod
|
|
680
|
+
def remove_many(cls, entity_id_list: list[str]) -> list[str | None]:
|
|
681
|
+
"""
|
|
682
|
+
Remove multiple entities by their unique identifiers.
|
|
683
|
+
|
|
684
|
+
Args:
|
|
685
|
+
entity_id_list (List[str]): A list of unique identifiers for the entities to remove.
|
|
686
|
+
|
|
687
|
+
Returns:
|
|
688
|
+
List[str | None]: A list of unique identifiers for the removed entities, or None for entities not deleted.
|
|
689
|
+
|
|
690
|
+
Example:
|
|
691
|
+
To remove multiple entities by their unique identifiers:
|
|
692
|
+
|
|
693
|
+
>>> entity_ids_to_remove = ["entity_id1", "entity_id2"]
|
|
694
|
+
>>> MyClass.remove_many(entity_ids_to_remove)
|
|
695
|
+
"""
|
|
696
|
+
return cls.get_response(params={'entity_id_list': entity_id_list})
|
|
697
|
+
|
|
698
|
+
@classmethod
|
|
699
|
+
def clone_many(cls, entity_id_list: list[str], overwrites: dict | list[dict]) -> list[Self | None]:
|
|
700
|
+
"""
|
|
701
|
+
Clone multiple existing entities by creating new ones based on provided overwrites.
|
|
702
|
+
|
|
703
|
+
Args:
|
|
704
|
+
entity_id_list (List[str]): A list of unique identifiers for the entities to clone.
|
|
705
|
+
overwrites (Union[dict, List[dict]]): A dictionary or a list of dictionaries containing attribute updates
|
|
706
|
+
to apply to the new cloned entities.
|
|
707
|
+
|
|
708
|
+
Returns:
|
|
709
|
+
List[Self | None]: A list of instances of the class representing the newly copied entities, or None for entities not found.
|
|
710
|
+
|
|
711
|
+
Example:
|
|
712
|
+
To clone multiple existing entities by creating new ones with attribute overwrites:
|
|
713
|
+
|
|
714
|
+
>>> entity_ids_to_clone = ["entity_id1", "entity_id2"]
|
|
715
|
+
>>> attribute_overwrites = [{'property1': new_value1}, {'property2': new_value2}]
|
|
716
|
+
>>> copied_entities = MyClass.clone_many(entity_ids_to_clone, attribute_overwrites)
|
|
717
|
+
"""
|
|
718
|
+
entities: list[dict | None] = cls.get_response(params={'entity_id_list': entity_id_list, 'overwrites': overwrites})
|
|
719
|
+
|
|
720
|
+
return [cls(**entity_dict) if entity_dict is not None else None for entity_dict in entities]
|
|
721
|
+
|
|
722
|
+
def load(self, offset: int = None) -> Self | None:
|
|
723
|
+
"""
|
|
724
|
+
Load an entity from the database and return it as an instance of the class.
|
|
725
|
+
|
|
726
|
+
Args:
|
|
727
|
+
self (Self): The entity instance to load.
|
|
728
|
+
offset (int, optional): The offset to use for pagination. Defaults to None.
|
|
729
|
+
|
|
730
|
+
Returns:
|
|
731
|
+
Self: An instance of the class representing the loaded entity.
|
|
732
|
+
None: If not found.
|
|
733
|
+
|
|
734
|
+
Example:
|
|
735
|
+
>>> entity_to_load = MyClass(property1="value1", property2="value2")
|
|
736
|
+
>>> loaded_entity = entity_to_load.load()
|
|
737
|
+
"""
|
|
738
|
+
# pylint: disable=no-member
|
|
739
|
+
if self.id:
|
|
740
|
+
return type(self).retrieve(self.id)
|
|
741
|
+
|
|
742
|
+
query = self.to_query()
|
|
743
|
+
return query.load(offset=offset)
|
|
744
|
+
|
|
745
|
+
def save(self) -> Self:
|
|
746
|
+
"""
|
|
747
|
+
Save the entity to the database and return the saved entity as an instance of the class.
|
|
748
|
+
|
|
749
|
+
Args:
|
|
750
|
+
self (Self): The entity instance to save.
|
|
751
|
+
|
|
752
|
+
Returns:
|
|
753
|
+
Self: An instance of the class representing the saved entity.
|
|
754
|
+
|
|
755
|
+
Example:
|
|
756
|
+
To save an entity:
|
|
757
|
+
|
|
758
|
+
>>> entity_to_save = MyClass(id="entity_id_here", property1="value1", property2="value2")
|
|
759
|
+
>>> saved_entity = entity_to_save.save()
|
|
760
|
+
"""
|
|
761
|
+
entity_dict: dict = self.get_response(self_obj=self)
|
|
762
|
+
|
|
763
|
+
return self.__class__(**entity_dict)
|
|
764
|
+
|
|
765
|
+
def delete(self) -> Self | None:
|
|
766
|
+
"""
|
|
767
|
+
Delete the entity from the database and return the deleted entity as an instance of the class.
|
|
768
|
+
|
|
769
|
+
Returns:
|
|
770
|
+
Self: An instance of the class representing the deleted entity.
|
|
771
|
+
None: If not found.
|
|
772
|
+
|
|
773
|
+
Example:
|
|
774
|
+
To delete an entity:
|
|
775
|
+
|
|
776
|
+
>>> entity_to_delete = MyClass(id="entity_id_here")
|
|
777
|
+
>>> deleted_entity = entity_to_delete.delete()
|
|
778
|
+
"""
|
|
779
|
+
entity_dict: dict | None = self.get_response(self_obj=self)
|
|
780
|
+
|
|
781
|
+
if entity_dict is None:
|
|
782
|
+
return None
|
|
783
|
+
|
|
784
|
+
return self.__class__(**entity_dict)
|