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.
Files changed (137) hide show
  1. everysk/__init__.py +30 -0
  2. everysk/_version.py +683 -0
  3. everysk/api/__init__.py +61 -0
  4. everysk/api/api_requestor.py +167 -0
  5. everysk/api/api_resources/__init__.py +23 -0
  6. everysk/api/api_resources/api_resource.py +371 -0
  7. everysk/api/api_resources/calculation.py +779 -0
  8. everysk/api/api_resources/custom_index.py +42 -0
  9. everysk/api/api_resources/datastore.py +81 -0
  10. everysk/api/api_resources/file.py +42 -0
  11. everysk/api/api_resources/market_data.py +223 -0
  12. everysk/api/api_resources/parser.py +66 -0
  13. everysk/api/api_resources/portfolio.py +43 -0
  14. everysk/api/api_resources/private_security.py +42 -0
  15. everysk/api/api_resources/report.py +65 -0
  16. everysk/api/api_resources/report_template.py +39 -0
  17. everysk/api/api_resources/tests.py +115 -0
  18. everysk/api/api_resources/worker_execution.py +64 -0
  19. everysk/api/api_resources/workflow.py +65 -0
  20. everysk/api/api_resources/workflow_execution.py +93 -0
  21. everysk/api/api_resources/workspace.py +42 -0
  22. everysk/api/http_client.py +63 -0
  23. everysk/api/tests.py +32 -0
  24. everysk/api/utils.py +262 -0
  25. everysk/config.py +451 -0
  26. everysk/core/_tests/serialize/test_json.py +336 -0
  27. everysk/core/_tests/serialize/test_orjson.py +295 -0
  28. everysk/core/_tests/serialize/test_pickle.py +48 -0
  29. everysk/core/cloud_function/main.py +78 -0
  30. everysk/core/cloud_function/tests.py +86 -0
  31. everysk/core/compress.py +245 -0
  32. everysk/core/datetime/__init__.py +12 -0
  33. everysk/core/datetime/calendar.py +144 -0
  34. everysk/core/datetime/date.py +424 -0
  35. everysk/core/datetime/date_expression.py +299 -0
  36. everysk/core/datetime/date_mixin.py +1475 -0
  37. everysk/core/datetime/date_settings.py +30 -0
  38. everysk/core/datetime/datetime.py +713 -0
  39. everysk/core/exceptions.py +435 -0
  40. everysk/core/fields.py +1176 -0
  41. everysk/core/firestore.py +555 -0
  42. everysk/core/fixtures/_settings.py +29 -0
  43. everysk/core/fixtures/other/_settings.py +18 -0
  44. everysk/core/fixtures/user_agents.json +88 -0
  45. everysk/core/http.py +691 -0
  46. everysk/core/lists.py +92 -0
  47. everysk/core/log.py +709 -0
  48. everysk/core/number.py +37 -0
  49. everysk/core/object.py +1469 -0
  50. everysk/core/redis.py +1021 -0
  51. everysk/core/retry.py +51 -0
  52. everysk/core/serialize.py +674 -0
  53. everysk/core/sftp.py +414 -0
  54. everysk/core/signing.py +53 -0
  55. everysk/core/slack.py +127 -0
  56. everysk/core/string.py +199 -0
  57. everysk/core/tests.py +240 -0
  58. everysk/core/threads.py +199 -0
  59. everysk/core/undefined.py +70 -0
  60. everysk/core/unittests.py +73 -0
  61. everysk/core/workers.py +241 -0
  62. everysk/sdk/__init__.py +23 -0
  63. everysk/sdk/base.py +98 -0
  64. everysk/sdk/brutils/cnpj.py +391 -0
  65. everysk/sdk/brutils/cnpj_pd.py +129 -0
  66. everysk/sdk/engines/__init__.py +26 -0
  67. everysk/sdk/engines/cache.py +185 -0
  68. everysk/sdk/engines/compliance.py +37 -0
  69. everysk/sdk/engines/cryptography.py +69 -0
  70. everysk/sdk/engines/expression.cp312-win_amd64.pyd +0 -0
  71. everysk/sdk/engines/expression.pyi +55 -0
  72. everysk/sdk/engines/helpers.cp312-win_amd64.pyd +0 -0
  73. everysk/sdk/engines/helpers.pyi +26 -0
  74. everysk/sdk/engines/lock.py +120 -0
  75. everysk/sdk/engines/market_data.py +244 -0
  76. everysk/sdk/engines/settings.py +19 -0
  77. everysk/sdk/entities/__init__.py +23 -0
  78. everysk/sdk/entities/base.py +784 -0
  79. everysk/sdk/entities/base_list.py +131 -0
  80. everysk/sdk/entities/custom_index/base.py +209 -0
  81. everysk/sdk/entities/custom_index/settings.py +29 -0
  82. everysk/sdk/entities/datastore/base.py +160 -0
  83. everysk/sdk/entities/datastore/settings.py +17 -0
  84. everysk/sdk/entities/fields.py +375 -0
  85. everysk/sdk/entities/file/base.py +215 -0
  86. everysk/sdk/entities/file/settings.py +63 -0
  87. everysk/sdk/entities/portfolio/base.py +248 -0
  88. everysk/sdk/entities/portfolio/securities.py +241 -0
  89. everysk/sdk/entities/portfolio/security.py +580 -0
  90. everysk/sdk/entities/portfolio/settings.py +97 -0
  91. everysk/sdk/entities/private_security/base.py +226 -0
  92. everysk/sdk/entities/private_security/settings.py +17 -0
  93. everysk/sdk/entities/query.py +603 -0
  94. everysk/sdk/entities/report/base.py +214 -0
  95. everysk/sdk/entities/report/settings.py +23 -0
  96. everysk/sdk/entities/script.py +310 -0
  97. everysk/sdk/entities/secrets/base.py +128 -0
  98. everysk/sdk/entities/secrets/script.py +119 -0
  99. everysk/sdk/entities/secrets/settings.py +17 -0
  100. everysk/sdk/entities/settings.py +48 -0
  101. everysk/sdk/entities/tags.py +174 -0
  102. everysk/sdk/entities/worker_execution/base.py +307 -0
  103. everysk/sdk/entities/worker_execution/settings.py +63 -0
  104. everysk/sdk/entities/workflow_execution/base.py +113 -0
  105. everysk/sdk/entities/workflow_execution/settings.py +32 -0
  106. everysk/sdk/entities/workspace/base.py +99 -0
  107. everysk/sdk/entities/workspace/settings.py +27 -0
  108. everysk/sdk/settings.py +67 -0
  109. everysk/sdk/tests.py +105 -0
  110. everysk/sdk/worker_base.py +47 -0
  111. everysk/server/__init__.py +9 -0
  112. everysk/server/applications.py +63 -0
  113. everysk/server/endpoints.py +516 -0
  114. everysk/server/example_api.py +69 -0
  115. everysk/server/middlewares.py +80 -0
  116. everysk/server/requests.py +62 -0
  117. everysk/server/responses.py +119 -0
  118. everysk/server/routing.py +64 -0
  119. everysk/server/settings.py +36 -0
  120. everysk/server/tests.py +36 -0
  121. everysk/settings.py +98 -0
  122. everysk/sql/__init__.py +9 -0
  123. everysk/sql/connection.py +232 -0
  124. everysk/sql/model.py +376 -0
  125. everysk/sql/query.py +417 -0
  126. everysk/sql/row_factory.py +63 -0
  127. everysk/sql/settings.py +49 -0
  128. everysk/sql/utils.py +129 -0
  129. everysk/tests.py +23 -0
  130. everysk/utils.py +81 -0
  131. everysk/version.py +15 -0
  132. everysk_lib-1.10.2.dist-info/.gitignore +5 -0
  133. everysk_lib-1.10.2.dist-info/METADATA +326 -0
  134. everysk_lib-1.10.2.dist-info/RECORD +137 -0
  135. everysk_lib-1.10.2.dist-info/WHEEL +5 -0
  136. everysk_lib-1.10.2.dist-info/licenses/LICENSE.txt +9 -0
  137. everysk_lib-1.10.2.dist-info/top_level.txt +2 -0
