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,119 @@
1
+ ###############################################################################
2
+ #
3
+ # (C) Copyright 2025 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 base64
11
+ from collections.abc import Callable
12
+ from inspect import isclass
13
+ from typing import Any
14
+
15
+ import six
16
+
17
+ from everysk.config import settings
18
+ from everysk.core.exceptions import FieldValueError, WorkerError
19
+ from everysk.core.object import BaseDict
20
+ from everysk.core.string import import_from_string
21
+ from everysk.sdk.base import BaseSDK
22
+ from everysk.sdk.entities import File
23
+ from everysk.sdk.entities.base import QueryMetaClass
24
+
25
+ ###############################################################################
26
+ # Class Implementation
27
+ ###############################################################################
28
+
29
+
30
+ class SecretsScript(BaseDict, BaseSDK):
31
+ _klass: Callable = None
32
+
33
+ def __init__(self, _klass: Callable) -> None:
34
+ super().__init__(_klass=None)
35
+
36
+ if _klass is not None and not isclass(_klass):
37
+ try:
38
+ _klass = import_from_string(settings.EVERYSK_SDK_ENTITIES_MODULES_PATH[_klass])
39
+ except KeyError:
40
+ raise FieldValueError(
41
+ f"The _klass value '{_klass}' must be a class or a string with the class name."
42
+ ) from KeyError
43
+
44
+ self._klass = _klass
45
+
46
+ def _process__klass(self, value: Any) -> Any:
47
+ """
48
+ This method is used to process the '_klass' attribute.
49
+ """
50
+ return value.__name__
51
+
52
+ def _from_base_64(self, file_data: str) -> str:
53
+ """
54
+ Decodes the base 64 string data to normal sting.
55
+
56
+ Args:
57
+ file_data (str or bytes): The input data to be decoded. This can be a string or bytes.
58
+
59
+ Returns:
60
+ str: The decoded version of the input data as a string.
61
+ """
62
+ return six.ensure_str(base64.b64decode(six.ensure_str(file_data)))
63
+
64
+ def _get_secrets_from_file(self, query: str | BaseDict | list[str], variant: str, workspace: str) -> str:
65
+ secrets_file = File.script.fetch(query, variant, workspace)
66
+
67
+ if not secrets_file:
68
+ return None
69
+
70
+ return self._from_base_64(secrets_file.data)
71
+
72
+ def normalize(self, value: str | BaseDict | list[str], variant: str, workspace: str = None) -> str:
73
+ normalized_value: str = None
74
+
75
+ if variant == 'selectSecrets':
76
+ from everysk.sdk.entities import Secrets
77
+
78
+ normalized_value = Secrets.value_from_path(value)
79
+
80
+ elif variant in {'metaString', 'password'}:
81
+ normalized_value = value
82
+
83
+ elif variant in {'selectFile', 'tagLatest', 'linkLatest'}:
84
+ normalized_value = self._get_secrets_from_file(value, variant, workspace)
85
+
86
+ elif variant == 'previousWorkers':
87
+ if isinstance(value, str) and not File.validate_id(value):
88
+ normalized_value = value
89
+
90
+ else:
91
+ normalized_value = self._get_secrets_from_file(value, variant, workspace)
92
+
93
+ else:
94
+ raise WorkerError(f'Unsupported secrets variant `{variant}`')
95
+
96
+ return normalized_value
97
+
98
+
99
+ class SecretsScriptMetaClass(QueryMetaClass):
100
+ """
101
+ Metaclass for the Script class that allows for the script attribute to be accessed
102
+ directly from the entity class.
103
+
104
+ Example:
105
+ To access the script attribute from the entity class:
106
+ >>> MyClass.script
107
+ Script()
108
+
109
+ Notes:
110
+ This metaclass overrides the __getatrribute__ method to enable direct access
111
+ """
112
+
113
+ def __getattribute__(cls, __name: str) -> Any:
114
+ """
115
+ Get the script attribute from the entity class.
116
+ """
117
+ if __name == 'script':
118
+ return SecretsScript(cls)
119
+ return super().__getattribute__(__name)
@@ -0,0 +1,17 @@
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 IntField, RegexField, StrField
11
+
12
+ ###############################################################################
13
+ # Settings Implementation
14
+ ###############################################################################
15
+ SECRETS_ID_PREFIX = StrField(default='scrt_', readonly=True)
16
+ SECRETS_ID_REGEX = RegexField(default=r'^scrt_[a-zA-Z0-9]{25}', readonly=True)
17
+ SECRETS_ID_MAX_LENGTH = IntField(default=30, readonly=True) # len(SECRETS_ID_PREFIX) + ENTITY_ID_LENGTH
@@ -0,0 +1,48 @@
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
+
11
+ ###############################################################################
12
+ # Imports
13
+ ###############################################################################
14
+ from everysk.core.fields import IntField, StrField, SetField, ListField
15
+
16
+ ###############################################################################
17
+ # Settings Implementation
18
+ ###############################################################################
19
+ ENTITY_NAME_MAX_LENGTH = IntField(default=200, readonly=True)
20
+ ENTITY_NAME_MIN_LENGTH = IntField(default=1, readonly=True)
21
+
22
+ ENTITY_DESCRIPTION_MAX_LEN = IntField(default=500, readonly=True)
23
+ ENTITY_DESCRIPTION_MIN_LEN = IntField(default=0, readonly=True)
24
+
25
+ ENTITY_MAX_TAG_LENGTH = IntField(default=252, readonly=True)
26
+ ENTITY_MIN_TAG_LENGTH = IntField(default=1, readonly=True)
27
+ ENTITY_MAX_TAG_SIZE = IntField(default=32, readonly=True)
28
+ ENTITY_MIN_TAG_SIZE = IntField(default=0, readonly=True)
29
+
30
+ ENTITY_DEFAULT_VERSION = StrField(default='v1', readonly=True)
31
+ ENTITY_ID_LENGTH = IntField(default=25, readonly=True)
32
+
33
+ ENTITY_MAX_TAG_SIZE = IntField(default=32, readonly=True)
34
+ ENTITY_MIN_TAG_SIZE = IntField(default=0, readonly=True)
35
+
36
+ ENTITY_LINK_UID_MAX_LENGTH = IntField(default=128, readonly=True)
37
+ ENTITY_LINK_UID_MIN_LENGTH = IntField(default=1, readonly=True)
38
+
39
+ DEFAULT_QUERY_OFFSET = IntField(default=0, readonly=True)
40
+ DEFAULT_QUERY_PAGE_SIZE = IntField(default=20, readonly=True)
41
+ DEFAULT_QUERY_LIMIT = IntField(default=None)
42
+
43
+ ENTITY_RETRIEVE_BATCH_SIZE = IntField(default=1000, readonly=True)
44
+
45
+ QUERY_OPERATORS = SetField(default={'<=', '>=', '<', '>', '=', '!=', 'IN', 'NOT_IN'}, readonly=True)
46
+
47
+ ENTITY_BASE_CURRENCY_DEFAULT_LIST = SetField(default={'USD', 'EUR', 'GBP', 'JPY', 'CNY', 'AUD', 'CAD', 'CHF', 'CNH', 'HKD', 'NZD', 'BRL'}, readonly=True)
48
+ ENTITY_ALLOWED_QUERY_ATTRIBUTES_FOR_ALL_OPERATORS = ListField(default=['name', 'date', 'link_uid', 'created_on', 'updated_on'], readonly=True)
@@ -0,0 +1,174 @@
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 types import NoneType
11
+ from typing import Any, Self
12
+ from collections.abc import Iterable
13
+
14
+ from six import string_types
15
+
16
+ from everysk.config import settings
17
+ from everysk.core.datetime import DateTime, Date
18
+ from everysk.core.exceptions import FieldValueError
19
+ from everysk.core.number import is_float_convertible
20
+ from everysk.core.string import normalize_string, to_string
21
+ from everysk.sdk.entities.base_list import EntityList
22
+
23
+
24
+ ###############################################################################
25
+ # Tags Class Implementation
26
+ ###############################################################################
27
+ class Tags(EntityList):
28
+ """
29
+ A specialized list for handling tags.
30
+
31
+ This class is a subclass of EntityList and provides specific validation for tags, including
32
+ size limits and pattern matching.
33
+
34
+ Attributes:
35
+ min_size (int): The minimum allowed size for the list (default is 1).
36
+ max_size (int): The maximum allowed size for the list (default is the value from settings).
37
+
38
+ Example:
39
+ To create a Tags for handling tags:
40
+ tags = Tags()
41
+ """
42
+ min_size: int = 1
43
+ max_size: int = settings.ENTITY_MAX_TAG_LENGTH
44
+
45
+ def __init__(self, *args):
46
+ """
47
+ Initialize the Tags.
48
+
49
+ Args:
50
+ *args: Optional initial elements to populate the list.
51
+
52
+ Example:
53
+ To create an Tags with initial elements:
54
+ >>> my_list = Tags(['tag1', 'tag2', 'tag3'])
55
+ """
56
+ if args:
57
+ try:
58
+ args = (list(dict.fromkeys(self.unify(args[0]))), )
59
+ except TypeError:
60
+ raise FieldValueError('Unsupported format in Tags.') from TypeError
61
+ super().__init__(*args)
62
+
63
+ def _validate(self, value: Any) -> str:
64
+ """
65
+ Validate a tag value.
66
+
67
+ Args:
68
+ value (str): The tag value to be validated.
69
+
70
+ Raises:
71
+ FieldValueError: If the tag value is invalid based on the specified criteria.
72
+
73
+ Returns:
74
+ str: The validated tag value.
75
+
76
+ Criteria:
77
+ - The value must be a string.
78
+ - The value's length must be between min_size ({min_size}) and max_size ({max_size}).
79
+ - The value must consist of only lowercase letters, digits, and underscores.
80
+ - The value cannot be empty.
81
+
82
+ Raises:
83
+ FieldValueError: If the tag value does not meet the specified criteria.
84
+ """
85
+ if isinstance(value, list) or isinstance(value, dict):
86
+ raise FieldValueError(f'Unsupported format in Tags: {type(value)}')
87
+ elif value == '' or value is Undefined:
88
+ value = str(None)
89
+ elif is_float_convertible(value) or value.__class__ in [NoneType, bool]:
90
+ value = str(value)
91
+ elif value.__class__ in [DateTime, Date]:
92
+ value = value.strftime('%Y%m%d')
93
+ elif not isinstance(value, string_types):
94
+ raise FieldValueError(f'Unsupported format in Tags: {type(value)}')
95
+
96
+ value = to_string(''.join(x if x.isalnum() else '_' for x in normalize_string(value))).lower()
97
+
98
+ if (
99
+ self.min_size is not None and self.min_size > len(value) or
100
+ self.max_size is not None and self.max_size < len(value)
101
+ ):
102
+ raise FieldValueError(f"Tags: '{value}' size it's not between {self.min_size} and {self.max_size}")
103
+
104
+ return value
105
+
106
+ def insert(self, __index: int, __object: Any) -> None:
107
+ """
108
+ Insert an object at a specified index if the object does not exist with validation.
109
+
110
+ Args:
111
+ __index (int): The index at which to insert the object.
112
+ __object: The object to be inserted.
113
+ """
114
+ __object = self._validate(__object)
115
+ if __object not in self:
116
+ super().insert(__index, __object)
117
+
118
+ def append(self, __object: Any) -> None:
119
+ """
120
+ Append an object to the list if the object does not exist with validation.
121
+
122
+ Args:
123
+ __object: The object to be appended.
124
+ """
125
+ __object = self._validate(__object)
126
+ if __object not in self:
127
+ super().append(__object)
128
+
129
+ def extend(self, __iterable: Iterable) -> None:
130
+ """
131
+ Extend the list with values from an iterable if the value does not exist with validation.
132
+
133
+ Args:
134
+ __iterable (Iterable): An iterable containing values to be added to the list.
135
+ """
136
+ order_values: dict = {}
137
+ for value in __iterable:
138
+ value: str = self._validate(value)
139
+ if value not in self:
140
+ order_values[value] = None
141
+ super().extend(list(order_values.keys()))
142
+
143
+ @classmethod
144
+ def unify(cls, tag_set: Any, reference_tags: list[Any] = None) -> Self:
145
+ """
146
+ Unify a set of tags with a reference set of tags.
147
+
148
+ Args:
149
+ tag_set (list): The set of tags to be unified.
150
+ reference_tags (list): The reference set of tags.
151
+
152
+ Returns:
153
+ list: The unified set of tags.
154
+
155
+ Example:
156
+ To unify a set of tags with a reference set of tags:
157
+ >>> unified_tags = Tags.unify_tags([['tag1', 'tag2'], ['tag3', 'tag4']], ['tag5', 'tag6'])
158
+ """
159
+ unified_tags: Self = cls()
160
+
161
+ if not tag_set:
162
+ return unified_tags
163
+ elif isinstance(tag_set, (int, float)):
164
+ tag_set = [tag_set]
165
+
166
+ for tags in tag_set:
167
+ if tags is not False and not tags and reference_tags:
168
+ unified_tags.extend(reference_tags)
169
+ elif isinstance(tags, list):
170
+ unified_tags.extend(cls.unify(tags, reference_tags))
171
+ else:
172
+ unified_tags.append(tags)
173
+
174
+ return unified_tags
@@ -0,0 +1,307 @@
1
+ ###############################################################################
2
+ #
3
+ # (C) Copyright 2025 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, Self
11
+
12
+ from everysk.config import settings
13
+ from everysk.core.datetime import DateTime
14
+ from everysk.core.fields import BoolField, DateTimeField, DictField, FloatField, IntField, ListField, StrField
15
+ from everysk.core.object import BaseDict
16
+ from everysk.sdk.entities.base import BaseEntity
17
+ from everysk.sdk.entities.query import Query
18
+
19
+
20
+ ###############################################################################
21
+ # Result Class Implementation
22
+ ###############################################################################
23
+ class Result(BaseDict):
24
+ status = StrField(default='ERROR', choices=('OK', 'ERROR', 'UNKNOW'))
25
+ data: list | dict | None = None
26
+ log = ListField()
27
+
28
+
29
+ ###############################################################################
30
+ # ResultField Class Implementation
31
+ ###############################################################################
32
+ class ResultField(DictField):
33
+ attr_type: Result | BaseDict | dict = Result | BaseDict | dict
34
+
35
+ def clean_value(self, value: Any) -> Result | None:
36
+ """
37
+ This method cleans the value of the field.
38
+
39
+ Args:s
40
+ value (Any): The value to be cleaned.
41
+
42
+ Returns:
43
+ Securities: The cleaned value.
44
+ """
45
+ if isinstance(value, dict):
46
+ value = Result(**value)
47
+
48
+ return super().clean_value(value)
49
+
50
+
51
+ ###############################################################################
52
+ # ParallelInfo Class Implementation
53
+ ###############################################################################
54
+ class ParallelInfo(BaseDict):
55
+ index = IntField(default=settings.WORKER_EXECUTION_UNFORKED_PARALLEL_INDEX, required_lazy=True)
56
+ length = IntField(default=settings.WORKER_EXECUTION_UNFORKED_PARALLEL_LENGTH, required_lazy=True)
57
+
58
+
59
+ ###############################################################################
60
+ # ParallelInfoField Class Implementation
61
+ ###############################################################################
62
+ class ParallelInfoField(DictField):
63
+ attr_type: ParallelInfo | BaseDict | dict = ParallelInfo | BaseDict | dict
64
+
65
+ def __init__(
66
+ self,
67
+ default: Any = None,
68
+ *,
69
+ required: bool = False,
70
+ readonly: bool = False,
71
+ required_lazy: bool = True,
72
+ empty_is_none: bool = False,
73
+ **kwargs,
74
+ ) -> None:
75
+ if default is None:
76
+ default = ParallelInfo()
77
+ super().__init__(
78
+ default=default,
79
+ required=required,
80
+ readonly=readonly,
81
+ required_lazy=required_lazy,
82
+ empty_is_none=empty_is_none,
83
+ **kwargs,
84
+ )
85
+
86
+ def clean_value(self, value: Any) -> Result | None:
87
+ """
88
+ This method cleans the value of the field.
89
+
90
+ Args:s
91
+ value (Any): The value to be cleaned.
92
+
93
+ Returns:
94
+ Securities: The cleaned value.
95
+ """
96
+ if isinstance(value, (dict, BaseDict)):
97
+ value = ParallelInfo(**value)
98
+
99
+ return super().clean_value(value)
100
+
101
+
102
+ ###############################################################################
103
+ # InputParams Class Implementation
104
+ ###############################################################################
105
+ class InputParams(BaseDict):
106
+ worker_id = StrField(empty_is_none=True)
107
+ workflow_id = StrField(regex=settings.WORKFLOW_ID_REGEX, empty_is_none=True)
108
+
109
+ worker_execution_id = StrField(regex=settings.WORKER_EXECUTION_ID_REGEX, empty_is_none=True)
110
+ workflow_execution_id = StrField(regex=settings.WORKFLOW_EXECUTION_ID_REGEX, empty_is_none=True)
111
+
112
+ workspace = StrField(empty_is_none=True)
113
+ worker_type = StrField(default=Undefined, choices=settings.WORKER_TEMPLATE_TYPES)
114
+ script_inputs = DictField()
115
+ inputs_info = DictField()
116
+ parallel_info = ParallelInfoField()
117
+
118
+ def to_dict(self, add_class_path: bool = False, recursion: bool = False) -> dict:
119
+ """
120
+ This method is used to convert the object to a dictionary.
121
+ """
122
+ dct: dict = super().to_dict(add_class_path=add_class_path, recursion=recursion)
123
+
124
+ if isinstance(dct['parallel_info'], ParallelInfo):
125
+ dct['parallel_info'] = dct['parallel_info'].to_dict(add_class_path=add_class_path, recursion=recursion)
126
+
127
+ return dct
128
+
129
+
130
+ ###############################################################################
131
+ # InputParamsField Class Implementation
132
+ ###############################################################################
133
+ class InputParamsField(DictField):
134
+ attr_type: InputParams | BaseDict | dict = InputParams | BaseDict | dict
135
+
136
+ def clean_value(self, value: Any) -> InputParams | None:
137
+ """
138
+ This method cleans the value of the field.
139
+
140
+ Args:s
141
+ value (Any): The value to be cleaned.
142
+
143
+ Returns:
144
+ Securities: The cleaned value.
145
+ """
146
+ if isinstance(value, dict):
147
+ value = InputParams(**value)
148
+
149
+ return super().clean_value(value)
150
+
151
+
152
+ ###############################################################################
153
+ # WorkerExecution Class Implementation
154
+ ###############################################################################
155
+ class WorkerExecution(BaseEntity):
156
+ id = StrField(regex=settings.WORKER_EXECUTION_ID_REGEX, required_lazy=True, empty_is_none=True)
157
+
158
+ result = ResultField()
159
+ storage = BoolField(default=False)
160
+ input_params = InputParamsField(required_lazy=True)
161
+ storage_input_params = BoolField(default=False)
162
+
163
+ parallel_info = ParallelInfoField()
164
+ status = StrField(default=settings.WORKER_EXECUTION_STATUS_PREPARING, choices=settings.WORKER_EXECUTION_STATUS_LIST)
165
+ execution_type = StrField(default=Undefined, choices=settings.WORKER_EXECUTION_TYPE_LIST, required_lazy=True)
166
+ start_time = DateTimeField()
167
+ end_time = DateTimeField()
168
+ duration = FloatField(default=0.0)
169
+ cpu_time = FloatField(default=0.0)
170
+ process_cpu_time = FloatField(default=0.0)
171
+
172
+ workflow_execution_id = StrField(regex=settings.WORKFLOW_EXECUTION_ID_REGEX, required_lazy=True, empty_is_none=True)
173
+ workflow_id = StrField(regex=settings.WORKFLOW_ID_REGEX, required_lazy=True, empty_is_none=True)
174
+ workflow_name = StrField(required_lazy=True, empty_is_none=True)
175
+ worker_id = StrField(regex=settings.WORKER_ID_REGEX, required_lazy=True, empty_is_none=True)
176
+ worker_name = StrField(required_lazy=True, empty_is_none=True)
177
+ worker_type = StrField(default=Undefined, choices=settings.WORKER_TEMPLATE_TYPES)
178
+
179
+ @staticmethod
180
+ def get_id_prefix() -> str:
181
+ """
182
+ Returns the prefix of the Worker Execution id field value.
183
+
184
+ Returns:
185
+ str: The prefix of the Worker Execution id field value.
186
+
187
+ Usage:
188
+ >>> WorkerExecution.get_id_prefix()
189
+ 'wkex_'
190
+
191
+ Notes:
192
+ The prefix is typically used to distinguish Worker Execution IDs from other types of IDs.
193
+ """
194
+ return settings.WORKER_EXECUTION_ID_PREFIX
195
+
196
+ def generate_id(self) -> str:
197
+ """
198
+ Generate a unique ID for an entity instance.
199
+
200
+ Returns:
201
+ str: The generated unique ID.
202
+
203
+ Example:
204
+ To generate a unique ID for an entity instance:
205
+ >>> unique_id = MyEntity().generate_id()
206
+ """
207
+ raise NotImplementedError
208
+
209
+ def to_dict(self, add_class_path: bool = False, recursion: bool = False) -> dict:
210
+ """
211
+ This method is used to convert the object to a dictionary.
212
+ """
213
+ dct: dict = super().to_dict(add_class_path=add_class_path, recursion=recursion)
214
+
215
+ if isinstance(dct['parallel_info'], ParallelInfo):
216
+ dct['parallel_info'] = dct['parallel_info'].to_dict(add_class_path=add_class_path, recursion=recursion)
217
+
218
+ if isinstance(dct['result'], Result):
219
+ dct['result'] = dct['result'].to_dict(add_class_path=add_class_path, recursion=recursion)
220
+
221
+ if isinstance(dct['input_params'], InputParams):
222
+ dct['input_params'] = dct['input_params'].to_dict(add_class_path=add_class_path, recursion=recursion)
223
+
224
+ if add_class_path is False:
225
+ if self.duration is None:
226
+ now = DateTime.now()
227
+ start = self.start_time if self.start_time else now
228
+ end = self.end_time if self.end_time else now
229
+ dct['duration'] = (end - start).total_seconds()
230
+
231
+ dct['started'] = self.start_time.timestamp() if self.start_time else None
232
+ dct['trigger'] = self.execution_type
233
+
234
+ if dct['result'] is not None:
235
+ dct['result'] = dct.get('result', {}).get('data', None)
236
+
237
+ dct.pop('execution_type')
238
+ dct.pop('start_time')
239
+ dct.pop('end_time')
240
+ dct.pop('storage')
241
+ dct.pop('storage_input_params')
242
+
243
+ return dct
244
+
245
+ def _check_entity_to_query(self) -> bool:
246
+ """
247
+ Check the entity object to query.
248
+
249
+ Returns:
250
+ bool: True if the entity object is valid.
251
+ """
252
+ return True
253
+
254
+ def _check_query(self, query: Query) -> bool:
255
+ """
256
+ Check the query object.
257
+
258
+ Args:
259
+ query (Query): The query object.
260
+
261
+ Returns:
262
+ bool: True if the query object is valid.
263
+ """
264
+ return True
265
+
266
+ def _mount_query(self, query: Query) -> Query:
267
+ """
268
+ Mount the query object.
269
+
270
+ Args:
271
+ query (Query): The query object.
272
+
273
+ Returns:
274
+ Query: The query object.
275
+ """
276
+ if self.workflow_execution_id is not None:
277
+ query = query.where('workflow_execution_id', self.workflow_execution_id)
278
+
279
+ return query
280
+
281
+ @classmethod
282
+ def get_input_params(cls, entity_id: str) -> InputParams:
283
+ """
284
+ Get the input_params of a Worker Execution with the given ID.
285
+
286
+ Args:
287
+ entity_id (str): The ID of the Worker Execution.
288
+
289
+ Returns:
290
+ InputParams: The input_params of the Worker Execution.
291
+
292
+ Raises:
293
+ ValueError: If the entity ID is invalid.
294
+ ValueError: If the entity is not found.
295
+ """
296
+ if cls.validate_id(entity_id) is False:
297
+ raise ValueError(f'Invalid Entity ID: {entity_id}')
298
+
299
+ entity: Self | None = cls.retrieve(entity_id)
300
+
301
+ if entity is None:
302
+ raise ValueError(f'Entity not found. Entity ID: {entity_id}')
303
+
304
+ if entity.input_params.worker_execution_id is None:
305
+ entity.input_params.worker_execution_id = entity.id # pylint: disable=attribute-defined-outside-init
306
+
307
+ return entity.input_params