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,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)