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
everysk/config.py ADDED
@@ -0,0 +1,451 @@
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 contextlib import AbstractContextManager
11
+ from contextvars import ContextVar
12
+ from copy import deepcopy
13
+ from importlib import import_module
14
+ from inspect import getmembers, isroutine, isclass
15
+ from os import getenv
16
+ from os.path import dirname, exists, sep
17
+ from pathlib import Path, PosixPath
18
+ from re import findall
19
+ from types import TracebackType, UnionType
20
+ from typing import Any
21
+
22
+ from everysk.core.object import BaseObject, MetaClass
23
+ from everysk.utils import bool_convert
24
+
25
+
26
+ # The root path of the everysk lib we need this to create the correct stub file
27
+ EVERYSK_ROOT = dirname(__file__)
28
+
29
+
30
+ ###############################################################################
31
+ # Private Functions Implementation
32
+ ###############################################################################
33
+ def _get_context_value(name: str) -> Any:
34
+ """
35
+ If we are in a python context we return the value
36
+ that is in the context setting.
37
+ If the settings is not found we raise a KeyError.
38
+
39
+ Args:
40
+ name (str): The settings name.
41
+
42
+ Raises:
43
+ KeyError: If the name is not found.
44
+ """
45
+ context_settings = SettingsManager.settings.get()
46
+ # We only care for the values that are explicit set in this settings
47
+ if context_settings:
48
+ return context_settings.__dict__.get(name, Undefined)
49
+
50
+ return Undefined
51
+
52
+ def _get_env_value__(name: str) -> Any:
53
+ """
54
+ Get the value from the environment and clean it.
55
+
56
+ Args:
57
+ name (str): The var name to search.
58
+ """
59
+ env_value = getenv(name)
60
+
61
+ # This is a check to always get the correct value
62
+ # that we received from the environment
63
+ # https://everysk.atlassian.net/browse/COD-907
64
+ if env_value is not None:
65
+ attributes = getattr(Settings, SettingsMetaClass._attr_name, {}) # pylint: disable=protected-access
66
+ try:
67
+ attr_type = attributes[name]
68
+ try:
69
+ # Our fields have the clean_value method
70
+ env_value = attr_type.clean_value(env_value)
71
+
72
+ except AttributeError:
73
+ # For the other types we try to convert the
74
+ # value to the specific type that was declared
75
+ # For bool types we use a specific function
76
+ if attr_type != bool:
77
+ env_value = attr_type(env_value)
78
+ else:
79
+ env_value = bool_convert(env_value)
80
+
81
+ except KeyError:
82
+ pass
83
+ else:
84
+ # If env_value is None then the var was not set
85
+ env_value = Undefined
86
+
87
+ return env_value
88
+
89
+ def _is_valid_path(path: str) -> bool:
90
+ """
91
+ Function that checks if a path is valid to load the settings module.
92
+
93
+ Args:
94
+ path (str): The full path that need be checked.
95
+ """
96
+ result = True
97
+ # Python installation normally happens on venvs that are in the project path
98
+ if 'site-packages/' in path:
99
+ result = False
100
+
101
+ # Git files could have copies of python files
102
+ elif '.git/' in path:
103
+ result = False
104
+
105
+ return result
106
+
107
+
108
+ ###############################################################################
109
+ # Public Functions Implementation
110
+ ###############################################################################
111
+ def get_full_dotted_path_module(entry: PosixPath, root: str) -> str:
112
+ """
113
+ From the full path we need to generate the module that is valid for import.
114
+ Changes '/var/app/src/everysk/settings.py' to 'everysk.settings'.
115
+
116
+ Args:
117
+ entry (PosixPath): The posix path object.
118
+ root (str): The root path that will be removed.
119
+ """
120
+ # /var/app/src/everysk/settings.py
121
+ module = str(entry)
122
+
123
+ # everysk/settings.py
124
+ module = module.replace(f'{root}{sep}', '')
125
+
126
+ # everysk/settings
127
+ module = module.replace('.py', '')
128
+
129
+ # everysk.settings
130
+ module = module.replace(sep, '.')
131
+
132
+ return module
133
+
134
+ def get_all_modules() -> list:
135
+ """
136
+ We search inside EVERYSK_ROOT and PROJECT_ROOT for 'settings.py'
137
+ files and convert this files into python modules.
138
+
139
+ Returns:
140
+ list: A list of Python modules
141
+
142
+ Example:
143
+ >>> all_modules = get_all_modules()
144
+ >>> print(all_modules)
145
+ ... ['module1', 'module2']
146
+ """
147
+ search_name = 'settings.py'
148
+ modules = []
149
+ if EVERYSK_ROOT and exists(EVERYSK_ROOT):
150
+ # we need to remove the '/everysk' from the path to create the correct module path
151
+ root = EVERYSK_ROOT.replace(f'{sep}everysk', '')
152
+ for entry in Path(EVERYSK_ROOT).rglob(search_name):
153
+ modules.append(get_full_dotted_path_module(entry=entry, root=root))
154
+
155
+ project_root = getenv('PROJECT_ROOT')
156
+ if project_root and exists(project_root):
157
+ for entry in Path(project_root).rglob(search_name):
158
+ # The rglob function does not have a way to remove some paths
159
+ # so we need to manually exclude the ones that are not required
160
+ if _is_valid_path(path=entry.as_posix()):
161
+ modules.append(get_full_dotted_path_module(entry=entry, root=project_root))
162
+
163
+ return modules
164
+
165
+ def get_all_attributes() -> list[tuple[str, Any, Any]]:
166
+ """
167
+ Get all attributes from the settings modules except ones that starts with '_'
168
+
169
+ Example:
170
+ Consider a settings module 'my_settings.py' containing the following attributes:
171
+
172
+ ...
173
+ MY_SETTING_1 = 42
174
+ MY_SETTING_2 = 'Hello, World!'
175
+ _MY_SETTING_3 = 'Foo Bar'
176
+ ...
177
+
178
+ Calling get_all_attributes() will return:
179
+
180
+ [
181
+ ('MY_SETTING_1', int, 42),
182
+ ('MY_SETTING_2', str, 'Hello, World!')
183
+ ]
184
+ """
185
+ result = []
186
+
187
+ for module in get_all_modules():
188
+ # Import the module
189
+ module = import_module(module)
190
+
191
+ for attr, value in getmembers(module, predicate=lambda x: not isroutine(x) and not isclass(x)):
192
+ if not attr.startswith('_'):
193
+ try:
194
+ attr_value = value.default
195
+ attr_type = value
196
+ except AttributeError:
197
+ attr_value = value
198
+ # If this attribute already has an annotation on the module we use it
199
+ # otherwise we get the class of the value as the annotation
200
+ # https://everysk.atlassian.net/browse/COD-3833
201
+ attr_type = module.__annotations__.get(attr, type(value))
202
+
203
+ result.append((attr, attr_type, attr_value))
204
+ return result
205
+
206
+ def update_settings_attributes(obj: 'Settings'):
207
+ """
208
+ Updates the attributes of the Settings class in the config.pyi file.
209
+
210
+ This function updates the attribute definitions of the Settings class based on the attributes retrieved from the `get_all_attributes` function.
211
+
212
+ Example:
213
+ >>> from everysk.config import update_settings_attributes
214
+ >>> update_settings_attribute()
215
+ ...
216
+ """
217
+ with open(f'{EVERYSK_ROOT}/config.pyi', 'w', encoding='utf-8') as stubs:
218
+ # This fix the correct type of SettingsManager.settings
219
+ stubs.write('from contextvars import ContextVar\n')
220
+
221
+ # This fix the stub file for the RegexField
222
+ stubs.write('from re import Pattern\n\n')
223
+
224
+ # Now we have dict and BaseDict in the stub file too
225
+ stubs.write('from everysk.core.object import BaseDict\n\n')
226
+
227
+ # Write the SettingsManager class
228
+ stubs.write('class SettingsManager:\n')
229
+ stubs.write(' settings: ContextVar\n')
230
+ stubs.write(' token: str\n\n')
231
+
232
+ # Write the Settings class
233
+ stubs.write('class Settings:\n')
234
+
235
+ attributes = set()
236
+ for attr_name, attr_type, attr_value in get_all_attributes():
237
+ obj.__set_attribute__(attr_name, attr_type, attr_value)
238
+ try:
239
+ # If attr_type is a Everysk Field the real value will be in the attr_type attribute
240
+ attr_type = attr_type.attr_type
241
+ except AttributeError:
242
+ pass
243
+
244
+ # For Union types we need to get the real types inside __args__
245
+ if not isinstance(attr_type, UnionType):
246
+ attr_type = attr_type.__name__
247
+ else:
248
+ attr_type = ' | '.join([t.__name__ for t in attr_type.__args__])
249
+
250
+ # We could have some duplicated attributes so we keep then in a set
251
+ attributes.add(f' {attr_name}: {attr_type}\n')
252
+
253
+ # Then we write all attributes in the stub file
254
+ stubs.writelines(sorted(attributes))
255
+ # To autocomplete the init params
256
+ stubs.write(' def __init__(self, singleton: bool = True, **kwargs) -> None: ...\n')
257
+ # Fix for the autocomplete works if a context var is created
258
+ stubs.write(' def __enter__(self) -> \'Settings\': ...\n')
259
+
260
+ # This is needed to VS Code understand the instance
261
+ stubs.write('\nsettings: Settings\n')
262
+
263
+
264
+ ###############################################################################
265
+ # SettingsManager Class Implementation
266
+ ###############################################################################
267
+ class SettingsManager(AbstractContextManager):
268
+ settings: ContextVar = ContextVar('everysk-settings', default=None)
269
+ token: str = None
270
+
271
+ def __init__(self, context_settings: 'Settings' = Undefined) -> None:
272
+ if context_settings:
273
+ # We make a copy to not change the original
274
+ context_settings = deepcopy(context_settings)
275
+ else:
276
+ # We create a fresh one
277
+ context_settings = Settings(singleton=False)
278
+
279
+ # Store the value inside the context var
280
+ self.token = self.settings.set(context_settings)
281
+
282
+ def __exit__(self, __exc_type: type[BaseException] | None, __exc_value: BaseException | None, __traceback: TracebackType | None) -> bool | None:
283
+ """
284
+ https://docs.python.org/3/library/stdtypes.html#contextmanager.__exit__
285
+
286
+ Returns:
287
+ bool | None: If return is False any exception will be raised.
288
+ """
289
+ # Clear all settings config exiting the context
290
+ self.settings.reset(self.token)
291
+
292
+ # return False to raise any errors if they happened
293
+ return False
294
+
295
+
296
+ ###############################################################################
297
+ # SettingsMetaClass Class Implementation
298
+ ###############################################################################
299
+ class SettingsMetaClass(MetaClass):
300
+
301
+ def __new__(mcs, name: str, bases: tuple, attrs: dict) -> type:
302
+ """
303
+ Method that create the class object.
304
+
305
+ Args:
306
+ mcs (_type_): This class.
307
+ name (str): The name of the new class -> Settings.
308
+ bases (tuple): Parent for the new class -> BaseObject.
309
+ attrs (dict): A list of attributes tha the new class will have.
310
+ """
311
+ obj = super().__new__(mcs, name, bases, attrs)
312
+
313
+ # This is executed only one time for every python process
314
+ # before the initialization of the instance, we update the attributes list
315
+ update_settings_attributes(obj)
316
+
317
+ return obj
318
+
319
+
320
+ ###############################################################################
321
+ # Settings Class Implementation
322
+ ###############################################################################
323
+ class Settings(BaseObject, metaclass=SettingsMetaClass):
324
+
325
+ def __new__(cls, singleton: bool = True, **kwargs) -> 'Settings':
326
+ """
327
+ Changed to keep only one instance for the class.
328
+
329
+ Args:
330
+ singleton (bool): Used to keep the same instance. Defaults to True.
331
+ """
332
+ if singleton:
333
+ try:
334
+ return settings
335
+ except NameError:
336
+ pass
337
+
338
+ return object.__new__(cls)
339
+
340
+ def __init__(self, **kwargs) -> None:
341
+ # remove the singleton keyword
342
+ if 'singleton' in kwargs:
343
+ kwargs.pop('singleton')
344
+
345
+ super().__init__(**kwargs)
346
+
347
+ def __deepcopy__(self, memo: dict = None) -> 'Settings':
348
+ """
349
+ A deep copy constructs a new compound object and then, recursively,
350
+ inserts copies into it of the objects found in the original.
351
+ This method is used when we call deepcopy(obj).
352
+
353
+ Args:
354
+ memo (dict, optional): A memory object to avoid copy twice. Defaults to None.
355
+ """
356
+ # We need to copy the __dict__
357
+ obj = deepcopy(self.__dict__, memo)
358
+
359
+ # We create a new obj
360
+ obj = type(self)(singleton=False, **obj)
361
+ return obj
362
+
363
+ def __enter__(self) -> 'Settings':
364
+ """
365
+ https://docs.python.org/3/library/stdtypes.html#contextmanager.__enter__
366
+
367
+ Returns:
368
+ Settings: A copy of the settings object.
369
+ """
370
+ # We must use deepcopy to keep all values that are already set
371
+ return deepcopy(settings)
372
+
373
+ def __exit__(self, __exc_type: type[BaseException] | None, __exc_value: BaseException | None, __traceback: TracebackType | None) -> bool | None:
374
+ """
375
+ https://docs.python.org/3/library/stdtypes.html#contextmanager.__exit__
376
+ This method is required even if it only returns False
377
+
378
+ Returns:
379
+ bool | None: If return is False any exception will be raised.
380
+ """
381
+ return False
382
+
383
+ def __getattribute__(self, name: str) -> Any:
384
+ """
385
+ This method try to first get the value from the environment
386
+ if this does not exists get from the class.
387
+
388
+ Args:
389
+ name (str): The setting name.
390
+ """
391
+ ## For performance and to avoid some errors because
392
+ ## we are trying to get other things that does not
393
+ ## are attributes of this class
394
+ if name.startswith('__') or name == '_config':
395
+ return super().__getattribute__(name)
396
+
397
+ # First we try to get the value from the context
398
+ value = _get_context_value(name)
399
+ if value is Undefined:
400
+ # Second we try to get the value from the instance
401
+ value = self.__dict__.get(name, Undefined)
402
+ if value is Undefined:
403
+ # Third we try to get from the environment
404
+ value = _get_env_value__(name)
405
+ if value is Undefined:
406
+ # Fourth we try to get from the class that is the default value
407
+ value = super().__getattribute__(name)
408
+
409
+ if isinstance(value, str):
410
+ try:
411
+ # If is a normal string nothing happen
412
+ value = value.format()
413
+ except KeyError:
414
+ # Otherwise is a string in this format:
415
+ # '{SOME_SETTING}-rest-string' so we need to change SOME_SETTING
416
+ # for the real value that is a settings
417
+
418
+ # We get all {*} that appears
419
+ keys = findall(r'{(.*?)}', value)
420
+ # Then we get the real value of each key
421
+ kwargs = {key: getattr(self, key) for key in keys}
422
+ # Then we try to format the real string
423
+ value = value.format(**kwargs)
424
+
425
+ return value
426
+
427
+ def __setattr__(self, name: str, value: Any) -> None:
428
+ """
429
+ This method set the value of every attribute inside the Settings object,
430
+ we use it to choose if we set on the normal object or in the context object.
431
+ If the context_settings exists it sets the value inside the context_settings.
432
+
433
+ Args:
434
+ name (str): The name of the attribute.
435
+ value (Any): The value that needs to be stored.
436
+ """
437
+ context_settings = SettingsManager.settings.get()
438
+ # If context settings does not exist or it is a context_settings
439
+ # that is trying to store the value for this setting we use the default behavior
440
+ if not context_settings or context_settings == self:
441
+ super().__setattr__(name, value)
442
+ else:
443
+ # Otherwise we call the set for context_settings
444
+ setattr(context_settings, name, value)
445
+ SettingsManager.settings.set(context_settings)
446
+
447
+
448
+ ###############################################################################
449
+ # Here we load all computed settings on one var
450
+ ###############################################################################
451
+ settings: Settings = Settings()