everysk-lib 1.10.4__tar.gz → 1.11.0__tar.gz

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 (147) hide show
  1. {everysk_lib-1.10.4/src/everysk_lib.egg-info → everysk_lib-1.11.0}/PKG-INFO +1 -1
  2. everysk_lib-1.11.0/src/everysk/core/_tests/mapping/base.py +306 -0
  3. everysk_lib-1.11.0/src/everysk/core/_tests/mapping/fields.py +1154 -0
  4. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/datetime/datetime.py +1 -1
  5. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/http.py +6 -6
  6. everysk_lib-1.11.0/src/everysk/core/mapping/__init__.py +29 -0
  7. everysk_lib-1.11.0/src/everysk/core/mapping/base.py +214 -0
  8. everysk_lib-1.11.0/src/everysk/core/mapping/fields.py +1133 -0
  9. everysk_lib-1.11.0/src/everysk/core/mapping/metaclass.py +101 -0
  10. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/object.py +132 -124
  11. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/tests.py +19 -0
  12. everysk_lib-1.11.0/src/everysk/sql/__init__.py +9 -0
  13. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sql/connection.py +24 -0
  14. {everysk_lib-1.10.4 → everysk_lib-1.11.0/src/everysk_lib.egg-info}/PKG-INFO +1 -1
  15. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk_lib.egg-info/SOURCES.txt +7 -0
  16. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/LICENSE.txt +0 -0
  17. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/MANIFEST.in +0 -0
  18. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/README.md +0 -0
  19. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/pyproject.toml +0 -0
  20. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/setup.cfg +0 -0
  21. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/setup.py +0 -0
  22. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/__init__.py +0 -0
  23. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/_version.py +0 -0
  24. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/api/__init__.py +0 -0
  25. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/api/api_requestor.py +0 -0
  26. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/api/api_resources/__init__.py +0 -0
  27. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/api/api_resources/api_resource.py +0 -0
  28. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/api/api_resources/calculation.py +0 -0
  29. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/api/api_resources/custom_index.py +0 -0
  30. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/api/api_resources/datastore.py +0 -0
  31. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/api/api_resources/file.py +0 -0
  32. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/api/api_resources/market_data.py +0 -0
  33. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/api/api_resources/parser.py +0 -0
  34. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/api/api_resources/portfolio.py +0 -0
  35. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/api/api_resources/private_security.py +0 -0
  36. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/api/api_resources/report.py +0 -0
  37. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/api/api_resources/report_template.py +0 -0
  38. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/api/api_resources/tests.py +0 -0
  39. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/api/api_resources/worker_execution.py +0 -0
  40. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/api/api_resources/workflow.py +0 -0
  41. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/api/api_resources/workflow_execution.py +0 -0
  42. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/api/api_resources/workspace.py +0 -0
  43. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/api/http_client.py +0 -0
  44. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/api/tests.py +0 -0
  45. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/api/utils.py +0 -0
  46. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/config.py +0 -0
  47. {everysk_lib-1.10.4/src/everysk/server → everysk_lib-1.11.0/src/everysk/core/_tests/mapping}/__init__.py +0 -0
  48. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/_tests/serialize/test_json.py +0 -0
  49. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/_tests/serialize/test_orjson.py +0 -0
  50. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/_tests/serialize/test_pickle.py +0 -0
  51. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/cloud_function/main.py +0 -0
  52. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/cloud_function/tests.py +0 -0
  53. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/compress.py +0 -0
  54. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/datetime/__init__.py +0 -0
  55. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/datetime/calendar.py +0 -0
  56. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/datetime/date.py +0 -0
  57. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/datetime/date_expression.py +0 -0
  58. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/datetime/date_mixin.py +0 -0
  59. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/datetime/date_settings.py +0 -0
  60. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/exceptions.py +0 -0
  61. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/fields.py +0 -0
  62. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/firestore.py +0 -0
  63. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/fixtures/_settings.py +0 -0
  64. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/fixtures/other/_settings.py +0 -0
  65. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/fixtures/user_agents.json +0 -0
  66. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/lists.py +0 -0
  67. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/log.py +0 -0
  68. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/number.py +0 -0
  69. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/redis.py +0 -0
  70. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/retry.py +0 -0
  71. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/serialize.py +0 -0
  72. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/sftp.py +0 -0
  73. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/signing.py +0 -0
  74. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/slack.py +0 -0
  75. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/string.py +0 -0
  76. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/threads.py +0 -0
  77. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/undefined.py +0 -0
  78. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/unittests.py +0 -0
  79. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/core/workers.py +0 -0
  80. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/__init__.py +0 -0
  81. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/base.py +0 -0
  82. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/brutils/cnpj.py +0 -0
  83. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/brutils/cnpj_pd.py +0 -0
  84. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/engines/__init__.py +0 -0
  85. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/engines/cache.py +0 -0
  86. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/engines/compliance.py +0 -0
  87. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/engines/cryptography.py +0 -0
  88. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/engines/lock.py +0 -0
  89. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/engines/market_data.py +0 -0
  90. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/engines/settings.py +0 -0
  91. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/__init__.py +0 -0
  92. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/base.py +0 -0
  93. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/base_list.py +0 -0
  94. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/custom_index/base.py +0 -0
  95. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/custom_index/settings.py +0 -0
  96. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/datastore/base.py +0 -0
  97. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/datastore/settings.py +0 -0
  98. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/fields.py +0 -0
  99. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/file/base.py +0 -0
  100. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/file/settings.py +0 -0
  101. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/portfolio/base.py +0 -0
  102. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/portfolio/securities.py +0 -0
  103. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/portfolio/security.py +0 -0
  104. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/portfolio/settings.py +0 -0
  105. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/private_security/base.py +0 -0
  106. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/private_security/settings.py +0 -0
  107. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/query.py +0 -0
  108. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/report/base.py +0 -0
  109. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/report/settings.py +0 -0
  110. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/script.py +0 -0
  111. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/secrets/base.py +0 -0
  112. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/secrets/script.py +0 -0
  113. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/secrets/settings.py +0 -0
  114. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/settings.py +0 -0
  115. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/tags.py +0 -0
  116. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/worker_execution/base.py +0 -0
  117. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/worker_execution/settings.py +0 -0
  118. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/workflow_execution/base.py +0 -0
  119. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/workflow_execution/settings.py +0 -0
  120. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/workspace/base.py +0 -0
  121. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/entities/workspace/settings.py +0 -0
  122. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/settings.py +0 -0
  123. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/tests.py +0 -0
  124. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sdk/worker_base.py +0 -0
  125. {everysk_lib-1.10.4/src/everysk/sql → everysk_lib-1.11.0/src/everysk/server}/__init__.py +0 -0
  126. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/server/applications.py +0 -0
  127. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/server/endpoints.py +0 -0
  128. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/server/example_api.py +0 -0
  129. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/server/middlewares.py +0 -0
  130. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/server/requests.py +0 -0
  131. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/server/responses.py +0 -0
  132. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/server/routing.py +0 -0
  133. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/server/settings.py +0 -0
  134. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/server/tests.py +0 -0
  135. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/settings.py +0 -0
  136. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sql/model.py +0 -0
  137. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sql/query.py +0 -0
  138. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sql/row_factory.py +0 -0
  139. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sql/settings.py +0 -0
  140. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/sql/utils.py +0 -0
  141. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/tests.py +0 -0
  142. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/utils.py +0 -0
  143. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk/version.py +0 -0
  144. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk_lib.egg-info/.gitignore +0 -0
  145. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk_lib.egg-info/dependency_links.txt +0 -0
  146. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk_lib.egg-info/requires.txt +0 -0
  147. {everysk_lib-1.10.4 → everysk_lib-1.11.0}/src/everysk_lib.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: everysk-lib