@@ -0,0 +1,603 @@
1
+ # -*- coding: utf_8 -*-
2
+ ###############################################################################
3
+ #
4
+ # (C) Copyright 2023 EVERYSK TECHNOLOGIES
5
+ #
6
+ # This is an unpublished work containing confidential and proprietary
7
+ # information of EVERYSK TECHNOLOGIES. Disclosure, use, or reproduction
8
+ # without authorization of EVERYSK TECHNOLOGIES is prohibited.
9
+ #
10
+ ###############################################################################
11
+ from typing import Any, Self, Generator, TypedDict, Callable
12
+ from inspect import isclass
13
+
14
+ from everysk.config import settings
15
+ from everysk.core.datetime import Date, DateTime
16
+ from everysk.core.exceptions import SDKValueError, FieldValueError, SDKTypeError
17
+ from everysk.core.fields import StrField, IntField, ListField, BoolField
18
+ from everysk.core.object import BaseDict, BaseDictConfig
19
+ from everysk.core.string import is_string_object, normalize_string_to_search, import_from_string
20
+ from everysk.sdk.base import BaseSDK
21
+
22
+
23
+ ###############################################################################
24
+ # QueryPage Class Implementation
25
+ ###############################################################################
26
+ class QueryPage(TypedDict):
27
+ """
28
+ A dictionary containing the paginated list of entities and a next page token.
29
+
30
+ Attributes:
31
+ entities (list[Any]): The list of entities for the current page.
32
+ next_page_token (str): The token representing the next page of results.
33
+ """
34
+ entities: list[Any] = None
35
+ next_page_token: str = None
36
+
37
+
38
+ ###############################################################################
39
+ # Query Class Implementation
40
+ ###############################################################################
41
+ class Query(BaseDict, BaseSDK):
42
+ """
43
+ This class allows you to build a query to retrieve entities from the data source
44
+ based on certain conditions. The query can be executed to retrieve a single entity,
45
+ a list of entities, or a paginated list of entities.
46
+
47
+ Attributes:
48
+ _klass (Any): The class of the entity to be queried.
49
+ _clean_order (set): The set of properties by which to sort the query.
50
+ _find_or_fail (bool): A boolean value indicating whether the query should return an error if no entity is found.
51
+ filters (list): The list of filter conditions for the query.
52
+ order (list): The list of properties by which to sort the query.
53
+ projection (list): The list of properties to include or exclude in the query result.
54
+ distinct_on (list): The list of properties for which the resulting entities should be distinct.
55
+ limit (int): The maximum number of entities to retrieve.
56
+ offset (int): The number of initial entities to skip before starting retrieval.
57
+ page_size (int): The number of entities to retrieve per page.
58
+ page_token (str): The token representing the desired page of results.
59
+
60
+ Example:
61
+ To create a query to retrieve a single entity:
62
+ entity = Query(MyEntity).where('property_name', 'value').load()
63
+
64
+ To create a query to retrieve a list of entities:
65
+ entities = Query(MyEntity).where('property_name', 'value').loads()
66
+
67
+ To create a query to retrieve a paginated list of entities:
68
+ entities_page = Query(MyEntity).where('property_name', 'value').page()
69
+ """
70
+
71
+ class Config(BaseDictConfig):
72
+ exclude_keys: frozenset[str] = frozenset(['_is_frozen', '_silent', '_errors', '_orderable_attributes'])
73
+
74
+ _klass: Callable = None
75
+ _config: Config = None
76
+ _clean_order: set = None
77
+ _find_or_fail = BoolField(default=False)
78
+
79
+ # QUERY PARAMETERS
80
+ filters = ListField()
81
+ order = ListField()
82
+ projection = ListField()
83
+
84
+ # LOAD / LOADS PARAMETERS
85
+ limit = IntField()
86
+ offset = IntField()
87
+
88
+ # PAGE / PAGES PARAMETERS
89
+ page_size = IntField()
90
+ page_token = StrField()
91
+
92
+ def __init__(self, _klass: Callable, filters: list | None = None, order: list | None = None, projection: list | None = None, distinct_on: list | None = None,
93
+ limit: int | None = None, offset: int | None = None, page_size: int | None = None, page_token: str | None = None, **kwargs):
94
+
95
+ _clean_order = kwargs.pop('_clean_order', None)
96
+
97
+ # Initialize the query with the provided parameters, setting each parameter to None. Each parameter is
98
+ # associated with a respective function that will assign its value and perform validation.
99
+ super().__init__(_klass=None, filters=None, order=None, projection=None, distinct_on=None, limit=None,
100
+ offset=None, page_size=None, page_token=None, **kwargs)
101
+
102
+ if _klass is not None and not isclass(_klass):
103
+ try:
104
+ _klass = import_from_string(settings.EVERYSK_SDK_ENTITIES_MODULES_PATH[_klass])
105
+ except KeyError:
106
+ raise FieldValueError(f"The _klass value '{_klass}' must be a class or a string with the class name") from KeyError
107
+
108
+ self._klass = _klass
109
+ self._clean_order = set()
110
+
111
+ order = [] if order is None else order
112
+ self.order = []
113
+ for property_name in order:
114
+ self.sort_by(property_name)
115
+
116
+ if _clean_order and not isinstance(_clean_order, (list, set)):
117
+ raise FieldValueError(f'Key _clean_order must be {set}')
118
+ elif _clean_order:
119
+ self._clean_order = self._clean_order.union( _clean_order)
120
+
121
+ filters = [] if filters is None else filters
122
+ self.filters = []
123
+ for filter_set in filters:
124
+ self.where(*filter_set)
125
+
126
+ if projection is not None:
127
+ self.set_projection(projection)
128
+
129
+ distinct_on = [] if distinct_on is None else distinct_on
130
+ self.set_distinct_on(distinct_on)
131
+
132
+ if limit is not None:
133
+ self.set_limit(limit)
134
+
135
+ if offset is not None:
136
+ self.set_offset(offset)
137
+
138
+ if page_size is not None:
139
+ self.set_page_size(page_size)
140
+
141
+ if page_token is not None:
142
+ self.set_page_token(page_token)
143
+
144
+ def _process__klass(self, value: Any) -> Any:
145
+ """
146
+ This method is used to process the '_klass' attribute.
147
+ """
148
+ return value.__name__
149
+
150
+ def where(self, *args) -> Self:
151
+ """
152
+ Adds a filter condition to the query.
153
+
154
+ Args:
155
+ *args: Variable number of arguments. Expected formats are:
156
+ - (property_name, value)
157
+ - (property_name, operator, value)
158
+
159
+ Returns:
160
+ self: The Query object with the added filter condition.
161
+
162
+ Raises:
163
+ ValueError: If the number of arguments is not 2 or 3, indicating an incorrect format.
164
+ ValueError: If the operator is not '=' and property_name is not one of ('date', 'created_on', 'updated_on').
165
+
166
+ Example:
167
+ To create a query with a filter condition:
168
+ query = Query(MyEntity).where('property_name', 'value')
169
+
170
+ To create a query with a filter condition using an operator:
171
+ query = Query(MyEntity).where('property_name', '>', 'value')
172
+ """
173
+ property_name: str = args[0]
174
+ operator: str | None = None
175
+ value: str | None = None
176
+
177
+ if len(args) == 2:
178
+ operator = '='
179
+ value = args[1]
180
+ elif len(args) == 3:
181
+ operator = args[1]
182
+ value = args[2]
183
+ else:
184
+ raise SDKValueError('Query \'where\' function expects 2 or 3 arguments')
185
+
186
+ if operator not in settings.QUERY_OPERATORS:
187
+ raise SDKValueError(f'Invalid operator: {operator} for property {property_name}')
188
+
189
+ # Validate the operator for certain properties
190
+ if operator != '=' and property_name not in self._klass._allowed_query_attributes_for_all_operators:
191
+ raise SDKValueError(f"Filter by {property_name} operator must be '='")
192
+
193
+ if not value:
194
+ # Handle special case for searching null values like link_uid or date
195
+ self.filters.append((property_name, operator, value))
196
+ return self
197
+
198
+ # Handle special case for 'tags' property
199
+ if property_name == 'tags':
200
+ if isinstance(value, list):
201
+ self.filters.extend([('tags', '=', tag.lower().strip()) for tag in value])
202
+ elif isinstance(value, str):
203
+ self.filters.append(('tags', '=', value.lower().strip()))
204
+ else:
205
+ raise SDKTypeError('The tags value must be a string or a list of strings')
206
+
207
+ return self
208
+
209
+ # Handle special case for 'date' property
210
+ if property_name == 'date':
211
+ if is_string_object(value):
212
+ value = DateTime.fromisoformat(value).replace(hour=12, minute=0, second=0, microsecond=0)
213
+
214
+ elif Date.is_date(value):
215
+ value = DateTime.date_to_date_time(value)
216
+
217
+ if operator == '=':
218
+ start = value.replace(hour=0, minute=0, second=0, microsecond=0)
219
+ end = value.replace(hour=23, minute=59, second=59, microsecond=999999)
220
+
221
+ self.filters.append(('date', '>=', start))
222
+ self.filters.append(('date', '<=', end))
223
+
224
+ else:
225
+ if operator in ('>', '>='):
226
+ value = value.replace(hour=0, minute=0, second=0, microsecond=0)
227
+
228
+ elif operator in ('<', '<='):
229
+ value = value.replace(hour=23, minute=59, second=59, microsecond=999999)
230
+
231
+ self.filters.append((property_name, operator, value))
232
+
233
+ return self
234
+
235
+ # Handle special case for 'name' property
236
+ if property_name == 'name' and operator == '=':
237
+ value = normalize_string_to_search(value)
238
+
239
+ limit: str = f'{value[:-1]}{chr(ord(value[-1]) + 1)}'
240
+ self.filters.append((property_name, '<', limit))
241
+ self.filters.append((property_name, '>=', value))
242
+
243
+ return self
244
+
245
+ # Regular filter condition
246
+ self.filters.append((property_name, operator, value))
247
+
248
+ return self
249
+
250
+ def sort_by(self, property_name: str) -> Self:
251
+ """
252
+ Add a property by which to sort the query and return the instance.
253
+ This method updates the query's order based on the provided property_name.
254
+
255
+ Args:
256
+ - property_name (str): The name of the property to sort by. It can optionally
257
+ contain hyphens, which will be removed.
258
+
259
+ Returns:
260
+ - Query: The instance of the current object.
261
+
262
+ Raises:
263
+ - ValueError: If the provided property_name is not sortable or if the
264
+ property_name is duplicated in the current order.
265
+
266
+ Example:
267
+ To create a query with a sort condition:
268
+ >>> query = Query(MyEntity).sort_by('property_name')
269
+
270
+ """
271
+ clean_name: str = property_name.replace('-', '')
272
+
273
+ if clean_name not in self._klass._orderable_attributes: # pylint: disable=protected-access
274
+ raise ValueError(f'{clean_name} is not sortable')
275
+
276
+ if clean_name in self._clean_order:
277
+ raise ValueError(f'Duplicated order property: {clean_name} in {self.order}')
278
+
279
+ self.order.append(property_name)
280
+ self._clean_order.add(clean_name)
281
+
282
+ return self
283
+
284
+ def set_projection(self, projection: list | str) -> Self:
285
+ """
286
+ Set the projection attributes for the query and return the instance.
287
+
288
+ This method sets the desired properties that should be returned in the query result.
289
+ The properties can either be set to include (using the property name) or to exclude
290
+ (prefixing the property name with '-'). Both inclusion and exclusion should not be set
291
+ in the same query.
292
+
293
+ Args:
294
+ - projection (Union[List, str]): A property name as a string or a list of property names
295
+ indicating which properties to include or exclude in the query result.
296
+
297
+ Returns:
298
+ - Query: The instance of the current object.
299
+
300
+ Raises:
301
+ - ValueError: If both projection and inverse projection are set in the same query or
302
+ if the projection properties do not belong to the entity kind.
303
+
304
+ Example:
305
+ To create a query with a projection condition:
306
+ >>> query = Query(MyEntity).set_projection('property_name')
307
+
308
+ To create a query with an inverse projection condition:
309
+ >>> query = Query(MyEntity).set_projection('-property_name')
310
+
311
+ To create a query with a projection condition using a list:
312
+ >>> query = Query(MyEntity).set_projection(['property_name_1', 'property_name_2'])
313
+ """
314
+ self.projection = self._klass._normalize_projection(projection) # pylint: disable=protected-access
315
+ return self
316
+
317
+ def set_distinct_on(self, distinct_on: list | str) -> Self:
318
+ """
319
+ Set the attributes for which the query results should be distinct.
320
+
321
+ This method allows you to specify properties such that the resulting entities
322
+ of the query are distinct with respect to these properties.
323
+
324
+ Args:
325
+ - distinct_on (Union[List, str]): A property name as a string or a list of property names
326
+ for which the resulting entities should be distinct.
327
+
328
+ Returns:
329
+ - Query: The instance of the current object, allowing for method chaining.
330
+
331
+ Example:
332
+ To create a query with a distinct condition:
333
+ >>> query = Query(MyEntity).set_distinct_on('property_name')
334
+
335
+ To create a query with a distinct condition using a list:
336
+ >>> query = Query(MyEntity).set_distinct_on(['property_name_1', 'property_name_2'])
337
+ """
338
+
339
+ if is_string_object(distinct_on):
340
+ distinct_on = [distinct_on]
341
+
342
+ self.distinct_on = distinct_on
343
+ return self
344
+
345
+ def set_limit(self, limit: int) -> Self:
346
+ """
347
+ Set the maximum number of results the query should return.
348
+
349
+ This method defines the maximum number of entities to retrieve from the database
350
+ when the query is executed.
351
+
352
+ Args:
353
+ - limit (int): The maximum number of results to retrieve.
354
+
355
+ Returns:
356
+ - Query: The instance of the current object, allowing for method chaining.
357
+
358
+ Example:
359
+ To create a query with a limit condition:
360
+ >>> query = Query(MyEntity).set_limit(10)
361
+ """
362
+ if not isinstance(limit, int):
363
+ raise SDKValueError('The limit value must be an integer.')
364
+ if isinstance(limit, int) and limit < 0:
365
+ raise SDKValueError('The limit value must be greater than or equal to 0.')
366
+
367
+ self.limit = limit
368
+ return self
369
+
370
+ def set_offset(self, offset: int) -> Self:
371
+ """
372
+ Set the starting point from which to retrieve the results in the query.
373
+
374
+ This method specifies the number of initial results to skip before starting to
375
+ retrieve entities when the query is executed.
376
+
377
+ Args:
378
+ - offset (int): The number of results to skip before retrieval begins.
379
+
380
+ Returns:
381
+ - Query: The instance of the current object, allowing for method chaining.
382
+
383
+ Example:
384
+ To create a query with an offset condition:
385
+ >>> query = Query(MyEntity).set_offset(10)
386
+ """
387
+ if not isinstance(offset, int):
388
+ raise SDKValueError('The offset value must be an integer.')
389
+ if isinstance(offset, int) and offset < 0:
390
+ raise SDKValueError('The offset value must be greater than or equal to 0.')
391
+
392
+ self.offset = offset
393
+ return self
394
+
395
+ def set_page_size(self, page_size: int) -> Self:
396
+ """
397
+ Set the number of results to be returned per page for the query.
398
+
399
+ This method determines how many entities are retrieved at once in a paginated
400
+ manner when the query is executed.
401
+
402
+ Args:
403
+ - page_size (int): The number of results to retrieve per page.
404
+
405
+ Returns:
406
+ - Query: The instance of the current object, allowing for method chaining.
407
+
408
+ Example:
409
+ To create a query with a page size condition:
410
+ >>> query = Query(MyEntity).set_page_size(10)
411
+ """
412
+ if not isinstance(page_size, int):
413
+ raise SDKValueError('The page_size value must be an integer.')
414
+ if isinstance(page_size, int) and page_size < 0:
415
+ raise SDKValueError('The page_size value must be greater than or equal to 0.')
416
+
417
+ self.page_size = page_size
418
+ return self
419
+
420
+ def set_page_token(self, page_token: str) -> Self:
421
+ """
422
+ Set the token representing a specific page of results in the query.
423
+
424
+ This method determines the starting point for retrieving entities based on the
425
+ provided page token when the query is executed.
426
+
427
+ Args:
428
+ - page_token (str): The token representing the desired page of results.
429
+
430
+ Returns:
431
+ - Query: The instance of the current object, allowing for method chaining.
432
+
433
+ Example:
434
+ To create a query with a page token condition:
435
+ >>> query = Query(MyEntity).set_page_token('page_token')
436
+ """
437
+ self.page_token = page_token
438
+ return self
439
+
440
+ def set_find_or_fail(self, find_or_fail: bool) -> Self:
441
+ """
442
+ Set the find_or_fail attribute for the query and return the instance.
443
+
444
+ This method sets the desired find_or_fail attribute that should be returned in the query result.
445
+
446
+ Args:
447
+ - find_or_fail (bool): A boolean value indicating whether the query should return an error if no entity is found.
448
+
449
+ Returns:
450
+ - Query: The instance of the current object.
451
+
452
+ Example:
453
+ To create a query with a find_or_fail condition:
454
+ >>> query = Query(MyEntity).set_find_or_fail(True)
455
+ """
456
+ self._find_or_fail = find_or_fail
457
+ return self
458
+
459
+ def load(self, offset: int = Undefined) -> Any:
460
+ """
461
+ Fetch a single entity based on the query with an optional offset.
462
+
463
+ This method retrieves a single entity from the data source based on the conditions
464
+ specified in the query. An optional offset can be provided to skip a certain number
465
+ of results before fetching the desired entity.
466
+
467
+ Args:
468
+ - offset (int, optional): The number of results to skip before fetching the entity.
469
+ Defaults to None, meaning no results are skipped.
470
+
471
+ Returns:
472
+ - Any: An instance of the entity, or None if no entity matches the query.
473
+
474
+ Example:
475
+ To create a query with a load condition:
476
+ >>> entity = Query(MyEntity).where('property_name', 'value').load()
477
+ """
478
+ entity: Any | None = self.get_response(self_obj=self, params={'offset': offset})
479
+
480
+ if entity is not None:
481
+ entity = self._klass(**entity)
482
+
483
+ return entity
484
+
485
+ def loads(self, limit: int = Undefined, offset: int = Undefined) -> list[Any]:
486
+ """
487
+ Fetch a list of entities based on the query with optional limit and offset.
488
+
489
+ This method retrieves multiple entities from the data source based on the conditions
490
+ specified in the query. Optional limit and offset parameters can be provided to control
491
+ the number of returned entities and the starting point, respectively.
492
+
493
+ Args:
494
+ - limit (int, optional): The maximum number of entities to retrieve. Defaults to None,
495
+ meaning there's no specific limit.
496
+ - offset (int, optional): The number of initial entities to skip before starting retrieval.
497
+ Defaults to None, meaning no entities are skipped.
498
+
499
+ Returns:
500
+ - List[Any]: A list of instances of the entity. Returns an empty list if no entities match
501
+ the query.
502
+
503
+ Example:
504
+ To create a query with a loads condition:
505
+ >>> entities = Query(MyEntity).where('property_name', 'value').loads()
506
+ """
507
+ entities: list[dict] = self.get_response(self_obj=self, params={'limit': limit, 'offset': offset})
508
+
509
+ entities: list[Any] = [self._klass(**entity) for entity in entities]
510
+
511
+ return entities
512
+
513
+ def page(self, page_size: int = Undefined, page_token: str = Undefined) -> QueryPage:
514
+ """
515
+ Fetch a paginated list of entities based on the query.
516
+
517
+ This method retrieves a paginated set of entities from the data source based on the conditions
518
+ specified in the query. A specific page size and an optional page token can be provided to
519
+ control pagination.
520
+
521
+ Args:
522
+ - page_size (int, optional): The number of entities to retrieve per page. Defaults to 20.
523
+ - page_token (str, optional): The token representing the desired page of results. Defaults to None,
524
+ meaning the first page is retrieved.
525
+
526
+ Returns:
527
+ - Any: A dictionary containing the paginated list of entities and potentially other metadata
528
+ related to pagination.
529
+
530
+ Example:
531
+ To create a query with a page condition:
532
+ >>> entities_page = Query(MyEntity).where('property_name', 'value').page()
533
+ """
534
+ response: QueryPage = self.get_response(self_obj=self, params={'page_size': page_size, 'page_token': page_token})
535
+
536
+ response['entities'] = [self._klass(**entity) for entity in response['entities']]
537
+
538
+ return response
539
+
540
+ def pages(self, page_size: int = Undefined) -> Generator[list[Any | None], None, None]:
541
+ """
542
+ Fetch paginated lists of entities based on the query.
543
+
544
+ This method retrieves multiple pages of entities from the data source based on the conditions
545
+ specified in the query. Each page will contain up to `page_size` entities. This function yields
546
+ each page of entities as they are retrieved.
547
+
548
+ Args:
549
+ - page_size (int, optional): The number of entities to retrieve per page. Defaults to 20.
550
+
551
+ Yields:
552
+ - List[Any]: A list of entities for the current page.
553
+
554
+ Note:
555
+ This generator function will continue to fetch and yield pages until no more pages are available.
556
+
557
+ Example:
558
+ To create a query with a pages condition:
559
+ >>> for entities in Query(MyEntity).where('property_name', 'value').pages():
560
+ ... print(entities)
561
+ """
562
+ next_page_token: str = Undefined
563
+
564
+ while True:
565
+ result: QueryPage = self.page(page_size=page_size, page_token=next_page_token)
566
+ yield result['entities']
567
+
568
+ if not result['next_page_token']:
569
+ break
570
+
571
+ next_page_token = result['next_page_token']
572
+
573
+ def fetch_ids(self, limit: int = Undefined, offset: int = Undefined) -> list[str]:
574
+ """
575
+ Fetch a list of entity IDs based on the query.
576
+
577
+ This method retrieves a list of entity IDs from the data source based on the conditions
578
+ specified in the query.
579
+
580
+ Returns:
581
+ - List[str]: A list of entity IDs. Returns an empty list if no entities match the query.
582
+
583
+ Example:
584
+ To create a query with a fetch_ids condition:
585
+ >>> entity_ids = Query(MyEntity).where('property_name', 'value').fetch_ids()
586
+ """
587
+ return self.get_response(self_obj=self, params={'limit': limit, 'offset': offset})
588
+
589
+ def fetch_id(self, offset: int = Undefined) -> str | None:
590
+ """
591
+ Load a single entity matching the query and return its id.
592
+
593
+ Args:
594
+ offset (int, optional): The offset of the entity to load. Defaults to DEFAULT_QUERY_OFFSET.
595
+
596
+ Returns:
597
+ str: The id of the entity, or None if no entity is found.
598
+
599
+ Example:
600
+ To create a query with a fetch_id condition:
601
+ >>> entity_id = Query(MyEntity).where('property_name', 'value').fetch_id()
602
+ """
603
+ return self.get_response(self_obj=self, params={'offset': offset})