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,336 @@
|
|
|
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 everysk.config import settings
|
|
11
|
+
from everysk.core.datetime import Date, DateTime
|
|
12
|
+
from everysk.core.object import BaseDict, BaseObject
|
|
13
|
+
from everysk.core.serialize import CLASS_KEY, dumps, loads
|
|
14
|
+
from everysk.core.unittests import TestCase
|
|
15
|
+
from everysk.sdk.entities.datastore.base import Datastore
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
###############################################################################
|
|
19
|
+
# Serialize Dumps Test Case Implementation
|
|
20
|
+
###############################################################################
|
|
21
|
+
class SerializeJsonDumpsTestCase(TestCase):
|
|
22
|
+
def test_int(self):
|
|
23
|
+
self.assertEqual(dumps(1), '1')
|
|
24
|
+
|
|
25
|
+
def test_float(self):
|
|
26
|
+
self.assertEqual(dumps(1.1), '1.1')
|
|
27
|
+
|
|
28
|
+
def test_bytes(self):
|
|
29
|
+
self.assertEqual(dumps(b'bytes'), '{"__bytes__": {"encoding": "utf-8", "value": "bytes"}}')
|
|
30
|
+
|
|
31
|
+
def test_bytes_decode_bytes_true(self):
|
|
32
|
+
self.assertEqual(dumps(b'bytes', decode_bytes=True), '"bytes"')
|
|
33
|
+
|
|
34
|
+
def test_bytes_inside(self):
|
|
35
|
+
self.assertEqual(dumps({'key': b'bytes'}), '{"key": {"__bytes__": {"encoding": "utf-8", "value": "bytes"}}}')
|
|
36
|
+
|
|
37
|
+
def test_bytes_inside_decode_bytes_true(self):
|
|
38
|
+
self.assertEqual(dumps({'key': b'bytes'}, decode_bytes=True), '{"key": "bytes"}')
|
|
39
|
+
|
|
40
|
+
def test_bytes_decode_error(self):
|
|
41
|
+
self.assertEqual(
|
|
42
|
+
dumps({'key': b'Introdu\xe7\xe3o'}),
|
|
43
|
+
'{"key": {"__bytes__": {"encoding": "base64", "value": "SW50cm9kdefjbw=="}}}',
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
def test_str(self):
|
|
47
|
+
self.assertEqual(dumps('string'), '"string"')
|
|
48
|
+
|
|
49
|
+
def test_list(self):
|
|
50
|
+
self.assertEqual(dumps([1, 'string']), '[1, "string"]')
|
|
51
|
+
|
|
52
|
+
def test_tuple(self):
|
|
53
|
+
self.assertEqual(dumps((1, 'string')), '[1, "string"]')
|
|
54
|
+
|
|
55
|
+
def test_set(self):
|
|
56
|
+
# We need to use only one item because set changes the order randomly
|
|
57
|
+
self.assertEqual(dumps({1}), '[1]')
|
|
58
|
+
|
|
59
|
+
def test_frozenset(self):
|
|
60
|
+
# We need to use only one item because frozenset changes the order randomly
|
|
61
|
+
self.assertEqual(dumps(frozenset({1})), '[1]')
|
|
62
|
+
|
|
63
|
+
def test_dict(self):
|
|
64
|
+
self.assertEqual(dumps({'int': 1, 'str': 'string'}), '{"int": 1, "str": "string"}')
|
|
65
|
+
|
|
66
|
+
def test_bool(self):
|
|
67
|
+
self.assertEqual(dumps(True), 'true')
|
|
68
|
+
|
|
69
|
+
def test_none(self):
|
|
70
|
+
self.assertEqual(dumps(None), 'null')
|
|
71
|
+
|
|
72
|
+
def test_date(self):
|
|
73
|
+
self.assertEqual(dumps(Date(2023, 1, 1)), '{"__date__": "2023-01-01"}')
|
|
74
|
+
|
|
75
|
+
def test_datetime(self):
|
|
76
|
+
self.assertEqual(dumps(DateTime(2023, 1, 1, 12, 0, 0)), '{"__datetime__": "2023-01-01T12:00:00+00:00"}')
|
|
77
|
+
|
|
78
|
+
def test_undefined(self):
|
|
79
|
+
self.assertEqual(dumps(Undefined), 'null')
|
|
80
|
+
|
|
81
|
+
def test_undefined_true(self):
|
|
82
|
+
self.assertEqual(dumps(Undefined, use_undefined=True), '{"__undefined__": null}')
|
|
83
|
+
|
|
84
|
+
def test_date_format(self):
|
|
85
|
+
self.assertEqual(dumps(Date(2023, 1, 1), date_format='%Y%m%d'), '"20230101"')
|
|
86
|
+
|
|
87
|
+
def test_datetime_format(self):
|
|
88
|
+
self.assertEqual(dumps(DateTime(2023, 1, 1, 12, 0, 0), datetime_format='%Y%m%dT%H%M%S'), '"20230101T120000"')
|
|
89
|
+
|
|
90
|
+
def test_list_values(self):
|
|
91
|
+
values = [1, 'string', Date(2023, 1, 1), DateTime(2023, 1, 1, 12, 0, 0), Undefined, None]
|
|
92
|
+
self.assertEqual(
|
|
93
|
+
dumps(values, use_undefined=True),
|
|
94
|
+
'[1, "string", {"__date__": "2023-01-01"}, {"__datetime__": "2023-01-01T12:00:00+00:00"}, {"__undefined__": null}, null]',
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
def test_dict_values(self):
|
|
98
|
+
values = {
|
|
99
|
+
'int': 1,
|
|
100
|
+
'str': 'string',
|
|
101
|
+
'date': Date(2023, 1, 1),
|
|
102
|
+
'datetime': DateTime(2023, 1, 1, 12, 0, 0),
|
|
103
|
+
'undefined': Undefined,
|
|
104
|
+
'none': None,
|
|
105
|
+
}
|
|
106
|
+
self.assertEqual(
|
|
107
|
+
dumps(values, use_undefined=True),
|
|
108
|
+
'{"int": 1, "str": "string", "date": {"__date__": "2023-01-01"}, "datetime": {"__datetime__": "2023-01-01T12:00:00+00:00"}, "undefined": {"__undefined__": null}, "none": null}',
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
def test_protocol_json(self):
|
|
112
|
+
self.assertEqual(dumps(1, protocol='json'), '1')
|
|
113
|
+
|
|
114
|
+
def test_protocol_invalid(self):
|
|
115
|
+
with self.assertRaisesRegex(
|
|
116
|
+
ValueError, "Unsupported serialize protocol 'invalid'. Use 'json', 'orjson' or 'pickle'."
|
|
117
|
+
):
|
|
118
|
+
dumps(1, protocol='invalid')
|
|
119
|
+
|
|
120
|
+
def test_allow_nan_true(self):
|
|
121
|
+
self.assertEqual(dumps(float('nan'), allow_nan=True), 'NaN')
|
|
122
|
+
self.assertEqual(dumps(float('inf'), allow_nan=True), 'Infinity')
|
|
123
|
+
self.assertEqual(dumps(float('-inf'), allow_nan=True), '-Infinity')
|
|
124
|
+
|
|
125
|
+
def test_allow_nan_false(self):
|
|
126
|
+
with self.assertRaisesRegex(ValueError, 'Out of range float values are not JSON compliant'):
|
|
127
|
+
dumps(float('nan'), allow_nan=False)
|
|
128
|
+
with self.assertRaisesRegex(ValueError, 'Out of range float values are not JSON compliant'):
|
|
129
|
+
dumps(float('inf'), allow_nan=False)
|
|
130
|
+
with self.assertRaisesRegex(ValueError, 'Out of range float values are not JSON compliant'):
|
|
131
|
+
dumps(float('-inf'), allow_nan=False)
|
|
132
|
+
|
|
133
|
+
def test_object(self):
|
|
134
|
+
class Test:
|
|
135
|
+
def __init__(self, value):
|
|
136
|
+
self.value = value
|
|
137
|
+
|
|
138
|
+
with self.assertRaisesRegex(TypeError, 'Object of type Test is not JSON serializable'):
|
|
139
|
+
dumps(Test(1))
|
|
140
|
+
|
|
141
|
+
def test_complex_object(self):
|
|
142
|
+
class BaseDictTest(BaseDict):
|
|
143
|
+
var1: BaseDict | None = None
|
|
144
|
+
|
|
145
|
+
self.assertEqual(
|
|
146
|
+
dumps(BaseDictTest(var1=BaseDict(a='foo', b='boo')), sort_keys=True),
|
|
147
|
+
'{"%s": "everysk.core._tests.serialize.test_json.BaseDictTest", "_errors": null, "_is_frozen": false, "_silent": false, "var1": {"%s": "everysk.core.object.BaseDict", "_errors": null, "_is_frozen": false, "_silent": false, "a": "foo", "b": "boo"}}'
|
|
148
|
+
% (CLASS_KEY, CLASS_KEY),
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
def test_complex_object_with_key_function(self):
|
|
152
|
+
class BaseDictTest2(BaseDict):
|
|
153
|
+
var1: BaseDict | None = None
|
|
154
|
+
|
|
155
|
+
def _process_var1(self, value): # pylint: disable=unused-argument
|
|
156
|
+
return 'new_value'
|
|
157
|
+
|
|
158
|
+
self.assertEqual(
|
|
159
|
+
dumps(BaseDictTest2(var1=BaseDict(a='foo', b='boo')), sort_keys=True),
|
|
160
|
+
'{"%s": "everysk.core._tests.serialize.test_json.BaseDictTest2", "_errors": null, "_is_frozen": false, "_silent": false, "var1": "new_value"}'
|
|
161
|
+
% CLASS_KEY,
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
def test_base_object(self):
|
|
165
|
+
self.assertEqual(
|
|
166
|
+
dumps(BaseObject(a=1, b={}, c=[3]), sort_keys=True),
|
|
167
|
+
'{"%s": "everysk.core.object.BaseObject", "_errors": null, "_is_frozen": false, "_silent": false, "a": 1, "b": {}, "c": [3]}'
|
|
168
|
+
% CLASS_KEY,
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
def test_base_dict(self):
|
|
172
|
+
self.assertEqual(
|
|
173
|
+
dumps(BaseDict(a=1, b={}, c=[3]), sort_keys=True),
|
|
174
|
+
'{"%s": "everysk.core.object.BaseDict", "_errors": null, "_is_frozen": false, "_silent": false, "a": 1, "b": {}, "c": [3]}'
|
|
175
|
+
% CLASS_KEY,
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
def test_object_with_other_method(self):
|
|
179
|
+
class TestObject:
|
|
180
|
+
# pylint: disable=unused-argument
|
|
181
|
+
def to_my_name(self, *args, **kwargs):
|
|
182
|
+
return 'hi'
|
|
183
|
+
|
|
184
|
+
def to_native(self, *args, **kwargs):
|
|
185
|
+
return 'bye'
|
|
186
|
+
|
|
187
|
+
old = settings.SERIALIZE_CONVERT_METHOD_NAME
|
|
188
|
+
self.assertEqual(settings.SERIALIZE_CONVERT_METHOD_NAME, 'to_native')
|
|
189
|
+
self.assertEqual(dumps(TestObject()), '"bye"')
|
|
190
|
+
|
|
191
|
+
settings.SERIALIZE_CONVERT_METHOD_NAME = 'to_my_name'
|
|
192
|
+
self.assertEqual(settings.SERIALIZE_CONVERT_METHOD_NAME, 'to_my_name')
|
|
193
|
+
self.assertEqual(dumps(TestObject()), '"hi"')
|
|
194
|
+
|
|
195
|
+
settings.SERIALIZE_CONVERT_METHOD_NAME = old
|
|
196
|
+
self.assertEqual(settings.SERIALIZE_CONVERT_METHOD_NAME, 'to_native')
|
|
197
|
+
|
|
198
|
+
def test_return_str(self):
|
|
199
|
+
self.assertEqual(dumps('string', protocol='json', return_type='str'), '"string"')
|
|
200
|
+
|
|
201
|
+
def test_return_bytes(self):
|
|
202
|
+
self.assertEqual(dumps('string', protocol='json', return_type='bytes'), b'"string"')
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
###############################################################################
|
|
206
|
+
# Serialize Loads Test Case Implementation
|
|
207
|
+
###############################################################################
|
|
208
|
+
class SerializeJsonLoadsTestCase(TestCase):
|
|
209
|
+
def test_int(self):
|
|
210
|
+
self.assertEqual(loads('1'), 1)
|
|
211
|
+
|
|
212
|
+
def test_float(self):
|
|
213
|
+
self.assertEqual(loads('1.1'), 1.1)
|
|
214
|
+
|
|
215
|
+
def test_str(self):
|
|
216
|
+
self.assertEqual(loads('"string"'), 'string')
|
|
217
|
+
|
|
218
|
+
def test_list(self):
|
|
219
|
+
self.assertEqual(loads('[1, "string"]'), [1, 'string'])
|
|
220
|
+
|
|
221
|
+
def test_dict(self):
|
|
222
|
+
self.assertEqual(loads('{"int": 1, "str": "string"}'), {'int': 1, 'str': 'string'})
|
|
223
|
+
|
|
224
|
+
def test_bool(self):
|
|
225
|
+
self.assertEqual(loads('true'), True)
|
|
226
|
+
|
|
227
|
+
def test_none(self):
|
|
228
|
+
self.assertIsNone(loads('null'))
|
|
229
|
+
|
|
230
|
+
def test_date(self):
|
|
231
|
+
self.assertEqual(loads('{"__date__": "2023-01-01"}'), Date(2023, 1, 1))
|
|
232
|
+
|
|
233
|
+
def test_datetime(self):
|
|
234
|
+
self.assertEqual(loads('{"__datetime__": "2023-01-01T12:00:00+00:00"}'), DateTime(2023, 1, 1, 12, 0, 0))
|
|
235
|
+
|
|
236
|
+
def test_undefined_true(self):
|
|
237
|
+
self.assertEqual(loads('{"__undefined__": null}', use_undefined=True), Undefined)
|
|
238
|
+
|
|
239
|
+
def test_undefined_false(self):
|
|
240
|
+
self.assertIsNone(loads('{"__undefined__": null}', use_undefined=False))
|
|
241
|
+
|
|
242
|
+
def test_null(self):
|
|
243
|
+
self.assertIsNone(loads('null'))
|
|
244
|
+
|
|
245
|
+
def test_date_format(self):
|
|
246
|
+
self.assertEqual(loads('{"__date__": "20230101"}', date_format='%Y%m%d'), Date(2023, 1, 1))
|
|
247
|
+
|
|
248
|
+
def test_datetime_format(self):
|
|
249
|
+
self.assertEqual(
|
|
250
|
+
loads('{"__datetime__": "20230101T120000"}', datetime_format='%Y%m%dT%H%M%S'),
|
|
251
|
+
DateTime(2023, 1, 1, 12, 0, 0),
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
def test_list_values(self):
|
|
255
|
+
values = [1, 'string', Date(2023, 1, 1), DateTime(2023, 1, 1, 12, 0, 0), Undefined, None]
|
|
256
|
+
self.assertEqual(
|
|
257
|
+
loads(
|
|
258
|
+
'[1, "string", {"__date__": "2023-01-01"}, {"__datetime__": "2023-01-01T12:00:00+00:00"}, {"__undefined__": null}, null]',
|
|
259
|
+
use_undefined=True,
|
|
260
|
+
),
|
|
261
|
+
values,
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
def test_dict_values(self):
|
|
265
|
+
values = {
|
|
266
|
+
'int': 1,
|
|
267
|
+
'str': 'string',
|
|
268
|
+
'date': Date(2023, 1, 1),
|
|
269
|
+
'datetime': DateTime(2023, 1, 1, 12, 0, 0),
|
|
270
|
+
'undefined': Undefined,
|
|
271
|
+
'none': None,
|
|
272
|
+
}
|
|
273
|
+
self.assertEqual(
|
|
274
|
+
loads(
|
|
275
|
+
'{"int": 1, "str": "string", "date": {"__date__": "2023-01-01"}, "datetime": {"__datetime__": "2023-01-01T12:00:00+00:00"}, "undefined": {"__undefined__": null}, "none": null}',
|
|
276
|
+
use_undefined=True,
|
|
277
|
+
),
|
|
278
|
+
values,
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
def test_protocol_json(self):
|
|
282
|
+
self.assertEqual(loads('1', protocol='json'), 1)
|
|
283
|
+
|
|
284
|
+
def test_protocol_invalid(self):
|
|
285
|
+
with self.assertRaisesRegex(
|
|
286
|
+
ValueError, "Unsupported serialize protocol 'invalid'. Use 'json', 'orjson' or 'pickle'."
|
|
287
|
+
):
|
|
288
|
+
loads('1', protocol='invalid')
|
|
289
|
+
|
|
290
|
+
def test_nan(self):
|
|
291
|
+
nan = loads('NaN')
|
|
292
|
+
self.assertNotEqual(nan, nan)
|
|
293
|
+
|
|
294
|
+
def test_inf(self):
|
|
295
|
+
self.assertEqual(loads('Infinity'), float('inf'))
|
|
296
|
+
self.assertEqual(loads('-Infinity'), float('-inf'))
|
|
297
|
+
|
|
298
|
+
def test_bytes(self):
|
|
299
|
+
self.assertEqual(loads(b'1'), 1)
|
|
300
|
+
|
|
301
|
+
def test_bytes_inside(self):
|
|
302
|
+
self.assertEqual(loads('{"key": {"__bytes__": {"encoding": "utf-8", "value": "bytes"}}}'), {'key': b'bytes'})
|
|
303
|
+
|
|
304
|
+
def test_bytes_decode_error(self):
|
|
305
|
+
self.assertEqual(
|
|
306
|
+
loads('{"key": {"__bytes__": {"encoding": "base64", "value": "SW50cm9kdefjbw=="}}}'),
|
|
307
|
+
{'key': b'Introdu\xe7\xe3o'},
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
def test_base_object(self):
|
|
311
|
+
ret = loads('{"%s": "everysk.core.object.BaseObject", "a": 1, "b": {}, "c": [3]}' % CLASS_KEY)
|
|
312
|
+
self.assertIsInstance(ret, BaseObject)
|
|
313
|
+
self.assertEqual(ret.a, 1)
|
|
314
|
+
self.assertEqual(ret.b, {})
|
|
315
|
+
self.assertEqual(ret.c, [3])
|
|
316
|
+
|
|
317
|
+
ret = loads('{"%s": "app.var.test.Foo", "a": 1, "b": {}, "c": [3]}' % CLASS_KEY)
|
|
318
|
+
self.assertIsInstance(ret, BaseObject)
|
|
319
|
+
self.assertEqual(ret.a, 1)
|
|
320
|
+
self.assertEqual(ret.b, {})
|
|
321
|
+
self.assertEqual(ret.c, [3])
|
|
322
|
+
|
|
323
|
+
def test_base_dict(self):
|
|
324
|
+
self.assertDictEqual(
|
|
325
|
+
loads('{"%s": "everysk.core.object.BaseDict", "a": 1, "b": {}, "c": [3]}' % CLASS_KEY),
|
|
326
|
+
BaseDict(a=1, b={}, c=[3]),
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
def test_internal_entity(self):
|
|
330
|
+
self.assertIsInstance(
|
|
331
|
+
loads(
|
|
332
|
+
'{"%s": "engines.sample.Datastore", "workspace": null, "tags": [], "data": null, "id": null, "description": null, "updated_on": {"__datetime__": "2024-08-28T15:18:44.386204+00:00"}, "link_uid": null, "created_on": {"__datetime__": "2024-08-28T15:18:44.386204+00:00"}, "name": null, "level": null, "date": null, "version": "v1"}'
|
|
333
|
+
% CLASS_KEY
|
|
334
|
+
),
|
|
335
|
+
Datastore,
|
|
336
|
+
)
|
|
@@ -0,0 +1,295 @@
|
|
|
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 os
|
|
11
|
+
from json import JSONDecodeError
|
|
12
|
+
|
|
13
|
+
from everysk.core.datetime import Date, DateTime
|
|
14
|
+
from everysk.core.object import BaseDict, BaseObject
|
|
15
|
+
from everysk.core.serialize import dumps, loads
|
|
16
|
+
from everysk.core.unittests import TestCase
|
|
17
|
+
|
|
18
|
+
PDF = (
|
|
19
|
+
'JVBERi0xLjcKJcOkw7zDtsOfCjIgMCBvYmoKPDwvTGVuZ3RoIDMgMCBSL0ZpbHRlci9GbGF0ZURlY29kZT4+CnN0cmVhbQp4nDPQM1Qo59J3LCrJTEtMLlFw8nXmKlQ'
|
|
20
|
+
'wUDDQMzCyUDC1NNUzMjdVsDAx1LMwM1QoSuUK11LI43IFqgpUAAC+aw3mCmVuZHN0cmVhbQplbmRvYmoKCjMgMCBvYmoKNjcKZW5kb2JqCgo2IDAgb2JqCjw8Cj4+Cm'
|
|
21
|
+
'VuZG9iagoKNyAwIG9iago8PAovRm9udCA2IDAgUgovUHJvY1NldFsvUERGL1RleHRdCj4+CmVuZG9iagoKMSAwIG9iago8PC9UeXBlL1BhZ2UvUGFyZW50IDUgMCBSL'
|
|
22
|
+
'1Jlc291cmNlcyA3IDAgUi9NZWRpYUJveFswIDAgNTk1LjMwMzkzNzAwNzg3NCA4NDEuODg5NzYzNzc5NTI4XS9UYWJzL1MKL0NvbnRlbnRzIDIgMCBSPj4KZW5kb2Jq'
|
|
23
|
+
'Cgo0IDAgb2JqCjw8L1R5cGUvU3RydWN0RWxlbQovUy9Eb2N1bWVudAovUCA4IDAgUgovUGcgMSAwIFIKPj4KZW5kb2JqCgo4IDAgb2JqCjw8L1R5cGUvU3RydWN0VHJ'
|
|
24
|
+
'lZVJvb3QKL1BhcmVudFRyZWUgOSAwIFIKL0tbNCAwIFIgIF0KPj4KZW5kb2JqCgo5IDAgb2JqCjw8L051bXNbCl0+PgplbmRvYmoKCjUgMCBvYmoKPDwvVHlwZS9QYW'
|
|
25
|
+
'dlcwovUmVzb3VyY2VzIDcgMCBSCi9LaWRzWyAxIDAgUiBdCi9Db3VudCAxPj4KZW5kb2JqCgoxMCAwIG9iago8PC9UeXBlL0NhdGFsb2cvUGFnZXMgNSAwIFIKL1BhZ'
|
|
26
|
+
'2VNb2RlL1VzZU91dGxpbmVzCi9PcGVuQWN0aW9uWzEgMCBSIC9YWVogbnVsbCBudWxsIDBdCi9TdHJ1Y3RUcmVlUm9vdCA4IDAgUgovTGFuZyhwdC1CUikKL01hcmtJ'
|
|
27
|
+
'bmZvPDwvTWFya2VkIHRydWU+Pgo+PgplbmRvYmoKCjExIDAgb2JqCjw8L0NyZWF0b3I8RkVGRjAwNTcwMDcyMDA2OTAwNzQwMDY1MDA3Mj4KL1Byb2R1Y2VyPEZFRkY'
|
|
28
|
+
'wMDRDMDA2OTAwNjIwMDcyMDA2NTAwNEYwMDY2MDA2NjAwNjkwMDYzMDA2NTAwMjAwMDMyMDAzNDAwMkUwMDMyPgovQ3JlYXRpb25EYXRlKEQ6MjAyNTA1MjAxNjEzND'
|
|
29
|
+
'MtMDMnMDAnKT4+CmVuZG9iagoKeHJlZgowIDEyCjAwMDAwMDAwMDAgNjU1MzUgZiAKMDAwMDAwMDI1MiAwMDAwMCBuIAowMDAwMDAwMDE5IDAwMDAwIG4gCjAwMDAwM'
|
|
30
|
+
'DAxNTcgMDAwMDAgbiAKMDAwMDAwMDM4MyAwMDAwMCBuIAowMDAwMDAwNTUzIDAwMDAwIG4gCjAwMDAwMDAxNzYgMDAwMDAgbiAKMDAwMDAwMDE5OCAwMDAwMCBuIAow'
|
|
31
|
+
'MDAwMDAwNDUyIDAwMDAwIG4gCjAwMDAwMDA1MjQgMDAwMDAgbiAKMDAwMDAwMDYyNiAwMDAwMCBuIAowMDAwMDAwNzkzIDAwMDAwIG4gCnRyYWlsZXIKPDwvU2l6ZSA'
|
|
32
|
+
'xMi9Sb290IDEwIDAgUgovSW5mbyAxMSAwIFIKL0lEIFsgPDQzMTkzRDFENDQ4NDI4MUFCQ0ZCMzYzMEU0RkMzNDY3Pgo8NDMxOTNEMUQ0NDg0MjgxQUJDRkIzNjMwRT'
|
|
33
|
+
'RGQzM0Njc+IF0KL0RvY0NoZWNrc3VtIC8yMEIxOTM4NTMzNTVGQUQwMjFBRUU5MEU2ODFGMDk2QQo+PgpzdGFydHhyZWYKOTcyCiUlRU9GCg=='
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
PDF_PATH = os.path.join(os.path.dirname(__file__), 'example.pdf')
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class MyDict(dict):
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class SerializeOrjsonDumpsTestCase(TestCase):
|
|
44
|
+
def setUp(self):
|
|
45
|
+
self.params: dict = {'protocol': 'orjson', 'sort_keys': True}
|
|
46
|
+
|
|
47
|
+
## Constants
|
|
48
|
+
def test_none(self):
|
|
49
|
+
self.assertEqual(dumps(None, **self.params), 'null')
|
|
50
|
+
|
|
51
|
+
def test_bytes(self):
|
|
52
|
+
self.assertEqual(dumps(b'bytes', **self.params), '{"__bytes__": {"encoding": "utf-8", "value": "bytes"}}')
|
|
53
|
+
|
|
54
|
+
def test_bytes_decode_bytes_true(self):
|
|
55
|
+
self.assertEqual(dumps(b'bytes', decode_bytes=True, **self.params), '"bytes"')
|
|
56
|
+
|
|
57
|
+
def test_undefined_true(self):
|
|
58
|
+
self.assertEqual(dumps(Undefined, use_undefined=True, **self.params), '{"__undefined__":null}')
|
|
59
|
+
|
|
60
|
+
def test_undefined_false(self):
|
|
61
|
+
self.assertEqual(dumps(Undefined, use_undefined=False, **self.params), 'null')
|
|
62
|
+
|
|
63
|
+
def test_nan(self):
|
|
64
|
+
self.assertEqual(dumps(float('NaN'), use_undefined=False, **self.params), 'null')
|
|
65
|
+
|
|
66
|
+
def test_infinity(self):
|
|
67
|
+
self.assertEqual(dumps(float('Infinity'), use_undefined=False, **self.params), 'null')
|
|
68
|
+
|
|
69
|
+
def test_minus_infinity(self):
|
|
70
|
+
self.assertEqual(dumps(float('-Infinity'), use_undefined=False, **self.params), 'null')
|
|
71
|
+
|
|
72
|
+
def test_big_int(self):
|
|
73
|
+
self.assertEqual(dumps(123456789012345678901234567890, **self.params), '123456789012345678901234567890')
|
|
74
|
+
|
|
75
|
+
## Basic types
|
|
76
|
+
def test_str(self):
|
|
77
|
+
self.assertEqual(dumps('teste', **self.params), '"teste"')
|
|
78
|
+
|
|
79
|
+
def test_bytes(self):
|
|
80
|
+
self.assertEqual(
|
|
81
|
+
dumps({'key': b'teste'}, **self.params), '{"key":{"__bytes__":{"encoding":"utf-8","value":"teste"}}}'
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
def test_bytes_decode_bytes_true(self):
|
|
85
|
+
self.assertEqual(dumps({'key': b'teste'}, decode_bytes=True, **self.params), '{"key":"teste"}')
|
|
86
|
+
|
|
87
|
+
def test_bytes_base64(self):
|
|
88
|
+
with open(PDF_PATH, 'rb') as fd:
|
|
89
|
+
data = fd.read()
|
|
90
|
+
|
|
91
|
+
self.assertEqual(
|
|
92
|
+
dumps({'key': data}, **self.params), (f'{{"key":{{"__bytes__":{{"encoding":"base64","value":"{PDF}"}}}}}}')
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
def test_int(self):
|
|
96
|
+
self.assertEqual(dumps(1, **self.params), '1')
|
|
97
|
+
|
|
98
|
+
def test_float(self):
|
|
99
|
+
self.assertEqual(dumps(1.0, **self.params), '1.0')
|
|
100
|
+
|
|
101
|
+
def test_true(self):
|
|
102
|
+
self.assertEqual(dumps(True, **self.params), 'true')
|
|
103
|
+
|
|
104
|
+
def test_false(self):
|
|
105
|
+
self.assertEqual(dumps(False, **self.params), 'false')
|
|
106
|
+
|
|
107
|
+
def test_tuple(self):
|
|
108
|
+
self.assertEqual(dumps((2, 'a', True), **self.params), '[2,"a",true]')
|
|
109
|
+
|
|
110
|
+
def test_list(self):
|
|
111
|
+
self.assertEqual(dumps([2, 'a', True], **self.params), '[2,"a",true]')
|
|
112
|
+
|
|
113
|
+
def test_set(self):
|
|
114
|
+
# set have random order so we use only one element
|
|
115
|
+
self.assertEqual(dumps({2}, **self.params), '[2]')
|
|
116
|
+
|
|
117
|
+
def test_dict(self):
|
|
118
|
+
self.assertEqual(dumps({'a': 1, '2': 'b'}, **self.params), '{"2":"b","a":1}')
|
|
119
|
+
|
|
120
|
+
def test_date(self):
|
|
121
|
+
self.assertEqual(dumps(Date(2025, 1, 1), **self.params), '{"__date__":"2025-01-01"}')
|
|
122
|
+
|
|
123
|
+
def test_date_with_format(self):
|
|
124
|
+
self.assertEqual(dumps(Date(2025, 1, 1), date_format='%Y-%m-%d', **self.params), '"2025-01-01"')
|
|
125
|
+
|
|
126
|
+
def test_datetime_big_int_nan(self):
|
|
127
|
+
self.assertEqual(
|
|
128
|
+
dumps(
|
|
129
|
+
{
|
|
130
|
+
'datetime': DateTime(2025, 1, 1, 12, 0, 0),
|
|
131
|
+
'nan_value': float('NaN'),
|
|
132
|
+
'big_int': 123456789012345678901234567890,
|
|
133
|
+
},
|
|
134
|
+
**self.params,
|
|
135
|
+
),
|
|
136
|
+
'{"big_int":123456789012345678901234567890,"datetime":{"__datetime__":"2025-01-01T12:00:00+00:00"},"nan_value":null}',
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
def test_datetime(self):
|
|
140
|
+
self.assertEqual(
|
|
141
|
+
dumps(DateTime(2025, 1, 1, 12, 0, 0), **self.params), '{"__datetime__":"2025-01-01T12:00:00+00:00"}'
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
def test_datetime_with_format(self):
|
|
145
|
+
self.assertEqual(
|
|
146
|
+
dumps(DateTime(2025, 1, 1, 12, 0, 0), datetime_format='%Y-%m-%d %H:%M:%S', **self.params),
|
|
147
|
+
'"2025-01-01 12:00:00"',
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
## Objects
|
|
151
|
+
def test_base_object(self):
|
|
152
|
+
self.assertEqual(
|
|
153
|
+
dumps(BaseObject(a=1, b=2), **self.params),
|
|
154
|
+
'{"__class_path__":"everysk.core.object.BaseObject","_errors":null,"_is_frozen":false,"_silent":false,"a":1,"b":2}',
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
def test_base_object_without_class_path(self):
|
|
158
|
+
self.assertEqual(dumps(BaseObject(a=1, b=2), add_class_path=False, **self.params), '{"a":1,"b":2}')
|
|
159
|
+
|
|
160
|
+
def test_base_dict(self):
|
|
161
|
+
self.assertEqual(
|
|
162
|
+
dumps(BaseDict(a=1, b=2), **self.params),
|
|
163
|
+
'{"__class_path__":"everysk.core.object.BaseDict","_errors":null,"_is_frozen":false,"_silent":false,"a":1,"b":2}',
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
def test_base_dict_without_class_path(self):
|
|
167
|
+
self.assertEqual(dumps(BaseDict(a=1, b=2), add_class_path=False, **self.params), '{"a":1,"b":2}')
|
|
168
|
+
|
|
169
|
+
def test_dict_subclass_default(self):
|
|
170
|
+
# This use default dict serializer
|
|
171
|
+
self.assertEqual(dumps(MyDict(a=1, b=2), **self.params), '{"a":1,"b":2}')
|
|
172
|
+
|
|
173
|
+
def test_dict_subclass_passthrough(self):
|
|
174
|
+
# This will raise a TypeError because MyDict is not implemented
|
|
175
|
+
# to be serializable inside the JSONEncoder class
|
|
176
|
+
self.assertRaises(TypeError, dumps, MyDict(a=1, b=2), passthrough_subclass=True, **self.params)
|
|
177
|
+
|
|
178
|
+
def test_dict_key_non_str(self):
|
|
179
|
+
self.assertEqual(dumps({1: 'a', 1.1: 'b'}), '{"1": "a", "1.1": "b"}')
|
|
180
|
+
|
|
181
|
+
def test_return_str(self):
|
|
182
|
+
self.assertEqual(dumps('string', protocol='orjson', return_type='str'), '"string"')
|
|
183
|
+
|
|
184
|
+
def test_return_bytes(self):
|
|
185
|
+
self.assertEqual(dumps('string', protocol='orjson', return_type='bytes'), b'"string"')
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
class SerializeOrjsonLoadsTestCase(TestCase):
|
|
189
|
+
def setUp(self):
|
|
190
|
+
self.params: dict = {'protocol': 'orjson'}
|
|
191
|
+
|
|
192
|
+
## Constants
|
|
193
|
+
def test_null(self):
|
|
194
|
+
self.assertEqual(loads(b'null', **self.params), None)
|
|
195
|
+
|
|
196
|
+
def test_undefined_true(self):
|
|
197
|
+
self.assertEqual(loads(b'{"__undefined__":null}', use_undefined=True, **self.params), Undefined)
|
|
198
|
+
|
|
199
|
+
def test_undefined_false(self):
|
|
200
|
+
self.assertEqual(loads(b'{"__undefined__":null}', use_undefined=False, **self.params), None)
|
|
201
|
+
|
|
202
|
+
def test_nan(self):
|
|
203
|
+
self.assertIsNone(loads('NaN', **self.params))
|
|
204
|
+
self.assertRaises(JSONDecodeError, loads, 'NaN', nan_as_null=False, **self.params)
|
|
205
|
+
|
|
206
|
+
def test_infinity(self):
|
|
207
|
+
self.assertIsNone(loads('Infinity', **self.params))
|
|
208
|
+
self.assertRaises(JSONDecodeError, loads, 'Infinity', nan_as_null=False, **self.params)
|
|
209
|
+
|
|
210
|
+
def test_minus_infinity(self):
|
|
211
|
+
self.assertIsNone(loads('-Infinity', **self.params))
|
|
212
|
+
self.assertRaises(JSONDecodeError, loads, '-Infinity', nan_as_null=False, **self.params)
|
|
213
|
+
|
|
214
|
+
def test_big_int(self):
|
|
215
|
+
self.assertEqual(loads(b'123456789012345678901234567890', **self.params), 123456789012345678901234567890)
|
|
216
|
+
|
|
217
|
+
## Basic types
|
|
218
|
+
def test_str(self):
|
|
219
|
+
self.assertEqual(loads(b'"teste"', **self.params), 'teste')
|
|
220
|
+
|
|
221
|
+
def test_bytes(self):
|
|
222
|
+
self.assertEqual(loads(b'{"__bytes__":{"encoding":"utf-8","value":"teste"}}', **self.params), b'teste')
|
|
223
|
+
|
|
224
|
+
def test_bytes_base64(self):
|
|
225
|
+
with open(PDF_PATH, 'rb') as fd:
|
|
226
|
+
data = fd.read()
|
|
227
|
+
|
|
228
|
+
self.assertEqual(
|
|
229
|
+
loads((f'{{"key":{{"__bytes__":{{"encoding":"base64","value":"{PDF}"}}}}}}').encode(), **self.params),
|
|
230
|
+
{'key': data},
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
def test_int(self):
|
|
234
|
+
self.assertEqual(loads(b'1', **self.params), 1)
|
|
235
|
+
|
|
236
|
+
def test_float(self):
|
|
237
|
+
self.assertEqual(loads(b'1.0', **self.params), 1.0)
|
|
238
|
+
|
|
239
|
+
def test_true(self):
|
|
240
|
+
self.assertEqual(loads(b'true', **self.params), True)
|
|
241
|
+
|
|
242
|
+
def test_false(self):
|
|
243
|
+
self.assertEqual(loads(b'false', **self.params), False)
|
|
244
|
+
|
|
245
|
+
def test_list(self):
|
|
246
|
+
self.assertEqual(loads(b'[2,"a",true]', **self.params), [2, 'a', True])
|
|
247
|
+
|
|
248
|
+
def test_dict(self):
|
|
249
|
+
self.assertEqual(loads(b'{"a":1,"2":"b"}', **self.params), {'a': 1, '2': 'b'})
|
|
250
|
+
|
|
251
|
+
def test_datetime_big_int_nan(self):
|
|
252
|
+
self.assertEqual(
|
|
253
|
+
loads(
|
|
254
|
+
b'{"big_int":123456789012345678901234567890,"datetime":{"__datetime__":"2025-01-01T12:00:00+00:00"},"nan_value":null}',
|
|
255
|
+
**self.params,
|
|
256
|
+
),
|
|
257
|
+
{'big_int': 123456789012345678901234567890, 'datetime': DateTime(2025, 1, 1, 12, 0, 0), 'nan_value': None},
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
def test_date(self):
|
|
261
|
+
self.assertEqual(loads(b'{"__date__":"2025-01-01"}', **self.params), Date(2025, 1, 1))
|
|
262
|
+
|
|
263
|
+
def test_datetime(self):
|
|
264
|
+
self.assertEqual(
|
|
265
|
+
loads(b'{"__datetime__":"2025-01-01T12:00:00+00:00"}', **self.params), DateTime(2025, 1, 1, 12, 0, 0)
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
## Objects
|
|
269
|
+
def test_base_object(self):
|
|
270
|
+
# pylint: disable=protected-access
|
|
271
|
+
obj = loads(
|
|
272
|
+
b'{"__class_path__":"everysk.core.object.BaseObject","_errors":null,"_is_frozen":false,"_silent":false,"a":1,"b":2}',
|
|
273
|
+
**self.params,
|
|
274
|
+
)
|
|
275
|
+
self.assertEqual(obj.a, 1)
|
|
276
|
+
self.assertEqual(obj.b, 2)
|
|
277
|
+
self.assertEqual(obj._errors, None)
|
|
278
|
+
self.assertEqual(obj._is_frozen, False)
|
|
279
|
+
self.assertEqual(obj._silent, False)
|
|
280
|
+
self.assertEqual(obj.__class__.__name__, 'BaseObject')
|
|
281
|
+
|
|
282
|
+
def test_base_dict(self):
|
|
283
|
+
self.assertEqual(
|
|
284
|
+
loads(
|
|
285
|
+
b'{"__class_path__":"everysk.core.object.BaseDict","_errors":null,"_is_frozen":false,"_silent":false,"a":1,"b":2}',
|
|
286
|
+
**self.params,
|
|
287
|
+
),
|
|
288
|
+
BaseDict(a=1, b=2),
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
def test_dict_subclass(self):
|
|
292
|
+
self.assertEqual(
|
|
293
|
+
loads(b'{"__class_path__":"everysk.core._tests.serialize.test_orjson.MyDict","a":1,"b":2}', **self.params),
|
|
294
|
+
MyDict(a=1, b=2),
|
|
295
|
+
)
|
|
@@ -0,0 +1,48 @@
|
|
|
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 everysk.core.exceptions import SigningError
|
|
11
|
+
from everysk.core.serialize import dumps, loads
|
|
12
|
+
from everysk.core.unittests import TestCase, mock
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class SerializePickleDumpsTestCase(TestCase):
|
|
16
|
+
|
|
17
|
+
@mock.patch('os.environ', {'EVERYSK_SIGNING_KEY': 'test'})
|
|
18
|
+
def test_protocol_pickle(self):
|
|
19
|
+
self.assertEqual(
|
|
20
|
+
dumps(1, protocol='pickle'),
|
|
21
|
+
b'68cec7e4c81fe8571641ae3709d4f546841ec9b1:\x80\x04K\x01.'
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
@mock.patch('os.environ', {'EVERYSK_SIGNING_KEY': None})
|
|
25
|
+
def test_protocol_pickle_no_key(self):
|
|
26
|
+
self.assertEqual(
|
|
27
|
+
dumps(1, protocol='pickle'),
|
|
28
|
+
b'\x80\x04K\x01.'
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class SerializePickleLoadsTestCase(TestCase):
|
|
33
|
+
|
|
34
|
+
@mock.patch('os.environ', {'EVERYSK_SIGNING_KEY': 'test'})
|
|
35
|
+
def test_protocol_pickle(self):
|
|
36
|
+
self.assertEqual(
|
|
37
|
+
loads(b'68cec7e4c81fe8571641ae3709d4f546841ec9b1:\x80\x04K\x01.', protocol='pickle'),
|
|
38
|
+
1
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
@mock.patch('os.environ', {'EVERYSK_SIGNING_KEY': 'test_invalid'})
|
|
42
|
+
def test_protocol_pickle_invalid(self):
|
|
43
|
+
with self.assertRaisesRegex(SigningError, 'Error trying to unsign data.'):
|
|
44
|
+
loads(b'1dd5f31b5032a28d51025f46121b03ebe20f258a:\x80\x04\x95\x05\x00\x00\x00\x00\x00\x00\x00\x8c\x01k\x94.', protocol='pickle')
|
|
45
|
+
|
|
46
|
+
@mock.patch('os.environ', {'EVERYSK_SIGNING_KEY': ''})
|
|
47
|
+
def test_protocol_pickle_no_key(self):
|
|
48
|
+
self.assertEqual(loads(b'\x80\x04K\x01.', protocol='pickle'), 1)
|