3
- Version: 1.10.4
3
+ Version: 1.11.0
4
4
  Summary: Generic lib to share python code on Everysk.
5
5
  License-Expression: LicenseRef-Proprietary
6
6
  Project-URL: Homepage, https://everysk.com/
@@ -0,0 +1,306 @@
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.mapping import BaseMapping
11
+ from everysk.core.object import BaseDict, BaseObject
12
+ from everysk.core.unittests import TestCase
13
+
14
+
15
+ class TestClass(BaseMapping):
16
+ __invalid_keys__: frozenset[str] = frozenset({'field6'})
17
+
18
+ field1: int = 10
19
+ field2: int
20
+ field3 = 3.0
21
+ field6: str = 'value'
22
+
23
+
24
+ class BaseMappingTestCase(TestCase):
25
+ def tearDown(self) -> None:
26
+ # Reset TestClass to initial state after each test
27
+ TestClass.field1 = 10
28
+ TestClass.field2 = None
29
+ TestClass.field3 = 3.0
30
+ TestClass._generate_attributes() # noqa: SLF001
31
+
32
+ def test_attributes(self) -> None:
33
+ self.assertSetEqual(TestClass.__attributes__, {'field1', 'field2', 'field3', 'field6'})
34
+
35
+ def test_attributes_inheritance(self) -> None:
36
+ class SubTestClass(TestClass):
37
+ field4: str = 'test'
38
+ field5: float
39
+
40
+ self.assertSetEqual(SubTestClass.__attributes__, {'field1', 'field2', 'field3', 'field4', 'field5', 'field6'})
41
+
42
+ def test_attributes_add(self) -> None:
43
+ class SubTestClass(TestClass):
44
+ field4: str = 'test'
45
+
46
+ SubTestClass.field5 = 5.0 # Adding attribute after class creation
47
+ self.assertSetEqual(SubTestClass.__attributes__, {'field1', 'field2', 'field3', 'field4', 'field5', 'field6'})
48
+
49
+ def test_changed_attributes(self) -> None:
50
+ obj = TestClass()
51
+ obj.field2 = 20
52
+ obj.field1 = 10
53
+ obj.field3 = 5.0
54
+ self.assertDictEqual(obj, {'field1': 10, 'field2': 20, 'field3': 5.0})
55
+
56
+ def test_changed_keys(self) -> None:
57
+ obj = TestClass()
58
+ obj['field2'] = 25
59
+ obj['field1'] = 10
60
+ obj['field3'] = 4.0
61
+ self.assertDictEqual(obj, {'field1': 10, 'field2': 25, 'field3': 4.0})
62
+
63
+ def test_delete_attribute(self) -> None:
64
+ obj = TestClass(field2=30)
65
+ self.assertEqual(obj.field2, 30)
66
+ self.assertEqual(obj['field2'], 30)
67
+ del obj.field2
68
+ with self.assertRaises(AttributeError) as context:
69
+ _ = obj.field2
70
+ self.assertEqual(str(context.exception), "'TestClass' object has no attribute 'field2'.")
71
+ with self.assertRaises(KeyError) as context:
72
+ _ = obj['field2']
73
+ self.assertEqual(str(context.exception), "'field2'")
74
+
75
+ def test_delete_key(self) -> None:
76
+ obj = TestClass(field2=30)
77
+ self.assertEqual(obj.field2, 30)
78
+ self.assertEqual(obj['field2'], 30)
79
+ del obj['field2']
80
+ with self.assertRaises(AttributeError) as context:
81
+ _ = obj.field2
82
+ self.assertEqual(str(context.exception), "'TestClass' object has no attribute 'field2'.")
83
+ with self.assertRaises(KeyError) as context:
84
+ _ = obj['field2']
85
+ self.assertEqual(str(context.exception), "'field2'")
86
+
87
+ def test_equal(self) -> None:
88
+ obj1 = TestClass()
89
+ obj2 = TestClass()
90
+ self.assertDictEqual(obj1, obj2)
91
+
92
+ obj1.field2 = 20
93
+ self.assertNotEqual(obj1, obj2)
94
+
95
+ obj2.field2 = 20
96
+ self.assertDictEqual(obj1, obj2)
97
+
98
+ def test_equal_changed_class_value(self) -> None:
99
+ obj1 = TestClass()
100
+ obj2 = TestClass()
101
+ self.assertDictEqual(obj1, obj2)
102
+
103
+ TestClass.field1 = 15
104
+ self.assertDictEqual(obj1, obj2)
105
+ self.assertEqual(obj1.field1, 10)
106
+ self.assertEqual(obj1['field1'], 10)
107
+ self.assertEqual(obj2.field1, 10)
108
+ self.assertEqual(obj2['field1'], 10)
109
+
110
+ def test_field_type(self) -> None:
111
+ self.assertDictEqual(
112
+ TestClass.__annotations__,
113
+ {'__invalid_keys__': frozenset[str], 'field1': int, 'field2': int, 'field6': str, 'field3': float},
114
+ )
115
+ self.assertEqual(TestClass.__dict__['field1'].field_type, int)
116
+ self.assertEqual(TestClass.__dict__['field2'].field_type, int)
117
+ self.assertEqual(TestClass.__dict__['field3'].field_type, float)
118
+ self.assertEqual(TestClass.__dict__['field6'].field_type, str)
119
+
120
+ def test_field_type_generic_alias(self) -> None:
121
+ class GenericTestClass(BaseMapping):
122
+ field1: list[int] = None
123
+
124
+ self.assertEqual(GenericTestClass.__dict__['field1'].field_type, list)
125
+
126
+ def test_field_type_union(self) -> None:
127
+ class UnionTestClass(BaseMapping):
128
+ field1: int | list[str] | None = None
129
+
130
+ self.assertEqual(UnionTestClass.__dict__['field1'].field_type, int | list)
131
+
132
+ def test_inherited_changed(self) -> None:
133
+ class SubTestClass(TestClass):
134
+ field4: str = 'test'
135
+
136
+ obj = SubTestClass()
137
+ obj2 = SubTestClass()
138
+
139
+ obj.field2 = 20
140
+ obj.field4 = 'changed'
141
+ self.assertDictEqual(obj, {'field1': 10, 'field2': 20, 'field3': 3.0, 'field4': 'changed'})
142
+ self.assertDictEqual(obj2, {'field1': 10, 'field2': None, 'field3': 3.0, 'field4': 'test'})
143
+
144
+ def test_inherited_attribute(self) -> None:
145
+ class SubTestClass(TestClass):
146
+ pass
147
+
148
+ obj = SubTestClass()
149
+ self.assertEqual(obj.field1, 10)
150
+ self.assertEqual(obj.field2, None)
151
+ self.assertEqual(obj.field3, 3.0)
152
+ self.assertEqual(obj.field6, 'value')
153
+ # Fields that are keys don't have inherited values
154
+ TestClass.field1 = 20
155
+ self.assertEqual(obj.field1, 10)
156
+ self.assertEqual(obj['field1'], 10)
157
+ # Fields that are attributes only have inherited values
158
+ TestClass.field6 = 'new_value'
159
+ self.assertEqual(obj.field6, 'new_value')
160
+
161
+ def test_init(self) -> None:
162
+ obj = TestClass(field2=25, field3=4.5)
163
+ self.assertEqual(obj.field1, 10)
164
+ self.assertEqual(obj['field1'], 10)
165
+ self.assertEqual(obj.field2, 25)
166
+ self.assertEqual(obj['field2'], 25)
167
+ self.assertEqual(obj.field3, 4.5)
168
+ self.assertEqual(obj['field3'], 4.5)
169
+ self.assertDictEqual(obj, {'field1': 10, 'field2': 25, 'field3': 4.5})
170
+
171
+ def test_init_new_attribute(self) -> None:
172
+ obj = BaseMapping(key='value')
173
+ self.assertEqual(obj.key, 'value')
174
+ self.assertEqual(obj['key'], 'value')
175
+
176
+ def test_isinstance(self) -> None:
177
+ self.assertIsInstance(BaseMapping(), dict)
178
+ self.assertIsInstance(BaseMapping(), BaseDict)
179
+ self.assertIsInstance(BaseMapping(), BaseMapping)
180
+ self.assertNotIsInstance(BaseDict(), dict)
181
+ self.assertIsInstance(BaseDict(), BaseDict)
182
+ self.assertNotIsInstance(BaseDict(), BaseMapping)
183
+
184
+ def test_key(self) -> None:
185
+ obj = TestClass()
186
+ self.assertEqual(obj['field1'], 10)
187
+ self.assertEqual(obj['field2'], None)
188
+ self.assertEqual(obj['field3'], 3.0)
189
+
190
+ def test_key_changed(self) -> None:
191
+ obj = TestClass()
192
+ obj['field2'] = 30
193
+ self.assertEqual(obj.field2, 30)
194
+ self.assertEqual(obj['field2'], 30)
195
+
196
+ def test_key_invalid(self) -> None:
197
+ class SubTestClass(TestClass):
198
+ __invalid_keys__ = frozenset({'field3'})
199
+
200
+ obj = SubTestClass()
201
+ with self.assertRaises(KeyError):
202
+ _ = obj['field3']
203
+
204
+ self.assertEqual(obj.field3, 3.0)
205
+ obj.field3 = 5.0
206
+ self.assertEqual(obj.field3, 5.0)
207
+ with self.assertRaises(KeyError):
208
+ _ = obj['field3']
209
+
210
+ del obj.field3
211
+ with self.assertRaises(AttributeError):
212
+ _ = obj.field3
213
+
214
+ with self.assertRaises(KeyError):
215
+ _ = obj['field3']
216
+
217
+ def test_new_attribute(self) -> None:
218
+ obj = TestClass()
219
+ obj.new = 'new_value'
220
+ self.assertEqual(obj.new, 'new_value')
221
+ self.assertEqual(obj['new'], 'new_value')
222
+
223
+ def test_value_class(self) -> None:
224
+ obj = TestClass()
225
+ self.assertEqual(TestClass.field1, 10)
226
+ self.assertEqual(obj.field1, 10)
227
+ self.assertEqual(obj['field1'], 10)
228
+ TestClass.field1 = 15
229
+ self.assertEqual(TestClass.field1, 15)
230
+ # Values that are fields don't change in the instance only in the class
231
+ self.assertEqual(obj.field1, 10)
232
+ self.assertEqual(obj['field1'], 10)
233
+
234
+ def test_value_instance(self) -> None:
235
+ obj = TestClass()
236
+ self.assertEqual(TestClass.field1, 10)
237
+ self.assertEqual(obj.field1, 10)
238
+ self.assertEqual(obj['field1'], 10)
239
+ obj.field1 = 20
240
+ self.assertEqual(TestClass.field1, 10)
241
+ self.assertEqual(obj.field1, 20)
242
+ self.assertEqual(obj['field1'], 20)
243
+
244
+ def test_value_instances(self) -> None:
245
+ obj1 = TestClass()
246
+ obj2 = TestClass()
247
+ self.assertEqual(TestClass.field1, 10)
248
+ self.assertEqual(obj1.field1, 10)
249
+ self.assertEqual(obj1['field1'], 10)
250
+ self.assertEqual(obj2.field1, 10)
251
+ self.assertEqual(obj2['field1'], 10)
252
+
253
+ obj1.field1 = 20
254
+ self.assertEqual(TestClass.field1, 10)
255
+ self.assertEqual(obj1.field1, 20)
256
+ self.assertEqual(obj1['field1'], 20)
257
+ self.assertEqual(obj2.field1, 10)
258
+ self.assertEqual(obj2['field1'], 10)
259
+
260
+ def test_to_dict_defaults(self) -> None:
261
+ obj = TestClass()
262
+ expected_dict = {'field1': 10, 'field2': None, 'field3': 3.0}
263
+ self.assertDictEqual(obj.to_dict(), expected_dict)
264
+
265
+ def test_to_dict_defaults_sub_object(self) -> None:
266
+ class SubTestClass(TestClass):
267
+ field4: str = 'default'
268
+
269
+ obj = SubTestClass()
270
+ expected_dict = {'field1': 10, 'field2': None, 'field3': 3.0, 'field4': 'default'}
271
+ self.assertDictEqual(obj.to_dict(), expected_dict)
272
+
273
+ def test_to_dict_add_class_path(self) -> None:
274
+ obj = TestClass()
275
+ expected_dict = {
276
+ 'field1': 10,
277
+ 'field2': None,
278
+ 'field3': 3.0,
279
+ '__class_path__': obj.get_full_dotted_class_path(),
280
+ }
281
+ self.assertDictEqual(obj.to_dict(add_class_path=True), expected_dict)
282
+
283
+ def test_to_dict_exclude_keys(self) -> None:
284
+ class SubTestClass(TestClass):
285
+ def _to_dict_excluded_keys(self) -> set[str]:
286
+ return {'field2', 'field3'}
287
+
288
+ obj = SubTestClass()
289
+ expected_dict = {'field1': 10}
290
+ self.assertDictEqual(obj.to_dict(), expected_dict)
291
+
292
+ def test_to_dict_recursive(self) -> None:
293
+ class SubTestClass(BaseMapping):
294
+ field1: BaseMapping = BaseMapping(field1=10)
295
+ field2: BaseDict = BaseDict(key='value')
296
+ field3: BaseObject = BaseObject(attr='value')
297
+
298
+ obj = SubTestClass()
299
+ expected_dict = {'field1': {'field1': 10}, 'field2': {'key': 'value'}, 'field3': {'attr': 'value'}}
300
+ self.assertDictEqual(obj.to_dict(recursion=True), expected_dict)
301
+
302
+ def test_to_native(self) -> None:
303
+ obj = TestClass()
304
+ result = obj.to_native()
305
+ expected_dict = {'field1': 10, 'field2': None, 'field3': 3.0}
306
+ self.assertDictEqual(result, expected_dict)