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,214 @@
|
|
|
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 everysk.config import settings
|
|
11
|
+
from everysk.core.exceptions import SDKValueError
|
|
12
|
+
from everysk.core.fields import ListField, StrField, DictField
|
|
13
|
+
from everysk.sdk.entities.base import BaseEntity, ScriptMetaClass
|
|
14
|
+
from everysk.sdk.entities.fields import EntityNameField, EntityDescriptionField, EntityLinkUIDField, EntityWorkspaceField, EntityDateTimeField, EntityTagsField
|
|
15
|
+
from everysk.sdk.entities.query import Query
|
|
16
|
+
from everysk.sdk.entities.script import Script
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
###############################################################################
|
|
20
|
+
# Report Class Implementation
|
|
21
|
+
###############################################################################
|
|
22
|
+
class Report(BaseEntity, metaclass=ScriptMetaClass):
|
|
23
|
+
"""
|
|
24
|
+
This class represents a report entity object and provides methods to validate and manage the entity's data.
|
|
25
|
+
|
|
26
|
+
Attributes:
|
|
27
|
+
script (Script): The script object associated with the report.
|
|
28
|
+
id (StrField): The unique identifier of the report.
|
|
29
|
+
workspace (EntityWorkspaceField): The workspace of the report.
|
|
30
|
+
name (EntityNameField): The name of the report.
|
|
31
|
+
tags (EntityTagsField): The tags of the report.
|
|
32
|
+
description (EntityDescriptionField): The description of the report.
|
|
33
|
+
link_uid (EntityLinkUIDField): The link UID of the report.
|
|
34
|
+
date (EntityDateTimeField): The date associated with the report.
|
|
35
|
+
widgets (ListField): A list of widgets associated with the report.
|
|
36
|
+
url (StrField): The URL of the report.
|
|
37
|
+
authorization (StrField): The authorization string for accessing the report.
|
|
38
|
+
config_cascaded (DictField): A dictionary of cascaded configuration settings.
|
|
39
|
+
layout_content (DictField): A dictionary representing the layout content of the report.
|
|
40
|
+
|
|
41
|
+
version (StrField): The version of the report.
|
|
42
|
+
created_on (DateTimeField): The created on date of the report.
|
|
43
|
+
updated_on (DateTimeField): The updated on date of the report.
|
|
44
|
+
|
|
45
|
+
Example:
|
|
46
|
+
>>> from everysk.sdk.entities.report.base import Report
|
|
47
|
+
>>> report = Report()
|
|
48
|
+
>>> report.script = 'my_script'
|
|
49
|
+
>>> report.id = 'repo_12345678'
|
|
50
|
+
>>> report.name = 'My Report'
|
|
51
|
+
>>> report.tags = ['tag1', 'tag2']
|
|
52
|
+
>>> report.description = 'This is a sample report.'
|
|
53
|
+
>>> report.workspace = 'my_workspace'
|
|
54
|
+
>>> report.date = '20220101'
|
|
55
|
+
>>> report.widgets = [{'type': 'chart', 'data': {...}}, {'type': 'table', 'data': {...}}]
|
|
56
|
+
>>> report.url = '/sefdsf5s54sdfsksdfs5'
|
|
57
|
+
>>> report.authorization = 'private'
|
|
58
|
+
>>> report.data_hash = 'hash123'
|
|
59
|
+
>>> report.config_cascaded = {'setting1': 'value1', 'setting2': 'value2'}
|
|
60
|
+
>>> report.layout_content = {'section1': {...}, 'section2': {...}}
|
|
61
|
+
>>> report.create()
|
|
62
|
+
>>> print(report)
|
|
63
|
+
{
|
|
64
|
+
'id': 'repo_12345678',
|
|
65
|
+
'script': 'my_script',
|
|
66
|
+
'name': 'My Report',
|
|
67
|
+
'description': 'This is a sample report.',
|
|
68
|
+
'tags': ['tag1', 'tag2'],
|
|
69
|
+
'link_uid': None,
|
|
70
|
+
'workspace': 'my_workspace',
|
|
71
|
+
'date': '20220101',
|
|
72
|
+
'widgets': [{'type': 'chart', 'data': {...}}, {'type': 'table', 'data': {...}}],
|
|
73
|
+
'url': '/sefdsf5s54sdfsksdfs5',
|
|
74
|
+
'authorization': 'private',
|
|
75
|
+
'config_cascaded': {'setting1': 'value1', 'setting2': 'value2'},
|
|
76
|
+
'layout_content': {'section1': {...}, 'section2': {...}}
|
|
77
|
+
}
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
script: Script = None
|
|
81
|
+
_orderable_attributes = ListField(default=['date', 'created_on', 'updated_on', 'name'], readonly=True)
|
|
82
|
+
|
|
83
|
+
id = StrField(regex=settings.REPORT_ID_REGEX, max_size=settings.REPORT_ID_MAX_SIZE, required_lazy=True, empty_is_none=True)
|
|
84
|
+
|
|
85
|
+
name = EntityNameField()
|
|
86
|
+
description = EntityDescriptionField()
|
|
87
|
+
tags = EntityTagsField()
|
|
88
|
+
link_uid = EntityLinkUIDField()
|
|
89
|
+
workspace = EntityWorkspaceField()
|
|
90
|
+
date = EntityDateTimeField()
|
|
91
|
+
|
|
92
|
+
widgets = ListField()
|
|
93
|
+
url = StrField(required_lazy=True)
|
|
94
|
+
authorization = StrField(default=None, regex=settings.REPORT_AUTHORIZATION_REGEX, required_lazy=True)
|
|
95
|
+
config_cascaded = DictField(required_lazy=True)
|
|
96
|
+
layout_content = DictField(required_lazy=True)
|
|
97
|
+
|
|
98
|
+
def validate(self) -> bool:
|
|
99
|
+
"""
|
|
100
|
+
This method validates the entity object and raises an exception if it is not
|
|
101
|
+
valid. The validation is performed by calling the `validate` method of each field
|
|
102
|
+
of the entity.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
self (Self): The entity object to be validated.
|
|
106
|
+
|
|
107
|
+
Raises:
|
|
108
|
+
FieldValueError: If the entity object is not valid.
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
bool: True if the entity object is valid, False otherwise.
|
|
112
|
+
|
|
113
|
+
Example:
|
|
114
|
+
>>> entity = Entity()
|
|
115
|
+
>>> entity.validate()
|
|
116
|
+
True
|
|
117
|
+
"""
|
|
118
|
+
return self.get_response(self_obj=self)
|
|
119
|
+
|
|
120
|
+
@staticmethod
|
|
121
|
+
def get_id_prefix() -> str:
|
|
122
|
+
"""
|
|
123
|
+
Returns the prefix of the report id field value.
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
str: The prefix of the report id field value.
|
|
127
|
+
|
|
128
|
+
Example:
|
|
129
|
+
>>> from everysk.sdk.entities.report.base import Report
|
|
130
|
+
>>> Report.get_id_prefix()
|
|
131
|
+
'repo_'
|
|
132
|
+
|
|
133
|
+
Notes:
|
|
134
|
+
The prefix is typically used to distinguish report IDs from the other types of IDs
|
|
135
|
+
"""
|
|
136
|
+
return settings.REPORT_ID_PREFIX
|
|
137
|
+
|
|
138
|
+
def _check_query(self, query: Query) -> bool:
|
|
139
|
+
"""
|
|
140
|
+
Check the query object.
|
|
141
|
+
|
|
142
|
+
Args:
|
|
143
|
+
query (Query): The query object.
|
|
144
|
+
|
|
145
|
+
Returns:
|
|
146
|
+
Query: The query object.
|
|
147
|
+
"""
|
|
148
|
+
return True
|
|
149
|
+
|
|
150
|
+
def _check_entity_to_query(self) -> bool:
|
|
151
|
+
"""
|
|
152
|
+
Check the entity object to query.
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
bool: True if the entity object is valid.
|
|
156
|
+
"""
|
|
157
|
+
super()._check_entity_to_query()
|
|
158
|
+
if self.url and (self.name or self.tags or self.link_uid):
|
|
159
|
+
raise SDKValueError("Can't filter by URL and Name, Tags or Link UID at the same time")
|
|
160
|
+
|
|
161
|
+
return True
|
|
162
|
+
|
|
163
|
+
def _mount_query(self, query: Query) -> Query:
|
|
164
|
+
"""
|
|
165
|
+
Mount the query object.
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
query (Query): The query object.
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
Query: The query object.
|
|
172
|
+
"""
|
|
173
|
+
query = super()._mount_query(query)
|
|
174
|
+
if self.url is not None:
|
|
175
|
+
query = query.where('url', self.url)
|
|
176
|
+
|
|
177
|
+
return query
|
|
178
|
+
|
|
179
|
+
def to_dict(self, add_class_path: bool = False, recursion: bool = False) -> dict:
|
|
180
|
+
"""
|
|
181
|
+
Convert the entity to a JSON-serializable dictionary.
|
|
182
|
+
This method converts the entity object into a dictionary that can be easily
|
|
183
|
+
serialized to JSON.
|
|
184
|
+
|
|
185
|
+
Args:
|
|
186
|
+
self (Self): The entity instance to convert.
|
|
187
|
+
with_internals (bool, optional): Whether to include internal parameters. Defaults to True.
|
|
188
|
+
recursion (bool, optional): Whether to include nested entities. Defaults to False.
|
|
189
|
+
|
|
190
|
+
Returns:
|
|
191
|
+
dict: A dictionary representation of the entity.
|
|
192
|
+
|
|
193
|
+
Raises:
|
|
194
|
+
NotImplementedError: This method should be implemented in subclasses.
|
|
195
|
+
"""
|
|
196
|
+
dct: dict = super().to_dict(add_class_path=add_class_path, recursion=recursion)
|
|
197
|
+
|
|
198
|
+
if add_class_path is False:
|
|
199
|
+
relative_url: None | str = None
|
|
200
|
+
absolute_url: None | str = None
|
|
201
|
+
if self.url is not None:
|
|
202
|
+
relative_url = f'{settings.REPORT_URL_PATH}{self.url}'
|
|
203
|
+
absolute_url = f'{settings.EVERYSK_APP_URL}{relative_url}'
|
|
204
|
+
|
|
205
|
+
dct['url'] = absolute_url
|
|
206
|
+
dct['absolute_url'] = absolute_url
|
|
207
|
+
dct['relative_url'] = relative_url
|
|
208
|
+
|
|
209
|
+
dct['authorization'] = dct['authorization'].upper() if dct['authorization'] else None
|
|
210
|
+
|
|
211
|
+
dct.pop('config_cascaded', None)
|
|
212
|
+
dct.pop('layout_content', None)
|
|
213
|
+
|
|
214
|
+
return dct
|
|
@@ -0,0 +1,23 @@
|
|
|
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 everysk.core.fields import StrField, IntField, RegexField
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
REPORT_ID_REGEX = RegexField(default=r'^repo_[a-zA-Z0-9]', readonly=True)
|
|
14
|
+
REPORT_ID_PREFIX = StrField(default='repo_', readonly=True)
|
|
15
|
+
|
|
16
|
+
REPORT_ID_MAX_SIZE = IntField(default=30, readonly=True)
|
|
17
|
+
REPORT_LEVEL_MAX_LENGTH = IntField(default=32, readonly=True)
|
|
18
|
+
|
|
19
|
+
REPORT_AUTHORIZATION_PUBLIC = StrField(default='public', readonly=True)
|
|
20
|
+
REPORT_AUTHORIZATION_PRIVATE = StrField(default='private', readonly=True)
|
|
21
|
+
REPORT_AUTHORIZATION_REGEX = RegexField(default=r'public|private', readonly=True)
|
|
22
|
+
|
|
23
|
+
REPORT_URL_PATH = StrField(default='/report', readonly=True)
|
|
@@ -0,0 +1,310 @@
|
|
|
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 Any, Callable, TypedDict
|
|
11
|
+
from inspect import isclass
|
|
12
|
+
|
|
13
|
+
from everysk.config import settings
|
|
14
|
+
from everysk.core.exceptions import FieldValueError, InvalidArgumentError
|
|
15
|
+
from everysk.core.object import BaseDict, BaseDictConfig
|
|
16
|
+
from everysk.core.string import import_from_string
|
|
17
|
+
from everysk.sdk.base import BaseSDK
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
###############################################################################
|
|
21
|
+
# StorageSettings Class Implementation
|
|
22
|
+
###############################################################################
|
|
23
|
+
class StorageSettings(TypedDict):
|
|
24
|
+
storage_mode: str
|
|
25
|
+
consistency_check: bool
|
|
26
|
+
skip_validation: bool
|
|
27
|
+
create_fallback: bool
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
###############################################################################
|
|
31
|
+
# Script Class Implementation
|
|
32
|
+
###############################################################################
|
|
33
|
+
class Script(BaseDict, BaseSDK):
|
|
34
|
+
"""
|
|
35
|
+
A base class for scripted queries.
|
|
36
|
+
This class provides a base implementation for scripted queries.
|
|
37
|
+
|
|
38
|
+
Attributes:
|
|
39
|
+
- _klass (callable): The class to instantiate when fetching an entity.
|
|
40
|
+
|
|
41
|
+
Example:
|
|
42
|
+
To fetch an entity:
|
|
43
|
+
>>> script = Script(klass=MyEntity)
|
|
44
|
+
>>> entity = script.fetch(user_input, variant, workspace)
|
|
45
|
+
"""
|
|
46
|
+
class Config(BaseDictConfig):
|
|
47
|
+
exclude_keys: frozenset[str] = frozenset(['_is_frozen', '_silent', '_errors', '_orderable_attributes'])
|
|
48
|
+
|
|
49
|
+
_klass: Callable = None
|
|
50
|
+
_config: Config = None
|
|
51
|
+
|
|
52
|
+
def __init__(self, _klass: Callable) -> None:
|
|
53
|
+
super().__init__(_klass=None)
|
|
54
|
+
|
|
55
|
+
if _klass is not None and not isclass(_klass):
|
|
56
|
+
try:
|
|
57
|
+
_klass = import_from_string(settings.EVERYSK_SDK_ENTITIES_MODULES_PATH[_klass])
|
|
58
|
+
except KeyError:
|
|
59
|
+
raise FieldValueError(f"The _klass value '{_klass}' must be a class or a string with the class name.") from KeyError
|
|
60
|
+
|
|
61
|
+
self._klass = _klass
|
|
62
|
+
|
|
63
|
+
def _process__klass(self, value: Any) -> Any:
|
|
64
|
+
"""
|
|
65
|
+
This method is used to process the '_klass' attribute.
|
|
66
|
+
"""
|
|
67
|
+
return value.__name__
|
|
68
|
+
|
|
69
|
+
def _process_entity_output(self, user_input: Any) -> Any:
|
|
70
|
+
"""
|
|
71
|
+
Processes the user input and returns an instance of the class or the input itself.
|
|
72
|
+
|
|
73
|
+
If the `user_input` is a dictionary or an instance of `BaseDict`, it will be passed as keyword arguments
|
|
74
|
+
to the class constructor (`self._klass`) and an instance of that class will be returned. Otherwise,
|
|
75
|
+
the `user_input` is returned as-is.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
user_input (Any): The input data to be processed. This can be a dictionary, an instance of `BaseDict`,
|
|
79
|
+
or any other type.
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
Any: An instance of the class if `user_input` is a dictionary or `BaseDict`; otherwise, the `user_input`
|
|
83
|
+
itself is returned.
|
|
84
|
+
"""
|
|
85
|
+
return self._klass(**user_input) if isinstance(user_input, (dict, BaseDict)) else user_input # pylint: disable=not-callable
|
|
86
|
+
|
|
87
|
+
def inner_fetch(self, user_input: Any, variant: str, workspace: str = Undefined) -> Any:
|
|
88
|
+
"""
|
|
89
|
+
Makes a call to the client to fetch an entity based on user input, variant, and workspace.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
user_input (Any): The input provided by the user, which can be used for filtering or as a direct entity ID.
|
|
93
|
+
variant (str): The type of scripted query to execute. Determines how the method processes the user input and constructs the query. Supported variants include 'previousWorkers', 'tagLatest', any string starting with 'select', and potentially others.
|
|
94
|
+
workspace (str): The workspace context for the query. Used for scoping and verifying entity retrieval.
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
Any: Depending on the variant and user input, the method might return an entity, or None.
|
|
98
|
+
|
|
99
|
+
"""
|
|
100
|
+
response = self.get_response(self_obj=self, params={'user_input': user_input, 'variant': variant, 'workspace': workspace})
|
|
101
|
+
|
|
102
|
+
return self._process_entity_output(response)
|
|
103
|
+
|
|
104
|
+
def fetch(self, user_input: Any, variant: str, workspace: str = Undefined) -> Any:
|
|
105
|
+
"""
|
|
106
|
+
Fetches an entity based on user input, variant, and workspace.
|
|
107
|
+
|
|
108
|
+
This method provides a way to construct and execute different types of queries
|
|
109
|
+
based on the specified variant. It's designed to handle a variety of scenarios
|
|
110
|
+
and return the desired entity or entities based on the input parameters.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
- user_input (Any): The input provided by the user, which can be used for filtering
|
|
114
|
+
or as a direct entity ID.
|
|
115
|
+
- variant (str): The type of scripted query to execute. Determines how the method
|
|
116
|
+
processes the user input and constructs the query. Supported variants include
|
|
117
|
+
'previousWorkers', 'tagLatest', any string starting with 'select', and potentially
|
|
118
|
+
others.
|
|
119
|
+
- workspace (str): The workspace context for the query. Used for scoping and
|
|
120
|
+
verifying entity retrieval.
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
- Any: Depending on the variant and user input, the method might return an entity,
|
|
124
|
+
or None.
|
|
125
|
+
|
|
126
|
+
Raises:
|
|
127
|
+
- ValueError: If there's an attempted cross-workspace operation or other variant-specific
|
|
128
|
+
error conditions are met.
|
|
129
|
+
|
|
130
|
+
Note:
|
|
131
|
+
The method behavior can vary greatly depending on the `variant` parameter, and it's
|
|
132
|
+
important to ensure that the variant aligns with the expected user input structure.
|
|
133
|
+
|
|
134
|
+
"""
|
|
135
|
+
if not user_input:
|
|
136
|
+
return None
|
|
137
|
+
|
|
138
|
+
if variant == 'previousWorkers' and isinstance(user_input, (dict, BaseDict, self._klass)) and (user_input.get('is_transient') or user_input.get('id') is None):
|
|
139
|
+
return self._process_entity_output(user_input)
|
|
140
|
+
|
|
141
|
+
entity: Any = self.inner_fetch(user_input, variant, workspace)
|
|
142
|
+
|
|
143
|
+
return entity
|
|
144
|
+
|
|
145
|
+
def inner_fetch_list(self, user_input: Any, variant: str, workspace: str = Undefined) -> list:
|
|
146
|
+
"""
|
|
147
|
+
Fetches a list of entities based on user input, variant, and workspace.
|
|
148
|
+
|
|
149
|
+
This method makes a call to the client to perform the necessary query actions.
|
|
150
|
+
|
|
151
|
+
Args:
|
|
152
|
+
user_input (Any): The input provided by the user, which can be used for filtering or as a direct entity ID.
|
|
153
|
+
variant (str): The type of scripted query to execute.
|
|
154
|
+
workspace (str): The workspace context for the query.
|
|
155
|
+
|
|
156
|
+
Returns:
|
|
157
|
+
list: The list of entities retrieved based on the input parameters.
|
|
158
|
+
|
|
159
|
+
"""
|
|
160
|
+
return self.get_response(self_obj=self, params={'user_input': user_input, 'variant': variant, 'workspace': workspace})
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def fetch_list(self, user_input: Any, variant: str, workspace: str = Undefined) -> list:
|
|
164
|
+
"""
|
|
165
|
+
Fetches an entity based on user input, variant, and workspace.
|
|
166
|
+
|
|
167
|
+
This method provides a way to construct and execute different types of queries
|
|
168
|
+
based on the specified variant. It's designed to handle a variety of scenarios
|
|
169
|
+
and return the desired entity or entities based on the input parameters.
|
|
170
|
+
|
|
171
|
+
Args:
|
|
172
|
+
user_input (Any): The input provided by the user, which can be used for filtering or as a direct entity ID.
|
|
173
|
+
variant (str): The type of scripted query to execute. Determines how the method processes the user input and constructs the query. Supported variants include 'previousWorkers', 'tagLatest', any string starting with 'select', and potentially others.
|
|
174
|
+
workspace (str): The workspace context for the query. Used for scoping and verifying entity retrieval.
|
|
175
|
+
|
|
176
|
+
Returns:
|
|
177
|
+
list: The method will return a list of entities or an empty list.
|
|
178
|
+
|
|
179
|
+
Raises:
|
|
180
|
+
ValueError: If there's an attempted cross-workspace operation or other variant-specific error conditions are met.
|
|
181
|
+
|
|
182
|
+
Note:
|
|
183
|
+
The method behavior can vary greatly depending on the `variant` parameter, and it's important to ensure that the variant aligns with the expected user input structure.
|
|
184
|
+
|
|
185
|
+
"""
|
|
186
|
+
if not user_input:
|
|
187
|
+
return []
|
|
188
|
+
|
|
189
|
+
entity_list: list = self.inner_fetch_list(user_input, variant, workspace)
|
|
190
|
+
|
|
191
|
+
return [self._klass(**item) if item is not None else item for item in entity_list] # pylint: disable=not-callable
|
|
192
|
+
|
|
193
|
+
def inner_fetch_multi(self, user_input_list: list[Any], variant_list: list[str], workspace_list: list[str] = Undefined) -> list:
|
|
194
|
+
"""
|
|
195
|
+
Fetches a list of entities based on user inputs, query variants, and workspace contexts.
|
|
196
|
+
|
|
197
|
+
This method sends a request to the client to execute the necessary query actions,
|
|
198
|
+
dynamically constructed based on the provided parameters.
|
|
199
|
+
|
|
200
|
+
Args:
|
|
201
|
+
user_input_list (list[Any]): A list of inputs provided by the user.
|
|
202
|
+
variant_list (list[str]): A list of query variants, each specifying the type of query to execute.
|
|
203
|
+
workspace_list (list[str], optional): A list of workspace contexts, used for scoping and validating
|
|
204
|
+
entity retrieval. Defaults to `Undefined`.
|
|
205
|
+
|
|
206
|
+
Returns:
|
|
207
|
+
list: A list of entities retrieved based on the provided parameters. Returns an empty list
|
|
208
|
+
if no entities match the query.
|
|
209
|
+
"""
|
|
210
|
+
return self.get_response(self_obj=self, params={'user_input_list': user_input_list, 'variant_list': variant_list, 'workspace_list': workspace_list})
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def fetch_multi(self, user_input_list: list[Any], variant_list: list[str], workspace_list: list[str] = Undefined) -> list:
|
|
214
|
+
"""
|
|
215
|
+
Fetches entities based on user inputs, query variants, and workspace contexts.
|
|
216
|
+
|
|
217
|
+
This method provides a higher-level interface for constructing and executing different
|
|
218
|
+
types of queries, delegating the core functionality to `inner_fetch_multi`.
|
|
219
|
+
|
|
220
|
+
Args:
|
|
221
|
+
user_input_list (list[Any]): A list of inputs provided by the user.
|
|
222
|
+
variant_list (list[str]): A list of query variants, each specifying the type of query to execute.
|
|
223
|
+
workspace_list (list[str], optional): A list of workspace contexts, used for scoping and validating
|
|
224
|
+
entity retrieval. Defaults to `Undefined`.
|
|
225
|
+
|
|
226
|
+
Returns:
|
|
227
|
+
list: A list of entities processed and instantiated using the class constructor (`self._klass`).
|
|
228
|
+
Returns an empty list if no entities match the query.
|
|
229
|
+
"""
|
|
230
|
+
if not user_input_list:
|
|
231
|
+
return []
|
|
232
|
+
|
|
233
|
+
entity_list: list = self.inner_fetch_multi(user_input_list, variant_list, workspace_list)
|
|
234
|
+
|
|
235
|
+
return [self._klass(**item) for item in entity_list] # pylint: disable=not-callable
|
|
236
|
+
|
|
237
|
+
def persist(self, entity: Any, persist: str, consistency_check: bool = False) -> Any:
|
|
238
|
+
"""
|
|
239
|
+
This method provides a way to persist an entity based on the specified persist type.
|
|
240
|
+
|
|
241
|
+
Args:
|
|
242
|
+
- entity (Any): The entity to persist.
|
|
243
|
+
- persist (str): The type of persist to execute. Determines how the method
|
|
244
|
+
persists the entity. Supported persists include 'insert', 'update', and 'delete'.
|
|
245
|
+
- consistency_check (bool): A flag to enable consistency checks before persisting.
|
|
246
|
+
|
|
247
|
+
Returns:
|
|
248
|
+
- Any: Depending on the persist type, the method might return an entity.
|
|
249
|
+
|
|
250
|
+
"""
|
|
251
|
+
response = self.get_response(self_obj=self, params={'entity': entity, 'persist': persist, 'consistency_check': consistency_check})
|
|
252
|
+
|
|
253
|
+
if isinstance(response, dict):
|
|
254
|
+
response = self._klass(**response) # pylint: disable=not-callable
|
|
255
|
+
|
|
256
|
+
return response
|
|
257
|
+
|
|
258
|
+
def inner_storage(self, entity: Any, storage_settings: StorageSettings) -> Any:
|
|
259
|
+
"""
|
|
260
|
+
Handles the storage actions for a given entity using specified storage settings.
|
|
261
|
+
|
|
262
|
+
This method makes a call to the client to perform the necessary storage actions.
|
|
263
|
+
|
|
264
|
+
Args:
|
|
265
|
+
entity (Any): The entity to be stored.
|
|
266
|
+
storage_settings (StorageSettings): The settings and configurations for storage.
|
|
267
|
+
|
|
268
|
+
Returns:
|
|
269
|
+
Any: The response from the client after performing the storage actions.
|
|
270
|
+
|
|
271
|
+
"""
|
|
272
|
+
response = self.get_response(self_obj=self, params={'entity': entity, 'storage_settings': storage_settings})
|
|
273
|
+
|
|
274
|
+
return self._process_entity_output(response)
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def storage(self, entity: Any, storage_settings: StorageSettings) -> Any:
|
|
278
|
+
"""
|
|
279
|
+
Stores an entity based on the specified storage settings.
|
|
280
|
+
|
|
281
|
+
This method determines the appropriate storage actions for an entity, including handling
|
|
282
|
+
different storage modes, performing consistency checks, and optionally skipping validation.
|
|
283
|
+
|
|
284
|
+
Args:
|
|
285
|
+
entity (Any): The entity to be stored.
|
|
286
|
+
storage_settings (StorageSettings): A configuration object containing:
|
|
287
|
+
- storage_mode (str): The storage mode to use. Supported modes include 'transient', 'create', and 'update'.
|
|
288
|
+
- consistency_check (bool): A flag indicating whether to perform a consistency check.
|
|
289
|
+
- validate (bool): A flag indicating whether to validate the entity parameters or not.
|
|
290
|
+
- create_fallback (bool): A flag indicating whether to create an entity if it does not exist.
|
|
291
|
+
|
|
292
|
+
Returns:
|
|
293
|
+
Any: Depending on the storage mode, the method might return the stored entity or a list of entities.
|
|
294
|
+
|
|
295
|
+
Raises:
|
|
296
|
+
InvalidArgumentError: If the entity is empty.
|
|
297
|
+
|
|
298
|
+
"""
|
|
299
|
+
if not entity:
|
|
300
|
+
raise InvalidArgumentError('Entity should not be empty.')
|
|
301
|
+
|
|
302
|
+
if storage_settings['storage_mode'] == 'transient':
|
|
303
|
+
entity.is_transient = True
|
|
304
|
+
|
|
305
|
+
if not storage_settings['validate']:
|
|
306
|
+
return self._process_entity_output(entity)
|
|
307
|
+
|
|
308
|
+
entity: Any = self.inner_storage(entity, storage_settings)
|
|
309
|
+
|
|
310
|
+
return entity
|
|
@@ -0,0 +1,128 @@
|
|
|
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
|
|
12
|
+
|
|
13
|
+
from everysk.config import settings
|
|
14
|
+
from everysk.core.exceptions import FieldValueError
|
|
15
|
+
from everysk.core.fields import DictField, ListField, StrField
|
|
16
|
+
from everysk.core.object import BaseDict
|
|
17
|
+
from everysk.sdk.entities.base import BaseEntity
|
|
18
|
+
from everysk.sdk.entities.fields import EntityDescriptionField, EntityNameField
|
|
19
|
+
from everysk.sdk.entities.secrets.script import SecretsScript, SecretsScriptMetaClass
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
###############################################################################
|
|
23
|
+
# Secrets Class Implementation
|
|
24
|
+
###############################################################################
|
|
25
|
+
class Secrets(BaseEntity, metaclass=SecretsScriptMetaClass):
|
|
26
|
+
script: SecretsScript = None
|
|
27
|
+
_orderable_attributes = ListField(default=['created_on', 'updated_on', 'name'], readonly=True)
|
|
28
|
+
|
|
29
|
+
id = StrField(regex=settings.SECRETS_ID_REGEX, required_lazy=True, empty_is_none=True)
|
|
30
|
+
|
|
31
|
+
name = EntityNameField()
|
|
32
|
+
description = EntityDescriptionField()
|
|
33
|
+
data = DictField(required_lazy=True, empty_is_none=True)
|
|
34
|
+
|
|
35
|
+
def to_dict(self, add_class_path: bool = False, recursion: bool = False) -> dict:
|
|
36
|
+
"""
|
|
37
|
+
Convert the entity to a dictionary.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
add_class_path (bool): If True, include the class path in the dictionary. Defaults to False.
|
|
41
|
+
recursion (bool): If True, recursively convert nested entities to dictionaries. Defaults to False.
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
dict: The entity as a dictionary.
|
|
45
|
+
"""
|
|
46
|
+
dct = super().to_dict(add_class_path, recursion)
|
|
47
|
+
|
|
48
|
+
if add_class_path is False and self.data and isinstance(self.data, BaseDict):
|
|
49
|
+
dct['data'] = self.data.to_dict()
|
|
50
|
+
|
|
51
|
+
return dct
|
|
52
|
+
|
|
53
|
+
@staticmethod
|
|
54
|
+
def get_id_prefix() -> str:
|
|
55
|
+
"""Get the ID prefix for the Secrets entity."""
|
|
56
|
+
return settings.SECRETS_ID_PREFIX
|
|
57
|
+
|
|
58
|
+
def _validate_data(self) -> None:
|
|
59
|
+
"""Validates the data field."""
|
|
60
|
+
if not self.data:
|
|
61
|
+
raise FieldValueError('data is required')
|
|
62
|
+
|
|
63
|
+
if not isinstance(self.data, dict):
|
|
64
|
+
raise FieldValueError('data must be a dictionary of version to Secret')
|
|
65
|
+
|
|
66
|
+
def validate(self) -> bool:
|
|
67
|
+
"""
|
|
68
|
+
Validate the entity properties.
|
|
69
|
+
|
|
70
|
+
Raises:
|
|
71
|
+
FieldValueError: If the entity properties are invalid.
|
|
72
|
+
RequiredFieldError: If a required field is missing.
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
bool: True if the entity properties are valid, False otherwise.
|
|
76
|
+
|
|
77
|
+
Example usage:
|
|
78
|
+
>>> entity = Secrets()
|
|
79
|
+
>>> entity.validate()
|
|
80
|
+
Traceback (most recent call last):
|
|
81
|
+
...
|
|
82
|
+
everysk.sdk.exceptions.RequiredFieldError: The field 'name' is required.
|
|
83
|
+
"""
|
|
84
|
+
super().validate()
|
|
85
|
+
self._validate_data()
|
|
86
|
+
return True
|
|
87
|
+
|
|
88
|
+
@classmethod
|
|
89
|
+
def _split_path(cls, path: str) -> tuple[str, list[str]]:
|
|
90
|
+
"""
|
|
91
|
+
Split a path into id and keys.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
path (str): The path to split.
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
tuple[str, list[str]]: The id and keys.
|
|
98
|
+
|
|
99
|
+
Raises:
|
|
100
|
+
ValueError: If the path is invalid.
|
|
101
|
+
"""
|
|
102
|
+
if not path or not isinstance(path, str) or '.' not in path:
|
|
103
|
+
raise ValueError('Invalid path format. Expected format: "<secret_id>.<key1>.<key2>..."')
|
|
104
|
+
|
|
105
|
+
values: list[str] = path.split('.')
|
|
106
|
+
id, keys = values[0], values[1:]
|
|
107
|
+
|
|
108
|
+
if cls.validate_id(id) is False:
|
|
109
|
+
raise ValueError(f'Invalid id format: {id}')
|
|
110
|
+
|
|
111
|
+
return id, keys
|
|
112
|
+
|
|
113
|
+
@classmethod
|
|
114
|
+
def value_from_path(cls, path: str) -> Any:
|
|
115
|
+
"""
|
|
116
|
+
Retrieve a value from a given path.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
path (str): The path to retrieve the value from.
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
Any | None: The value retrieved from the path or None if the path is empty.
|
|
123
|
+
"""
|
|
124
|
+
if not path:
|
|
125
|
+
return None
|
|
126
|
+
|
|
127
|
+
_, _ = cls._split_path(path)
|
|
128
|
+
return cls.get_response(params={'path': path})
|