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
everysk/core/string.py
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
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
|
+
import re
|
|
11
|
+
from typing import Any
|
|
12
|
+
from re import compile as compile_re
|
|
13
|
+
from importlib import import_module
|
|
14
|
+
from unicodedata import normalize
|
|
15
|
+
from six import string_types, ensure_str, text_type
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
RE_ISIN = compile_re(r'^[a-zA-Z]{2}\s*[0-9a-zA-Z]{9}[0-9](?![0-9a-zA-Z-])$')
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
###############################################################################
|
|
22
|
+
# Public Functions Implementation
|
|
23
|
+
###############################################################################
|
|
24
|
+
def import_from_string(dotted_path: str) -> type:
|
|
25
|
+
"""
|
|
26
|
+
Import and return a Python class or module based on a dotted path.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
dotted_path (str): The dotted path to the Python class or module.
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
type: The imported Python class or module.
|
|
33
|
+
|
|
34
|
+
Raises:
|
|
35
|
+
ImportError: If the provided dotted path is invalid or if the class/module cannot be imported.
|
|
36
|
+
|
|
37
|
+
Example:
|
|
38
|
+
>>> import_from_string("module_name.ClassName")
|
|
39
|
+
<class 'module_name.ClassName'>
|
|
40
|
+
"""
|
|
41
|
+
try:
|
|
42
|
+
module_path, class_name = dotted_path.rsplit(".", 1)
|
|
43
|
+
except ValueError as error:
|
|
44
|
+
raise ImportError(f"{dotted_path} doesn't look like a module path.") from error
|
|
45
|
+
|
|
46
|
+
module = import_module(module_path)
|
|
47
|
+
try:
|
|
48
|
+
return getattr(module, class_name)
|
|
49
|
+
except AttributeError as error:
|
|
50
|
+
raise ImportError(f'Module "{module_path}" does not define a "{class_name}" class.') from error
|
|
51
|
+
|
|
52
|
+
def is_string_object(obj: Any) -> bool:
|
|
53
|
+
"""
|
|
54
|
+
Check if the provided object is a string object.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
obj (Any): The object to check.
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
bool: True if the object is a string, False otherwise.
|
|
61
|
+
|
|
62
|
+
Example:
|
|
63
|
+
>>> from everysk.core.string import is_string_object
|
|
64
|
+
>>> is_string_object('Hello, World!')
|
|
65
|
+
>>> True
|
|
66
|
+
|
|
67
|
+
>>> is_string_object(42)
|
|
68
|
+
>>> False
|
|
69
|
+
"""
|
|
70
|
+
return isinstance(obj, string_types)
|
|
71
|
+
|
|
72
|
+
def to_string(value: str) -> str:
|
|
73
|
+
"""
|
|
74
|
+
Convert a value to a string representation.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
value (str): The value to convert to a string.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
str: The string representation of the value.
|
|
81
|
+
|
|
82
|
+
Example:
|
|
83
|
+
Convert a value to a string:
|
|
84
|
+
>>> to_string(42)
|
|
85
|
+
'42'
|
|
86
|
+
"""
|
|
87
|
+
if is_string_object(value):
|
|
88
|
+
return ensure_str(value)
|
|
89
|
+
return text_type(value)
|
|
90
|
+
|
|
91
|
+
def normalize_string(value: str):
|
|
92
|
+
"""
|
|
93
|
+
Normalize a string by applying Unicode normalization (NFKD).
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
value (str): The string to normalize.
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
str: The normalized string.
|
|
100
|
+
|
|
101
|
+
Example:
|
|
102
|
+
>>> from everysk.core.string import normalize_string
|
|
103
|
+
>>> result = normalize_string("Café")
|
|
104
|
+
>>> print(result)
|
|
105
|
+
>>> "Cafe"
|
|
106
|
+
|
|
107
|
+
"""
|
|
108
|
+
value = normalize('NFKD', value)
|
|
109
|
+
return value
|
|
110
|
+
|
|
111
|
+
def normalize_string_to_search(value):
|
|
112
|
+
"""
|
|
113
|
+
Normalize a string for search purposes by lowercasing and applying Unicode normalization (NFKD).
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
value: The string to normalize.
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
str: The normalized and lowercase string suitable for searching.
|
|
120
|
+
"""
|
|
121
|
+
value = value.lower().strip()
|
|
122
|
+
value = to_string(value)
|
|
123
|
+
return normalize_string(value)
|
|
124
|
+
|
|
125
|
+
def is_isin_string_regex(isin: str) -> bool:
|
|
126
|
+
"""
|
|
127
|
+
Check if a provided string matches the ISIN (International Securities Identification Number) format using regex.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
isin (str): The string to check.
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
bool: True if the string matches the ISIN format, False otherwise.
|
|
134
|
+
|
|
135
|
+
Example:
|
|
136
|
+
>>> from everysk.core.string import is_isin_string_regex
|
|
137
|
+
>>> result = is_isin_string_regex("US0378331005")
|
|
138
|
+
>>> print(result)
|
|
139
|
+
>>> True
|
|
140
|
+
"""
|
|
141
|
+
if not isinstance(isin, string_types):
|
|
142
|
+
return False
|
|
143
|
+
return True if RE_ISIN.match(isin) else False
|
|
144
|
+
|
|
145
|
+
def pluralize(string: str) -> str:
|
|
146
|
+
"""
|
|
147
|
+
Transform the string into its pluralized version.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
string (str): The string that we want to pluralize.
|
|
151
|
+
|
|
152
|
+
Example:
|
|
153
|
+
>>> from.everysk.core.string import pluralize
|
|
154
|
+
>>> pluralize('study')
|
|
155
|
+
'studies'
|
|
156
|
+
|
|
157
|
+
>>> pluralize('class')
|
|
158
|
+
'classes'
|
|
159
|
+
|
|
160
|
+
>>> pluralize('tax')
|
|
161
|
+
'taxes'
|
|
162
|
+
|
|
163
|
+
>>> pluralize('system')
|
|
164
|
+
'systems'
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
string (str): The pluralized version of the string
|
|
168
|
+
"""
|
|
169
|
+
if string[-1] in ('s', 'x'):
|
|
170
|
+
string += 'es'
|
|
171
|
+
elif string[-1] in ('y'):
|
|
172
|
+
string = string[:-1] + 'ies'
|
|
173
|
+
else:
|
|
174
|
+
string += 's'
|
|
175
|
+
return string
|
|
176
|
+
|
|
177
|
+
def snake_case(string: str) -> str:
|
|
178
|
+
"""
|
|
179
|
+
Convert the current string into the snake case format.
|
|
180
|
+
|
|
181
|
+
Args:
|
|
182
|
+
string (str): The string for conversion
|
|
183
|
+
|
|
184
|
+
Example:
|
|
185
|
+
>>> from everysk.core.string import snake_case
|
|
186
|
+
>>> snake_case('CustomIndex')
|
|
187
|
+
'custom_index'
|
|
188
|
+
|
|
189
|
+
>>> snake_case('Security')
|
|
190
|
+
'security'
|
|
191
|
+
|
|
192
|
+
>>> snake_case('ClassOrObjectByTest')
|
|
193
|
+
'class_or_object_by_test'
|
|
194
|
+
|
|
195
|
+
Returns:
|
|
196
|
+
string (str): The string converted to to snake case format
|
|
197
|
+
"""
|
|
198
|
+
_snake_case = re.compile(r'(?<!^)(?=[A-Z])')
|
|
199
|
+
return _snake_case.sub('_', string).lower()
|
everysk/core/tests.py
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
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
|
+
# ruff: noqa: F401
|
|
11
|
+
|
|
12
|
+
## Remember to prefix all import with EveryskLib to avoid clash with other tests
|
|
13
|
+
|
|
14
|
+
## Cloud function Test Cases
|
|
15
|
+
try:
|
|
16
|
+
from everysk.core.cloud_function.tests import CloudFunctionTestCase as EveryskLibCloudFunctionTestCase
|
|
17
|
+
except ModuleNotFoundError as error:
|
|
18
|
+
# This will prevent running these tests if redis is not installed
|
|
19
|
+
if not error.args[0].startswith("No module named 'redis'"):
|
|
20
|
+
raise
|
|
21
|
+
|
|
22
|
+
## Compress Test Cases
|
|
23
|
+
from everysk.core._tests.compress import CompressGzipJsonTestCase as EveryskLibCompressGzipJsonTestCase
|
|
24
|
+
from everysk.core._tests.compress import CompressGzipPickleTestCase as EveryskLibCompressGzipPickleTestCase
|
|
25
|
+
from everysk.core._tests.compress import CompressTestCase as EveryskLibCompressTestCase
|
|
26
|
+
from everysk.core._tests.compress import CompressZlibJsonTestCase as EveryskLibCompressZlibJsonTestCase
|
|
27
|
+
from everysk.core._tests.compress import CompressZlibPickleTestCase as EveryskLibCompressZlibPickleTestCase
|
|
28
|
+
from everysk.core._tests.compress import FileHandlingTestCase as EveryskLibFileHandlingTestCase
|
|
29
|
+
|
|
30
|
+
## Config Test Cases
|
|
31
|
+
from everysk.core._tests.config import SettingsManagerTestCase as EveryskLibSettingsManagerTestCase
|
|
32
|
+
from everysk.core._tests.config import SettingsModulesTestCase as EveryskLibSettingsModulesTestCase
|
|
33
|
+
from everysk.core._tests.config import SettingsTestCase as EveryskLibSettingsTestCase
|
|
34
|
+
|
|
35
|
+
## Exceptions Test Cases
|
|
36
|
+
from everysk.core._tests.exceptions import BaseExceptionTestCase as EveryskLibBaseExceptionTestCase
|
|
37
|
+
from everysk.core._tests.exceptions import DefaultErrorTestCase as EveryskLibDefaultErrorTestCase
|
|
38
|
+
from everysk.core._tests.exceptions import FieldValueErrorTestCase as EveryskLibFieldValueErrorTestCase
|
|
39
|
+
from everysk.core._tests.exceptions import HandledExceptionTestCase as EveryskLibHandledExceptionTestCase
|
|
40
|
+
from everysk.core._tests.exceptions import HttpErrorTestCase as EveryskLibHttpErrorTestCase
|
|
41
|
+
from everysk.core._tests.exceptions import ReadonlyErrorTestCase as EveryskLibReadonlyErrorTestCase
|
|
42
|
+
from everysk.core._tests.exceptions import RequiredErrorTestCase as EveryskLibRequiredErrorTestCase
|
|
43
|
+
from everysk.core._tests.exceptions import SDKExceptionsTestCase as EveryskLibSDKExceptionsTestCase
|
|
44
|
+
from everysk.core._tests.exceptions import TestAPIError as EveryskLibTestAPIError
|
|
45
|
+
|
|
46
|
+
## Fields Test Cases
|
|
47
|
+
from everysk.core._tests.fields import BoolFieldTestCase as EveryskLibBoolFieldTestCase
|
|
48
|
+
from everysk.core._tests.fields import ChoiceFieldTestCase as EveryskLibChoiceFieldTestCase
|
|
49
|
+
from everysk.core._tests.fields import COD3770TestCase as EveryskLibCOD3770TestCase
|
|
50
|
+
from everysk.core._tests.fields import DateFieldTestCase as EveryskLibDateFieldTestCase
|
|
51
|
+
from everysk.core._tests.fields import DateTimeFieldTestCase as EveryskLibDateTimeFieldTestCase
|
|
52
|
+
from everysk.core._tests.fields import DictFieldTestCase as EveryskLibDictFieldTestCase
|
|
53
|
+
from everysk.core._tests.fields import EmailFieldTestCase as EveryskLibEmailFieldTestCase
|
|
54
|
+
from everysk.core._tests.fields import FieldTestCase as EveryskLibFieldTestCase
|
|
55
|
+
from everysk.core._tests.fields import FieldUndefinedTestCase as EveryskLibFieldUndefinedTestCase
|
|
56
|
+
from everysk.core._tests.fields import FloatFieldTestCase as EveryskLibFloatFieldTestCase
|
|
57
|
+
from everysk.core._tests.fields import IntFieldTestCase as EveryskLibIntFieldTestCase
|
|
58
|
+
from everysk.core._tests.fields import IteratorFieldTestCase as EveryskLibIteratorFieldTestCase
|
|
59
|
+
from everysk.core._tests.fields import ListFieldTestCase as EveryskLibListFieldTestCase
|
|
60
|
+
from everysk.core._tests.fields import ObjectInitPropertyTestCase as EveryskLibObjectInitPropertyTestCase
|
|
61
|
+
from everysk.core._tests.fields import SetFieldTestCase as EveryskLibSetFieldTestCase
|
|
62
|
+
from everysk.core._tests.fields import StrFieldTestCase as EveryskLibStrFieldTestCase
|
|
63
|
+
from everysk.core._tests.fields import TupleFieldTestCase as EveryskLibTupleFieldTestCase
|
|
64
|
+
from everysk.core._tests.fields import URLFieldTestCase as EveryskLibURLFieldTestCase
|
|
65
|
+
|
|
66
|
+
## Date, DateTime Test Cases
|
|
67
|
+
from everysk.core.datetime.tests.calendar import CalendarTestCase as EveryskLibCalendarTestCase
|
|
68
|
+
from everysk.core.datetime.tests.date import DateTestCase as EveryskLibDateTestCase
|
|
69
|
+
from everysk.core.datetime.tests.date_mixin import GetHolidaysTestCase as EveryskLibDateMixinGetHolidaysTestCase
|
|
70
|
+
from everysk.core.datetime.tests.datetime import DateTimeTestCase as EveryskLibDateTimeTestCase
|
|
71
|
+
|
|
72
|
+
## Firestore Test Cases
|
|
73
|
+
try:
|
|
74
|
+
from everysk.core._tests.firestore import (
|
|
75
|
+
BaseDocumentCachedConfigTestCase as EveryskLibBaseDocumentCachedConfigTestCase,
|
|
76
|
+
)
|
|
77
|
+
from everysk.core._tests.firestore import BaseDocumentConfigTestCase as EveryskLibBaseDocumentConfigTestCase
|
|
78
|
+
from everysk.core._tests.firestore import DocumentCachedTestCase as EveryskLibDocumentCachedTestCase
|
|
79
|
+
from everysk.core._tests.firestore import DocumentTestCase as EveryskLibDocumentTestCase
|
|
80
|
+
from everysk.core._tests.firestore import FirestoreClientTestCase as EveryskLibFirestoreClientTestCase
|
|
81
|
+
from everysk.core._tests.firestore import LoadsPaginatedTestCase as EveryskLibLoadsPaginatedTestCase
|
|
82
|
+
except ModuleNotFoundError as error:
|
|
83
|
+
# This will prevent running these tests if google-cloud-firestore is not installed
|
|
84
|
+
if not error.args[0].startswith("No module named 'google"):
|
|
85
|
+
raise
|
|
86
|
+
|
|
87
|
+
## Http Test Cases
|
|
88
|
+
try:
|
|
89
|
+
from everysk.core._tests.http import HttpConnectionConfigTestCase as EveryskLibHttpConnectionConfigTestCase
|
|
90
|
+
from everysk.core._tests.http import HttpConnectionTestCase as EveryskLibHttpConnectionTestCase
|
|
91
|
+
from everysk.core._tests.http import HttpDELETEConnectionTestCase as EveryskLibHttpDELETEConnectioNTestCase
|
|
92
|
+
from everysk.core._tests.http import HttpGETConnectionTestCase as EveryskLibHttpGETConnectionTestCase
|
|
93
|
+
from everysk.core._tests.http import HttpHEADConnectionTestCase as EveryskLibHttpHEADConnectionTestCase
|
|
94
|
+
from everysk.core._tests.http import HttpOPTIONSConnectionTestCase as EveryskLibHttpOPTIONSConnectionTestCase
|
|
95
|
+
from everysk.core._tests.http import HttpPATCHConnectionTestCase as EveryskLibHttpPATCHConnectionTestCase
|
|
96
|
+
from everysk.core._tests.http import (
|
|
97
|
+
HttpPOSTCompressedConnectionTestCase as EveryskLibHttpPOSTCompressedConnectionTestCase,
|
|
98
|
+
)
|
|
99
|
+
from everysk.core._tests.http import HttpPOSTConnectionTestCase as EveryskLibHttpPOSTConnectionTestCase
|
|
100
|
+
from everysk.core._tests.http import HttpPUTConnectionTestCase as EveryskLibHttpPUTCompressedConnectionTestCase
|
|
101
|
+
from everysk.core._tests.http import HttpSDKPOSTConnectionTestCase as EveryskLibHttpSDKPOSTConnectionTestCase
|
|
102
|
+
except ModuleNotFoundError as error:
|
|
103
|
+
# This will prevent running these tests if requests is not installed
|
|
104
|
+
if not error.args[0].startswith("No module named 'requests'"):
|
|
105
|
+
raise
|
|
106
|
+
|
|
107
|
+
## Lists Test Cases
|
|
108
|
+
from everysk.core._tests.lists import SlicesTestCase as EveryskLibSlicesTestCase
|
|
109
|
+
from everysk.core._tests.lists import SortListDictTestCase as EveryskLibSortListDictTestCase
|
|
110
|
+
from everysk.core._tests.lists import SplitInSlicesTestCase as EveryskLibSplitInSlicesTestCase
|
|
111
|
+
|
|
112
|
+
## Log Test Cases
|
|
113
|
+
from everysk.core._tests.log import LoggerExtraDataTestCase as EveryskLibLoggerExtraDataTestCase
|
|
114
|
+
from everysk.core._tests.log import LoggerFormatterTestCase as EveryskLibLoggerFormatterTestCase
|
|
115
|
+
from everysk.core._tests.log import LoggerJsonTestCase as EveryskLibLoggerJsonTestCase
|
|
116
|
+
from everysk.core._tests.log import LoggerManagerTestCase as EveryskLibLoggerManagerTestCase
|
|
117
|
+
from everysk.core._tests.log import LoggerMethodsTestCase as EveryskLibLoggerMethodsTestCase
|
|
118
|
+
from everysk.core._tests.log import LoggerStackLevelTestCase as EveryskLibLoggerStackLevelTestCase
|
|
119
|
+
from everysk.core._tests.log import LoggerStdoutTestCase as EveryskLibLoggerStdoutTestCase
|
|
120
|
+
from everysk.core._tests.log import LoggerTestCase as EveryskLibLoggerTestCase
|
|
121
|
+
from everysk.core._tests.log import LoggerTraceTestCase as EveryskLibLogTraceTestCase
|
|
122
|
+
|
|
123
|
+
try:
|
|
124
|
+
# We need requests to run this test
|
|
125
|
+
from everysk.core._tests.log import LoggerSlackTestCase as EveryskLibLoggerSlackTestCase
|
|
126
|
+
except ModuleNotFoundError as error:
|
|
127
|
+
# This will prevent running these tests if requests is not installed
|
|
128
|
+
if not error.args[0].startswith("No module named 'requests'"):
|
|
129
|
+
raise
|
|
130
|
+
|
|
131
|
+
## Number Test Cases
|
|
132
|
+
from everysk.core._tests.number import NumberTestCase as EveryskLibNumberTestCase
|
|
133
|
+
|
|
134
|
+
## Object Test Cases
|
|
135
|
+
from everysk.core._tests.object import AfterInitTestCase as EveryskLibAfterInitTestCase
|
|
136
|
+
from everysk.core._tests.object import BaseDictPropertyTestCase as EveryskLibBaseDictPropertyTestCase
|
|
137
|
+
from everysk.core._tests.object import BaseDictSuperTestCase as EveryskLibBaseDictSuperTestCase
|
|
138
|
+
from everysk.core._tests.object import BaseDictTestCase as EveryskLibBaseDictTestCase
|
|
139
|
+
from everysk.core._tests.object import BaseFieldTestCase as EveryskLibBaseFieldTestCase
|
|
140
|
+
from everysk.core._tests.object import BaseObjectTestCase as EveryskLibBaseObjectTestCase
|
|
141
|
+
from everysk.core._tests.object import BeforeInitTestCase as EveryskLibBeforeInitTestCase
|
|
142
|
+
from everysk.core._tests.object import ConfigHashTestCase as EveryskLibConfigHashTestCase
|
|
143
|
+
from everysk.core._tests.object import FrozenDictTestCase as EveryskLibFrozenDictTestCase
|
|
144
|
+
from everysk.core._tests.object import FrozenObjectTestCase as EveryskLibFrozenObjectTestCase
|
|
145
|
+
from everysk.core._tests.object import MetaClassAttributesTestCase as EveryskLibMetaClassAttributesTestCase
|
|
146
|
+
from everysk.core._tests.object import MetaClassConfigTestCase as EveryskLibMetaClassConfigTestCase
|
|
147
|
+
from everysk.core._tests.object import NpArrayTestCase as EveryskLibNpArrayTestCase
|
|
148
|
+
from everysk.core._tests.object import RequiredTestCase as EveryskLibRequiredTestCase
|
|
149
|
+
from everysk.core._tests.object import SilentTestCase as EveryskLibSilentTestCase
|
|
150
|
+
from everysk.core._tests.object import TypingCheckingTestCase as EveryskLibTypingCheckingTestCase
|
|
151
|
+
from everysk.core._tests.object import ValidateTestCase as EveryskLibValidateTestCase
|
|
152
|
+
|
|
153
|
+
## Redis Test Cases
|
|
154
|
+
try:
|
|
155
|
+
from everysk.core._tests.redis import CacheDecoratorTestCase as EveryskLibCacheDecoratorTestCase
|
|
156
|
+
from everysk.core._tests.redis import RedisCacheCompressedTestCase as EveryskLibRedisCacheCompressedTestCase
|
|
157
|
+
from everysk.core._tests.redis import RedisCacheGetSetTestCase as EveryskLibRedisCacheGetSetTestCase
|
|
158
|
+
from everysk.core._tests.redis import RedisCacheTestCase as EveryskLibRedisCacheTestCase
|
|
159
|
+
from everysk.core._tests.redis import RedisChannelTestCase as EveryskLibRedisChannelTestCase
|
|
160
|
+
from everysk.core._tests.redis import RedisClientTestCase as EveryskLibRedisClientTestCase
|
|
161
|
+
from everysk.core._tests.redis import RedisListTestCase as EveryskLibRedisListTestCase
|
|
162
|
+
from everysk.core._tests.redis import RedisLockTestCase as EveryskLibRedisLockTestCase
|
|
163
|
+
except ModuleNotFoundError as error:
|
|
164
|
+
# This will prevent running these tests if redis is not installed
|
|
165
|
+
if not error.args[0].startswith("No module named 'redis'"):
|
|
166
|
+
raise
|
|
167
|
+
|
|
168
|
+
## Retry Test Cases
|
|
169
|
+
from everysk.core._tests.retry import RetryTestCase as EveryskLibRetryTestCase
|
|
170
|
+
|
|
171
|
+
## Serialize Test Cases
|
|
172
|
+
from everysk.core._tests.serialize.test_json import SerializeJsonDumpsTestCase as EveryskLibSerializeJsonDumpsTestCase
|
|
173
|
+
from everysk.core._tests.serialize.test_json import SerializeJsonLoadsTestCase as EveryskLibSerializeJsonLoadsTestCase
|
|
174
|
+
from everysk.core._tests.serialize.test_pickle import (
|
|
175
|
+
SerializePickleDumpsTestCase as EveryskLibSerializePickleDumpsTestCase,
|
|
176
|
+
)
|
|
177
|
+
from everysk.core._tests.serialize.test_pickle import (
|
|
178
|
+
SerializePickleLoadsTestCase as EveryskLibSerializePickleLoadsTestCase,
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
try:
|
|
182
|
+
from everysk.core._tests.serialize.test_orjson import (
|
|
183
|
+
SerializeOrjsonDumpsTestCase as EveryskLibSerializeOrjsonDumpsTestCase,
|
|
184
|
+
)
|
|
185
|
+
from everysk.core._tests.serialize.test_orjson import (
|
|
186
|
+
SerializeOrjsonLoadsTestCase as EveryskLibSerializeOrjsonLoadsTestCase,
|
|
187
|
+
)
|
|
188
|
+
except ModuleNotFoundError as error:
|
|
189
|
+
# This will prevent running these tests if orjson is not installed
|
|
190
|
+
if not error.args[0].startswith("No module named 'orjson'"):
|
|
191
|
+
raise
|
|
192
|
+
|
|
193
|
+
## SFTP Test Cases
|
|
194
|
+
try:
|
|
195
|
+
from everysk.core._tests.sftp import KnownHostsTestCase as EveryskLibKnownHostsTestCase
|
|
196
|
+
from everysk.core._tests.sftp import SFTPTestCase as EveryskLibSFTPTestCase
|
|
197
|
+
except ModuleNotFoundError as error:
|
|
198
|
+
# This will prevent running these tests if Paramiko is not installed
|
|
199
|
+
if not error.args[0].startswith("No module named 'paramiko'"):
|
|
200
|
+
raise
|
|
201
|
+
|
|
202
|
+
## Signing Test Cases
|
|
203
|
+
from everysk.core._tests.signing import SignTestCase as EveryskLibSignTestCase
|
|
204
|
+
from everysk.core._tests.signing import UnsignTestCase as EveryskLibUnsignTestCase
|
|
205
|
+
|
|
206
|
+
## String Test Cases
|
|
207
|
+
from everysk.core._tests.string import StringTestCase as EveryskLibStringTestCase
|
|
208
|
+
|
|
209
|
+
## Slack Test Cases
|
|
210
|
+
try:
|
|
211
|
+
from everysk.core._tests.slack import SlackTestCase as EveryskLibSlackTestCase
|
|
212
|
+
except ModuleNotFoundError as error:
|
|
213
|
+
# This will prevent running these tests if requests is not installed
|
|
214
|
+
if not error.args[0].startswith("No module named 'requests'"):
|
|
215
|
+
raise
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
## Thread Test Cases
|
|
219
|
+
from everysk.core._tests.threads import ThreadPoolTestCase as EveryskLibThreadPoolTestCase
|
|
220
|
+
from everysk.core._tests.threads import ThreadTestCase as EveryskLibThreadTestCase
|
|
221
|
+
|
|
222
|
+
## Undefined Test Cases
|
|
223
|
+
from everysk.core._tests.undefined import UndefinedTestCase as EveryskLibUndefinedTestCase
|
|
224
|
+
|
|
225
|
+
## Unittest Test Cases
|
|
226
|
+
from everysk.core._tests.unittests import SDKUnittestTestCase as EveryskLibSDKUnittestTestCase
|
|
227
|
+
|
|
228
|
+
## Utils Test Cases
|
|
229
|
+
from everysk.core._tests.utils import BoolConverterTestCase as EveryskLibBoolConverterTestCase
|
|
230
|
+
from everysk.core._tests.utils import SearchKeyTestCase as EveryskLibSearchKeyTestCase
|
|
231
|
+
|
|
232
|
+
## Workers Test Cases
|
|
233
|
+
try:
|
|
234
|
+
from everysk.core._tests.workers import BaseGoogleTestCase as EveryskLibBaseGoogleTestCase
|
|
235
|
+
from everysk.core._tests.workers import TaskGoogleTestCase as EveryskLibTaskGoogleTestCase
|
|
236
|
+
from everysk.core._tests.workers import WorkerGoogleTestCase as EveryskLibWorkerGoogleTestCase
|
|
237
|
+
except ModuleNotFoundError as error:
|
|
238
|
+
# This will prevent running these tests if google-cloud-tasks is not installed
|
|
239
|
+
if not error.args[0].startswith("No module named 'google"):
|
|
240
|
+
raise
|
everysk/core/threads.py
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
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 concurrent.futures import ThreadPoolExecutor, Future, wait
|
|
11
|
+
from contextvars import Context, copy_context
|
|
12
|
+
from typing import Any
|
|
13
|
+
|
|
14
|
+
from everysk.core.log import Logger
|
|
15
|
+
from everysk.core.object import BaseObject
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
log = Logger(name='everysk-thread-error-log')
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
###############################################################################
|
|
22
|
+
# Thread Class Implementation
|
|
23
|
+
###############################################################################
|
|
24
|
+
class Thread(BaseObject):
|
|
25
|
+
## Private attributes
|
|
26
|
+
_pool: 'ThreadPool' = None
|
|
27
|
+
|
|
28
|
+
## Public attributes
|
|
29
|
+
args: tuple = None
|
|
30
|
+
kwargs: dict = None
|
|
31
|
+
target: callable = None
|
|
32
|
+
|
|
33
|
+
def __init__(self, target: callable, args: tuple = (), kwargs: dict = None):
|
|
34
|
+
"""
|
|
35
|
+
Use to execute the target inside a Thread and do parallel process.
|
|
36
|
+
This differs from the Python Threads for the capacity to use contextVars
|
|
37
|
+
and return the result.
|
|
38
|
+
AnOther ability
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
target (callable): The function that will be executed.
|
|
42
|
+
args (tuple, optional): The args attributes to be sent to the function. Defaults to ().
|
|
43
|
+
kwargs (dict, optional): The args attributes to be sent to the function. Defaults to None.
|
|
44
|
+
|
|
45
|
+
Example:
|
|
46
|
+
>>> from everysk.core.threads import Thread
|
|
47
|
+
>>> def sum(a, b):
|
|
48
|
+
... return a + b
|
|
49
|
+
...
|
|
50
|
+
>>> thread = Thread(target=sum, args=(1, 2))
|
|
51
|
+
>>> thread.start()
|
|
52
|
+
>>> thread.join()
|
|
53
|
+
3
|
|
54
|
+
>>> thread = Thread(target=sum, kwargs={'a': 1, 'b': 2})
|
|
55
|
+
>>> thread.start()
|
|
56
|
+
>>> thread.join()
|
|
57
|
+
3
|
|
58
|
+
"""
|
|
59
|
+
super().__init__(target=target, args=args, kwargs=kwargs)
|
|
60
|
+
if self.kwargs is None:
|
|
61
|
+
self.kwargs = {}
|
|
62
|
+
|
|
63
|
+
self._pool = ThreadPool(concurrency=1, silent=True)
|
|
64
|
+
|
|
65
|
+
def join(self) -> Any | None:
|
|
66
|
+
"""
|
|
67
|
+
Wait for the Thread to finish and returns the result.
|
|
68
|
+
"""
|
|
69
|
+
self._pool.wait()
|
|
70
|
+
return self._pool.results[0]
|
|
71
|
+
|
|
72
|
+
def run(self) -> Any:
|
|
73
|
+
"""
|
|
74
|
+
The method used to run the target inside the Thread.
|
|
75
|
+
"""
|
|
76
|
+
self._pool.add(target=self.target, args=self.args, kwargs=self.kwargs)
|
|
77
|
+
|
|
78
|
+
def start(self) -> None:
|
|
79
|
+
"""
|
|
80
|
+
The method used to start the Thread.
|
|
81
|
+
"""
|
|
82
|
+
self.run()
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
###############################################################################
|
|
86
|
+
# ThreadPool Class Implementation
|
|
87
|
+
###############################################################################
|
|
88
|
+
class ThreadPool(ThreadPoolExecutor):
|
|
89
|
+
context: Context = None
|
|
90
|
+
default_error_value: Any = Undefined
|
|
91
|
+
futures: list[Future] = None
|
|
92
|
+
results: list = None
|
|
93
|
+
silent: bool = True
|
|
94
|
+
|
|
95
|
+
def __init__(self, concurrency: int | None = None, silent: bool = True, default_error_value: Any = Undefined) -> None:
|
|
96
|
+
"""
|
|
97
|
+
ThreadPool is a queue to execute threads and control the concurrency.
|
|
98
|
+
If some error occur inside a Thread, we raise the exception or just log the exception.
|
|
99
|
+
If concurrency is not passed, then the default value is min(32, os.cpu_count() + 4).
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
concurrency (int | None, optional): The number of Threads that will be running simultaneously. Defaults to None.
|
|
103
|
+
silent (bool, optional): To log the error or raise. Defaults to True.
|
|
104
|
+
default_error (Any, optional): The default value to be stored as result if an error occur. Defaults to Undefined.
|
|
105
|
+
|
|
106
|
+
Example:
|
|
107
|
+
|
|
108
|
+
>>> from time import sleep
|
|
109
|
+
>>> from everysk.core.datetime import DateTime
|
|
110
|
+
>>> from everysk.core.threads import ThreadPool
|
|
111
|
+
|
|
112
|
+
>>> def sum(a: int, b: int) -> int:
|
|
113
|
+
... print(DateTime.now().strftime('%H:%M:%S'))
|
|
114
|
+
... sleep(1)
|
|
115
|
+
... return a + b
|
|
116
|
+
|
|
117
|
+
>>> pool = ThreadPool(6)
|
|
118
|
+
>>> for i in range(0, 6):
|
|
119
|
+
... pool.add(target=sum, args=(i, i))
|
|
120
|
+
>>> pool.wait()
|
|
121
|
+
19:24:22
|
|
122
|
+
19:24:22
|
|
123
|
+
19:24:22
|
|
124
|
+
19:24:22
|
|
125
|
+
19:24:22
|
|
126
|
+
19:24:22
|
|
127
|
+
>>> pool.results
|
|
128
|
+
[0, 2, 4, 6, 8, 10]
|
|
129
|
+
|
|
130
|
+
>>> pool = ThreadPool(2)
|
|
131
|
+
>>> for i in range(0, 6):
|
|
132
|
+
... pool.add(target=sum, args=(i,i))
|
|
133
|
+
>>> pool.wait()
|
|
134
|
+
19:25:09
|
|
135
|
+
19:25:09
|
|
136
|
+
19:25:10
|
|
137
|
+
19:25:10
|
|
138
|
+
19:25:11
|
|
139
|
+
19:25:11
|
|
140
|
+
>>> pool.results
|
|
141
|
+
[0, 2, 4, 6, 8, 10]
|
|
142
|
+
"""
|
|
143
|
+
self.context = copy_context()
|
|
144
|
+
self.futures = []
|
|
145
|
+
self.results = []
|
|
146
|
+
self.silent = silent
|
|
147
|
+
self.default_error_value = default_error_value
|
|
148
|
+
super().__init__(concurrency, initializer=self._set_child_context)
|
|
149
|
+
|
|
150
|
+
def _set_child_context(self) -> None:
|
|
151
|
+
""" Used to pass the context values to the child Threads. """
|
|
152
|
+
for var, value in self.context.items():
|
|
153
|
+
var.set(value)
|
|
154
|
+
|
|
155
|
+
def add(self, target: callable, args: tuple = (), kwargs: dict = None) -> None:
|
|
156
|
+
"""
|
|
157
|
+
Add the target to the queue to be processed later in a Thread.
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
target (callable): The function that will be executed in the Thread.
|
|
161
|
+
args (tuple, optional): The arguments that are needed to this function. Defaults to ().
|
|
162
|
+
kwargs (dict, optional): The keyword arguments that are needed to this function. Defaults to None.
|
|
163
|
+
"""
|
|
164
|
+
if kwargs is None:
|
|
165
|
+
kwargs = {}
|
|
166
|
+
|
|
167
|
+
future = self.submit(target, *args, **kwargs)
|
|
168
|
+
# We add these info on the future to be used later if some error occur
|
|
169
|
+
future.target = target
|
|
170
|
+
future.args = args
|
|
171
|
+
future.kwargs = kwargs
|
|
172
|
+
|
|
173
|
+
self.futures.append(future)
|
|
174
|
+
|
|
175
|
+
def wait(self) -> None:
|
|
176
|
+
""" This method is used to wait for all threads to complete and generate the results. """
|
|
177
|
+
wait(self.futures)
|
|
178
|
+
|
|
179
|
+
for future in self.futures:
|
|
180
|
+
try:
|
|
181
|
+
self.results.append(future.result())
|
|
182
|
+
except Exception as error: # pylint: disable=broad-exception-caught
|
|
183
|
+
if self.silent:
|
|
184
|
+
self.results.append(self.default_error_value)
|
|
185
|
+
log.error(
|
|
186
|
+
'Thread execution error -> target: %s',
|
|
187
|
+
future.target.__name__,
|
|
188
|
+
extra={
|
|
189
|
+
'labels': {
|
|
190
|
+
'args': future.args,
|
|
191
|
+
'kwargs': future.kwargs,
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
)
|
|
195
|
+
else:
|
|
196
|
+
raise error
|
|
197
|
+
|
|
198
|
+
# This is a Garbage Collector for the ThreadPool
|
|
199
|
+
self.shutdown()
|