everysk-lib 1.10.2__cp312-cp312-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. everysk/__init__.py +30 -0
  2. everysk/_version.py +683 -0
  3. everysk/api/__init__.py +61 -0
  4. everysk/api/api_requestor.py +167 -0
  5. everysk/api/api_resources/__init__.py +23 -0
  6. everysk/api/api_resources/api_resource.py +371 -0
  7. everysk/api/api_resources/calculation.py +779 -0
  8. everysk/api/api_resources/custom_index.py +42 -0
  9. everysk/api/api_resources/datastore.py +81 -0
  10. everysk/api/api_resources/file.py +42 -0
  11. everysk/api/api_resources/market_data.py +223 -0
  12. everysk/api/api_resources/parser.py +66 -0
  13. everysk/api/api_resources/portfolio.py +43 -0
  14. everysk/api/api_resources/private_security.py +42 -0
  15. everysk/api/api_resources/report.py +65 -0
  16. everysk/api/api_resources/report_template.py +39 -0
  17. everysk/api/api_resources/tests.py +115 -0
  18. everysk/api/api_resources/worker_execution.py +64 -0
  19. everysk/api/api_resources/workflow.py +65 -0
  20. everysk/api/api_resources/workflow_execution.py +93 -0
  21. everysk/api/api_resources/workspace.py +42 -0
  22. everysk/api/http_client.py +63 -0
  23. everysk/api/tests.py +32 -0
  24. everysk/api/utils.py +262 -0
  25. everysk/config.py +451 -0
  26. everysk/core/_tests/serialize/test_json.py +336 -0
  27. everysk/core/_tests/serialize/test_orjson.py +295 -0
  28. everysk/core/_tests/serialize/test_pickle.py +48 -0
  29. everysk/core/cloud_function/main.py +78 -0
  30. everysk/core/cloud_function/tests.py +86 -0
  31. everysk/core/compress.py +245 -0
  32. everysk/core/datetime/__init__.py +12 -0
  33. everysk/core/datetime/calendar.py +144 -0
  34. everysk/core/datetime/date.py +424 -0
  35. everysk/core/datetime/date_expression.py +299 -0
  36. everysk/core/datetime/date_mixin.py +1475 -0
  37. everysk/core/datetime/date_settings.py +30 -0
  38. everysk/core/datetime/datetime.py +713 -0
  39. everysk/core/exceptions.py +435 -0
  40. everysk/core/fields.py +1176 -0
  41. everysk/core/firestore.py +555 -0
  42. everysk/core/fixtures/_settings.py +29 -0
  43. everysk/core/fixtures/other/_settings.py +18 -0
  44. everysk/core/fixtures/user_agents.json +88 -0
  45. everysk/core/http.py +691 -0
  46. everysk/core/lists.py +92 -0
  47. everysk/core/log.py +709 -0
  48. everysk/core/number.py +37 -0
  49. everysk/core/object.py +1469 -0
  50. everysk/core/redis.py +1021 -0
  51. everysk/core/retry.py +51 -0
  52. everysk/core/serialize.py +674 -0
  53. everysk/core/sftp.py +414 -0
  54. everysk/core/signing.py +53 -0
  55. everysk/core/slack.py +127 -0
  56. everysk/core/string.py +199 -0
  57. everysk/core/tests.py +240 -0
  58. everysk/core/threads.py +199 -0
  59. everysk/core/undefined.py +70 -0
  60. everysk/core/unittests.py +73 -0
  61. everysk/core/workers.py +241 -0
  62. everysk/sdk/__init__.py +23 -0
  63. everysk/sdk/base.py +98 -0
  64. everysk/sdk/brutils/cnpj.py +391 -0
  65. everysk/sdk/brutils/cnpj_pd.py +129 -0
  66. everysk/sdk/engines/__init__.py +26 -0
  67. everysk/sdk/engines/cache.py +185 -0
  68. everysk/sdk/engines/compliance.py +37 -0
  69. everysk/sdk/engines/cryptography.py +69 -0
  70. everysk/sdk/engines/expression.cp312-win_amd64.pyd +0 -0
  71. everysk/sdk/engines/expression.pyi +55 -0
  72. everysk/sdk/engines/helpers.cp312-win_amd64.pyd +0 -0
  73. everysk/sdk/engines/helpers.pyi +26 -0
  74. everysk/sdk/engines/lock.py +120 -0
  75. everysk/sdk/engines/market_data.py +244 -0
  76. everysk/sdk/engines/settings.py +19 -0
  77. everysk/sdk/entities/__init__.py +23 -0
  78. everysk/sdk/entities/base.py +784 -0
  79. everysk/sdk/entities/base_list.py +131 -0
  80. everysk/sdk/entities/custom_index/base.py +209 -0
  81. everysk/sdk/entities/custom_index/settings.py +29 -0
  82. everysk/sdk/entities/datastore/base.py +160 -0
  83. everysk/sdk/entities/datastore/settings.py +17 -0
  84. everysk/sdk/entities/fields.py +375 -0
  85. everysk/sdk/entities/file/base.py +215 -0
  86. everysk/sdk/entities/file/settings.py +63 -0
  87. everysk/sdk/entities/portfolio/base.py +248 -0
  88. everysk/sdk/entities/portfolio/securities.py +241 -0
  89. everysk/sdk/entities/portfolio/security.py +580 -0
  90. everysk/sdk/entities/portfolio/settings.py +97 -0
  91. everysk/sdk/entities/private_security/base.py +226 -0
  92. everysk/sdk/entities/private_security/settings.py +17 -0
  93. everysk/sdk/entities/query.py +603 -0
  94. everysk/sdk/entities/report/base.py +214 -0
  95. everysk/sdk/entities/report/settings.py +23 -0
  96. everysk/sdk/entities/script.py +310 -0
  97. everysk/sdk/entities/secrets/base.py +128 -0
  98. everysk/sdk/entities/secrets/script.py +119 -0
  99. everysk/sdk/entities/secrets/settings.py +17 -0
  100. everysk/sdk/entities/settings.py +48 -0
  101. everysk/sdk/entities/tags.py +174 -0
  102. everysk/sdk/entities/worker_execution/base.py +307 -0
  103. everysk/sdk/entities/worker_execution/settings.py +63 -0
  104. everysk/sdk/entities/workflow_execution/base.py +113 -0
  105. everysk/sdk/entities/workflow_execution/settings.py +32 -0
  106. everysk/sdk/entities/workspace/base.py +99 -0
  107. everysk/sdk/entities/workspace/settings.py +27 -0
  108. everysk/sdk/settings.py +67 -0
  109. everysk/sdk/tests.py +105 -0
  110. everysk/sdk/worker_base.py +47 -0
  111. everysk/server/__init__.py +9 -0
  112. everysk/server/applications.py +63 -0
  113. everysk/server/endpoints.py +516 -0
  114. everysk/server/example_api.py +69 -0
  115. everysk/server/middlewares.py +80 -0
  116. everysk/server/requests.py +62 -0
  117. everysk/server/responses.py +119 -0
  118. everysk/server/routing.py +64 -0
  119. everysk/server/settings.py +36 -0
  120. everysk/server/tests.py +36 -0
  121. everysk/settings.py +98 -0
  122. everysk/sql/__init__.py +9 -0
  123. everysk/sql/connection.py +232 -0
  124. everysk/sql/model.py +376 -0
  125. everysk/sql/query.py +417 -0
  126. everysk/sql/row_factory.py +63 -0
  127. everysk/sql/settings.py +49 -0
  128. everysk/sql/utils.py +129 -0
  129. everysk/tests.py +23 -0
  130. everysk/utils.py +81 -0
  131. everysk/version.py +15 -0
  132. everysk_lib-1.10.2.dist-info/.gitignore +5 -0
  133. everysk_lib-1.10.2.dist-info/METADATA +326 -0
  134. everysk_lib-1.10.2.dist-info/RECORD +137 -0
  135. everysk_lib-1.10.2.dist-info/WHEEL +5 -0
  136. everysk_lib-1.10.2.dist-info/licenses/LICENSE.txt +9 -0
  137. everysk_lib-1.10.2.dist-info/top_level.txt +2 -0
@@ -0,0 +1,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})