py10x-universe 0.1.3__py3-none-any.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 (214) hide show
  1. core_10x/__init__.py +42 -0
  2. core_10x/backbone/__init__.py +0 -0
  3. core_10x/backbone/backbone_store.py +59 -0
  4. core_10x/backbone/backbone_traitable.py +30 -0
  5. core_10x/backbone/backbone_user.py +66 -0
  6. core_10x/backbone/bound_data_domain.py +49 -0
  7. core_10x/backbone/namespace.py +101 -0
  8. core_10x/backbone/vault.py +38 -0
  9. core_10x/code_samples/__init__.py +0 -0
  10. core_10x/code_samples/_package_manifest.py +3 -0
  11. core_10x/code_samples/directories.py +181 -0
  12. core_10x/code_samples/person.py +76 -0
  13. core_10x/concrete_traits.py +356 -0
  14. core_10x/conftest.py +12 -0
  15. core_10x/curve.py +321 -0
  16. core_10x/data_domain.py +48 -0
  17. core_10x/data_domain_binder.py +45 -0
  18. core_10x/directory.py +250 -0
  19. core_10x/entity.py +8 -0
  20. core_10x/entity_filter.py +5 -0
  21. core_10x/environment_variables.py +147 -0
  22. core_10x/exec_control.py +84 -0
  23. core_10x/experimental/__init__.py +0 -0
  24. core_10x/experimental/data_protocol_ex.py +34 -0
  25. core_10x/global_cache.py +121 -0
  26. core_10x/manual_tests/__init__.py +0 -0
  27. core_10x/manual_tests/calendar_test.py +35 -0
  28. core_10x/manual_tests/ctor_update_bug.py +58 -0
  29. core_10x/manual_tests/debug_graph_on.py +17 -0
  30. core_10x/manual_tests/debug_graphoff_inside_graph_on.py +28 -0
  31. core_10x/manual_tests/enum_bits_test.py +17 -0
  32. core_10x/manual_tests/env_vars_trivial_test.py +12 -0
  33. core_10x/manual_tests/existing_traitable.py +33 -0
  34. core_10x/manual_tests/k10x_test1.py +13 -0
  35. core_10x/manual_tests/named_constant_test.py +121 -0
  36. core_10x/manual_tests/nucleus_trivial_test.py +42 -0
  37. core_10x/manual_tests/polars_test.py +14 -0
  38. core_10x/manual_tests/py_class_test.py +4 -0
  39. core_10x/manual_tests/rc_test.py +42 -0
  40. core_10x/manual_tests/rdate_test.py +12 -0
  41. core_10x/manual_tests/reference_serialization_bug.py +19 -0
  42. core_10x/manual_tests/resource_trivial_test.py +10 -0
  43. core_10x/manual_tests/store_uri_test.py +6 -0
  44. core_10x/manual_tests/trait_definition_test.py +19 -0
  45. core_10x/manual_tests/trait_filter_test.py +15 -0
  46. core_10x/manual_tests/trait_flag_modification_test.py +42 -0
  47. core_10x/manual_tests/trait_modification_bug.py +26 -0
  48. core_10x/manual_tests/traitable_as_of_test.py +82 -0
  49. core_10x/manual_tests/traitable_heir_test.py +39 -0
  50. core_10x/manual_tests/traitable_history_test.py +41 -0
  51. core_10x/manual_tests/traitable_serialization_test.py +54 -0
  52. core_10x/manual_tests/traitable_trivial_test.py +71 -0
  53. core_10x/manual_tests/trivial_graph_test.py +16 -0
  54. core_10x/manual_tests/ts_class_association_test.py +64 -0
  55. core_10x/manual_tests/ts_trivial_test.py +35 -0
  56. core_10x/named_constant.py +425 -0
  57. core_10x/nucleus.py +81 -0
  58. core_10x/package_manifest.py +85 -0
  59. core_10x/package_refactoring.py +153 -0
  60. core_10x/py_class.py +431 -0
  61. core_10x/rc.py +155 -0
  62. core_10x/rdate.py +339 -0
  63. core_10x/resource.py +189 -0
  64. core_10x/roman_number.py +67 -0
  65. core_10x/testlib/__init__.py +0 -0
  66. core_10x/testlib/test_store.py +240 -0
  67. core_10x/testlib/traitable_history_tests.py +787 -0
  68. core_10x/testlib/ts_tests.py +280 -0
  69. core_10x/trait.py +377 -0
  70. core_10x/trait_definition.py +176 -0
  71. core_10x/trait_filter.py +205 -0
  72. core_10x/trait_method_error.py +36 -0
  73. core_10x/traitable.py +1082 -0
  74. core_10x/traitable_cli.py +153 -0
  75. core_10x/traitable_heir.py +33 -0
  76. core_10x/traitable_id.py +31 -0
  77. core_10x/ts_store.py +172 -0
  78. core_10x/ts_store_type.py +26 -0
  79. core_10x/ts_union.py +147 -0
  80. core_10x/ui_hint.py +153 -0
  81. core_10x/unit_tests/test_concrete_traits.py +156 -0
  82. core_10x/unit_tests/test_converters.py +51 -0
  83. core_10x/unit_tests/test_curve.py +157 -0
  84. core_10x/unit_tests/test_directory.py +54 -0
  85. core_10x/unit_tests/test_documentation.py +172 -0
  86. core_10x/unit_tests/test_environment_variables.py +15 -0
  87. core_10x/unit_tests/test_filters.py +239 -0
  88. core_10x/unit_tests/test_graph.py +348 -0
  89. core_10x/unit_tests/test_named_constant.py +98 -0
  90. core_10x/unit_tests/test_rc.py +11 -0
  91. core_10x/unit_tests/test_rdate.py +484 -0
  92. core_10x/unit_tests/test_trait_method_error.py +80 -0
  93. core_10x/unit_tests/test_trait_modification.py +19 -0
  94. core_10x/unit_tests/test_traitable.py +959 -0
  95. core_10x/unit_tests/test_traitable_history.py +1 -0
  96. core_10x/unit_tests/test_ts_store.py +1 -0
  97. core_10x/unit_tests/test_ts_union.py +369 -0
  98. core_10x/unit_tests/test_ui_nodes.py +81 -0
  99. core_10x/unit_tests/test_xxcalendar.py +471 -0
  100. core_10x/vault/__init__.py +0 -0
  101. core_10x/vault/sec_keys.py +133 -0
  102. core_10x/vault/security_keys_old.py +168 -0
  103. core_10x/vault/vault.py +56 -0
  104. core_10x/vault/vault_traitable.py +56 -0
  105. core_10x/vault/vault_user.py +70 -0
  106. core_10x/xdate_time.py +136 -0
  107. core_10x/xnone.py +71 -0
  108. core_10x/xxcalendar.py +228 -0
  109. infra_10x/__init__.py +0 -0
  110. infra_10x/manual_tests/__init__.py +0 -0
  111. infra_10x/manual_tests/test_misc.py +16 -0
  112. infra_10x/manual_tests/test_prepare_filter_and_pipeline.py +25 -0
  113. infra_10x/mongodb_admin.py +111 -0
  114. infra_10x/mongodb_store.py +346 -0
  115. infra_10x/mongodb_utils.py +129 -0
  116. infra_10x/unit_tests/conftest.py +13 -0
  117. infra_10x/unit_tests/test_mongo_db.py +36 -0
  118. infra_10x/unit_tests/test_mongo_history.py +1 -0
  119. py10x_universe-0.1.3.dist-info/METADATA +406 -0
  120. py10x_universe-0.1.3.dist-info/RECORD +214 -0
  121. py10x_universe-0.1.3.dist-info/WHEEL +4 -0
  122. py10x_universe-0.1.3.dist-info/licenses/LICENSE +21 -0
  123. ui_10x/__init__.py +0 -0
  124. ui_10x/apps/__init__.py +0 -0
  125. ui_10x/apps/collection_editor_app.py +100 -0
  126. ui_10x/choice.py +212 -0
  127. ui_10x/collection_editor.py +135 -0
  128. ui_10x/concrete_trait_widgets.py +220 -0
  129. ui_10x/conftest.py +8 -0
  130. ui_10x/entity_stocker.py +173 -0
  131. ui_10x/examples/__init__.py +0 -0
  132. ui_10x/examples/_guess_word_data.py +14076 -0
  133. ui_10x/examples/collection_editor.py +17 -0
  134. ui_10x/examples/date_selector.py +14 -0
  135. ui_10x/examples/entity_stocker.py +18 -0
  136. ui_10x/examples/guess_word.py +392 -0
  137. ui_10x/examples/message_box.py +20 -0
  138. ui_10x/examples/multi_choice.py +17 -0
  139. ui_10x/examples/py_data_browser.py +66 -0
  140. ui_10x/examples/radiobox.py +29 -0
  141. ui_10x/examples/single_choice.py +31 -0
  142. ui_10x/examples/style_sheet.py +47 -0
  143. ui_10x/examples/trivial_entity_editor.py +18 -0
  144. ui_10x/platform.py +20 -0
  145. ui_10x/platform_interface.py +517 -0
  146. ui_10x/py_data_browser.py +249 -0
  147. ui_10x/qt6/__init__.py +0 -0
  148. ui_10x/qt6/conftest.py +8 -0
  149. ui_10x/qt6/manual_tests/__init__.py +0 -0
  150. ui_10x/qt6/manual_tests/basic_test.py +35 -0
  151. ui_10x/qt6/platform_implementation.py +275 -0
  152. ui_10x/qt6/utils.py +665 -0
  153. ui_10x/rio/__init__.py +0 -0
  154. ui_10x/rio/apps/examples/examples/__init__.py +22 -0
  155. ui_10x/rio/apps/examples/examples/components/__init__.py +3 -0
  156. ui_10x/rio/apps/examples/examples/components/collection_editor.py +15 -0
  157. ui_10x/rio/apps/examples/examples/pages/collection_editor.py +21 -0
  158. ui_10x/rio/apps/examples/examples/pages/login_page.py +88 -0
  159. ui_10x/rio/apps/examples/examples/pages/style_sheet.py +21 -0
  160. ui_10x/rio/apps/examples/rio.toml +14 -0
  161. ui_10x/rio/component_builder.py +497 -0
  162. ui_10x/rio/components/__init__.py +9 -0
  163. ui_10x/rio/components/group_box.py +31 -0
  164. ui_10x/rio/components/labeled_checkbox.py +18 -0
  165. ui_10x/rio/components/line_edit.py +37 -0
  166. ui_10x/rio/components/radio_button.py +32 -0
  167. ui_10x/rio/components/separator.py +24 -0
  168. ui_10x/rio/components/splitter.py +121 -0
  169. ui_10x/rio/components/tree_view.py +75 -0
  170. ui_10x/rio/conftest.py +35 -0
  171. ui_10x/rio/internals/__init__.py +0 -0
  172. ui_10x/rio/internals/app.py +192 -0
  173. ui_10x/rio/manual_tests/__init__.py +0 -0
  174. ui_10x/rio/manual_tests/basic_test.py +24 -0
  175. ui_10x/rio/manual_tests/splitter.py +27 -0
  176. ui_10x/rio/platform_implementation.py +91 -0
  177. ui_10x/rio/style_sheet.py +53 -0
  178. ui_10x/rio/unit_tests/test_collection_editor.py +68 -0
  179. ui_10x/rio/unit_tests/test_internals.py +630 -0
  180. ui_10x/rio/unit_tests/test_style_sheet.py +37 -0
  181. ui_10x/rio/widgets/__init__.py +46 -0
  182. ui_10x/rio/widgets/application.py +109 -0
  183. ui_10x/rio/widgets/button.py +48 -0
  184. ui_10x/rio/widgets/button_group.py +60 -0
  185. ui_10x/rio/widgets/calendar.py +23 -0
  186. ui_10x/rio/widgets/checkbox.py +24 -0
  187. ui_10x/rio/widgets/dialog.py +137 -0
  188. ui_10x/rio/widgets/group_box.py +27 -0
  189. ui_10x/rio/widgets/layout.py +34 -0
  190. ui_10x/rio/widgets/line_edit.py +37 -0
  191. ui_10x/rio/widgets/list.py +105 -0
  192. ui_10x/rio/widgets/message_box.py +70 -0
  193. ui_10x/rio/widgets/scroll_area.py +31 -0
  194. ui_10x/rio/widgets/spacer.py +6 -0
  195. ui_10x/rio/widgets/splitter.py +45 -0
  196. ui_10x/rio/widgets/text_edit.py +28 -0
  197. ui_10x/rio/widgets/tree.py +89 -0
  198. ui_10x/rio/widgets/unit_tests/test_button.py +101 -0
  199. ui_10x/rio/widgets/unit_tests/test_button_group.py +33 -0
  200. ui_10x/rio/widgets/unit_tests/test_calendar.py +114 -0
  201. ui_10x/rio/widgets/unit_tests/test_checkbox.py +109 -0
  202. ui_10x/rio/widgets/unit_tests/test_group_box.py +158 -0
  203. ui_10x/rio/widgets/unit_tests/test_label.py +43 -0
  204. ui_10x/rio/widgets/unit_tests/test_line_edit.py +140 -0
  205. ui_10x/rio/widgets/unit_tests/test_list.py +146 -0
  206. ui_10x/table_header_view.py +305 -0
  207. ui_10x/table_view.py +174 -0
  208. ui_10x/trait_editor.py +189 -0
  209. ui_10x/trait_widget.py +131 -0
  210. ui_10x/traitable_editor.py +200 -0
  211. ui_10x/traitable_view.py +131 -0
  212. ui_10x/unit_tests/conftest.py +8 -0
  213. ui_10x/unit_tests/test_platform.py +9 -0
  214. ui_10x/utils.py +661 -0
@@ -0,0 +1,425 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ from core_10x.nucleus import Nucleus
6
+
7
+
8
+ # -- TODO: should I re-incarnate deriving from a metaclass, so that I can do: NAMED_CONSTANT[name] ?
9
+ class NamedConstant(Nucleus):
10
+ """
11
+ In a subclass, each line representing a member must be one of the following:
12
+ MEMBER_NAME = (label, value) #-- label, value
13
+ MEMBER_NAME = (label, ) #-- label, auto-value
14
+ MEMBER_NAME = () #-- MEMBER_NAME, auto-value
15
+ MEMBER_NAME = value #-- MEMBER_NAME, value
16
+
17
+ where:
18
+
19
+ MEMBER_NAME - a valid uppercase identifier
20
+ label - a string
21
+ value - any value
22
+ auto-value - automatically generated (int) value
23
+
24
+ NOTE: all the members must have either explicit or auto-generated values exclusively
25
+ """
26
+
27
+ __slots__ = 'label', 'name', 'value'
28
+
29
+ def __init__(self, name: str = '', label: str = '', value: Any = None):
30
+ super().__init__()
31
+ self.name = name
32
+ self.label = label
33
+ self.value = value
34
+
35
+ def __eq__(self, other):
36
+ return self.name == other.name
37
+
38
+ def __hash__(self):
39
+ return hash(self.name)
40
+
41
+ def __deepcopy__(self, memo=None):
42
+ return self
43
+
44
+ # -- Makes sense only for NamedConstants with Callable values
45
+ def __call__(self, *args, **kwargs):
46
+ return self.value(*args, **kwargs)
47
+
48
+ def is_member_by_name(self, other_class) -> bool:
49
+ return self.name in other_class.s_dir
50
+
51
+ @classmethod
52
+ def _create(cls, args: Any) -> NamedConstant:
53
+ cdef = cls()
54
+ if type(args) is not tuple: # -- just a value
55
+ cdef.value = args
56
+
57
+ else:
58
+ n = len(args)
59
+ if n == 0: # -- ()
60
+ pass
61
+
62
+ elif n == 1: # -- just a label
63
+ cdef.label = args[0]
64
+
65
+ elif n == 2: # -- (label, value)
66
+ cdef.label = args[0]
67
+ cdef.value = args[1]
68
+
69
+ else:
70
+ raise ValueError(f"'{args}' may have at most two items")
71
+
72
+ return cdef
73
+
74
+ #===================================================================================================================
75
+ # Nucleus Interface implementation
76
+ #===================================================================================================================
77
+
78
+ def to_str(self) -> str:
79
+ return f'{self.__class__.__name__}.{self.name}'
80
+
81
+ def to_id(self) -> str:
82
+ return self.name
83
+
84
+ def serialize(self, embed: bool) -> str:
85
+ return self.name
86
+
87
+ @classmethod
88
+ def deserialize(cls, name: str) -> NamedConstant:
89
+ sdir = cls.s_dir
90
+ cdef = sdir.get(name, sdir)
91
+ if cdef is sdir:
92
+ raise TypeError(f'{cls} - unknown constant {name}')
93
+
94
+ return cdef
95
+
96
+ @classmethod
97
+ def from_str(cls, s: str) -> NamedConstant:
98
+ return cls.s_dir.get(s)
99
+
100
+ @classmethod
101
+ def from_any_xstr(cls, data) -> NamedConstant | None:
102
+ if type(data) is cls.s_data_type:
103
+ reverse_dir = cls.s_reverse_dir
104
+ if reverse_dir:
105
+ return reverse_dir.get(data)
106
+
107
+ # -- the last resort - this is slow!
108
+ for cdef in cls.s_dir.values():
109
+ if cdef.value == data:
110
+ return cdef
111
+ return None
112
+
113
+ @classmethod
114
+ def same_values(cls, value1, value2) -> bool:
115
+ return value1 is value2
116
+
117
+ @classmethod
118
+ def choose_from(cls):
119
+ return cls.s_dir
120
+
121
+ # ===================================================================================================================
122
+
123
+ s_dir: dict[str, NamedConstant] = {}
124
+ s_reverse_dir = {}
125
+ s_data_type = None
126
+ s_default_labels = False
127
+ s_lowercase_values = False
128
+
129
+ # fmt: off
130
+ def __init_subclass__(
131
+ cls,
132
+ default_labels: bool = None, #-- if True and a label is not defined, creates it by calling default_label(name)
133
+ lowercase_values: bool = None, #-- if a value is not defined, sets it to name, or name.lower() if True
134
+ data_type: type = None, #-- if value is not defined it is taken from superclass or the first value
135
+ ):
136
+ # fmt: on
137
+ sdir = cls.s_dir = {name: cls(cdef.name, cdef.label, cdef.value) for name, cdef in cls.s_dir.items()}
138
+
139
+
140
+ if default_labels is not None:
141
+ cls.s_default_labels = default_labels
142
+ else:
143
+ default_labels = cls.s_default_labels
144
+
145
+ if lowercase_values is not None:
146
+ cls.s_lowercase_values = lowercase_values
147
+ else:
148
+ lowercase_values = cls.s_lowercase_values
149
+
150
+ if data_type is not None:
151
+ cls.s_data_type = data_type
152
+ else:
153
+ data_type = cls.s_data_type
154
+
155
+ for name, constant_definition in cls.__dict__.items():
156
+ if not name.isupper():
157
+ continue
158
+
159
+ cdef = cls._create(constant_definition)
160
+ cdef.name = name
161
+ if not cdef.label:
162
+ cdef.label = cls.default_label(name) if default_labels else name
163
+
164
+ if cdef.value is None:
165
+ value = cls.next_auto_value()
166
+ if value is None:
167
+ value = name if not lowercase_values else name.lower()
168
+ cdef.value = value
169
+
170
+ dt = type(cdef.value)
171
+ if data_type is None:
172
+ data_type = dt
173
+ else:
174
+ assert issubclass(dt, data_type), f'{cls}.{name} must be a subclass of {data_type}'
175
+
176
+ sdir[name] = cdef
177
+
178
+ cls.s_data_type = data_type
179
+ if getattr(data_type, '__hash__', None): #-- check if data_type is hashable and build the reverse dir if so
180
+ cls.s_reverse_dir = {cdef.value: cdef for cdef in sdir.values()}
181
+
182
+ for name, cdef in sdir.items():
183
+ setattr(cls, name, cdef)
184
+
185
+ @staticmethod
186
+ def union(*named_constant_classes):
187
+ class _union(NamedConstant):
188
+ pass
189
+ dir = _union.s_dir
190
+ for cls in named_constant_classes:
191
+ dir.update(cls.s_dir)
192
+
193
+ for name, value in dir.items():
194
+ setattr(_union, name, value)
195
+
196
+ return _union
197
+
198
+ @classmethod
199
+ def default_label(cls, name: str) -> str:
200
+ return name.title().replace('_', ' ')
201
+
202
+ @classmethod
203
+ def next_auto_value(cls):
204
+ return None
205
+
206
+ @classmethod
207
+ def item(cls, symbol_name: str) -> NamedConstant:
208
+ return cls.s_dir.get(symbol_name)
209
+
210
+ class Enum(NamedConstant):
211
+ """
212
+ Enum constants definitions are in a simplified form:
213
+ - an empty tuple (next enum auto value)
214
+ - a string - just a label
215
+ """
216
+
217
+ s_last_value = 0
218
+ s_step = 1
219
+
220
+ def __init_subclass__(cls, seed: int = None, step: int = None, **kwargs):
221
+ if seed is not None:
222
+ cls.s_last_value = seed
223
+ else:
224
+ cls.s_last_value = cls.s_last_value
225
+
226
+ if step is not None:
227
+ cls.s_step = step
228
+ else:
229
+ cls.s_step = cls.s_step
230
+
231
+ super().__init_subclass__(**kwargs)
232
+
233
+ def __int__(self):
234
+ return self.value
235
+
236
+ @classmethod
237
+ def _create(cls, args: Any) -> Enum:
238
+ cdef = cls()
239
+ if args == ():
240
+ return cdef
241
+
242
+ if type(args) is str: # -- just a label
243
+ cdef.label = args
244
+ return cdef
245
+
246
+ raise ValueError('an empty tuple or string is expected')
247
+
248
+ @classmethod
249
+ def next_auto_value(cls) -> int:
250
+ last_value = cls.s_last_value
251
+ cls.s_last_value += cls.s_step
252
+ return last_value
253
+
254
+
255
+ NO_FLAGS_TAG = 'NONE'
256
+
257
+
258
+ class EnumBits(NamedConstant):
259
+ s_last_flag = 0x1
260
+
261
+ def __init_subclass__(cls, **kwargs):
262
+ cls.s_last_flag = cls.s_last_flag
263
+ super().__init_subclass__(**kwargs)
264
+ setattr(cls, NO_FLAGS_TAG, cls(name=NO_FLAGS_TAG, value=0x0))
265
+
266
+ @classmethod
267
+ def next_auto_value(cls):
268
+ mask = cls.s_last_flag
269
+ cls.s_last_flag <<= 1
270
+ return mask
271
+
272
+ @classmethod
273
+ def names_from_value(cls, value: int) -> tuple:
274
+ return tuple(name for name, cdef in cls.s_dir.items() if cdef.value & value)
275
+
276
+ def __or__(self, other):
277
+ the_value = self.value
278
+ value = the_value | other.value
279
+ if value == the_value:
280
+ return self
281
+
282
+ cls = self.__class__
283
+ return cls.from_int(value)
284
+
285
+ def __and__(self, other):
286
+ the_value = self.value
287
+ value = the_value & other.value
288
+ if value == the_value:
289
+ return self
290
+
291
+ cls = self.__class__
292
+ return cls.from_int(value)
293
+
294
+ def __sub__(self, other):
295
+ the_value = self.value
296
+ value = the_value & ~other.value
297
+ if value == the_value:
298
+ return self
299
+
300
+ cls = self.__class__
301
+ return cls.from_int(value)
302
+
303
+ @classmethod
304
+ def names_to_value(cls, cnames: list) -> int:
305
+ value = 0x0
306
+ sdir = cls.s_dir
307
+ for cname in cnames:
308
+ cdef = sdir.get(cname)
309
+ if cdef is None:
310
+ raise TypeError(f'{cls} - unknown bit {cname}')
311
+
312
+ value |= cdef.value
313
+
314
+ return value
315
+
316
+ @classmethod
317
+ def from_str(cls, s: str) -> EnumBits:
318
+ if not s:
319
+ return getattr(cls, NO_FLAGS_TAG)
320
+
321
+ found = cls.s_dir.get(s)
322
+ if found is not None:
323
+ return found
324
+
325
+ cnames = s.split('|')
326
+ value = cls.names_to_value(cnames)
327
+ return cls(s, s, value)
328
+
329
+ @classmethod
330
+ def from_int(cls, value: int) -> EnumBits:
331
+ cnames = cls.names_from_value(value)
332
+ if not cnames:
333
+ return getattr(cls, NO_FLAGS_TAG)
334
+
335
+ name = '|'.join(cnames)
336
+ return cls(name, name, value)
337
+
338
+ @classmethod
339
+ def from_any_xstr(cls, data) -> EnumBits:
340
+ dt = type(data)
341
+ if dt is int:
342
+ return cls.from_int(data)
343
+
344
+ if dt is tuple or dt is list:
345
+ value = cls.names_to_value(data)
346
+ if not value:
347
+ return getattr(cls, NO_FLAGS_TAG)
348
+
349
+ name = '|'.join(data)
350
+ return cls(name, name, value)
351
+ return None
352
+
353
+ @classmethod
354
+ def deserialize(cls, data) -> EnumBits:
355
+ return cls.from_str(data)
356
+
357
+ @classmethod
358
+ def same_values(cls, value1, value2) -> bool:
359
+ return value1 is value2 or value1.name == value2.name
360
+
361
+
362
+ class ErrorCode(Enum, seed=-1, step=-1):
363
+ def __call__(self, *args, **kwargs):
364
+ return self.label.format(*args, **kwargs)
365
+
366
+
367
+ class NamedConstantValue:
368
+ __slots__ = 'data', 'named_constant_class'
369
+
370
+ def __init__(self, named_constant_class, **named_constant_values):
371
+ assert issubclass(named_constant_class, NamedConstant), f'{named_constant_class} must be a subclass of NamedConstant'
372
+ c_defs = named_constant_class.s_dir
373
+ num_values = len(c_defs)
374
+ assert num_values == len(named_constant_values), f'{named_constant_class} - number of named values must be {num_values}'
375
+ self.named_constant_class = named_constant_class
376
+
377
+ self.data = data = {}
378
+ for cname, value in named_constant_values.items():
379
+ cdef = c_defs.get(cname)
380
+ assert cdef, f'{named_constant_class}.{cname} - unknown named constant'
381
+ self.process_row(cdef, data, value)
382
+
383
+ def process_row(self, cdef: NamedConstant, data: dict, row):
384
+ data[cdef] = row
385
+
386
+ def __getitem__(self, key):
387
+ try:
388
+ return self.data[key] # -- if it's a known NamedConstant
389
+
390
+ except Exception as e:
391
+ # -- check if it is a name of a constant
392
+ named_constant_class = self.named_constant_class
393
+ cdef = named_constant_class.s_dir.get(key)
394
+ if not cdef:
395
+ raise KeyError(f'{named_constant_class}.{key} - unknown named constant') from e
396
+
397
+ return self.data[cdef]
398
+
399
+ def __setitem__(self, key, value):
400
+ raise AssertionError(f'{self.__class__} - may not be modified')
401
+
402
+ def __getattr__(self, key):
403
+ return self.__getitem__(key)
404
+
405
+
406
+ class NamedConstantTable(NamedConstantValue):
407
+ __slots__ = 'col_named_constant_class', 'data', 'named_constant_class'
408
+
409
+ def __init__(self, row_nc_class, col_nc_class, **named_tuple_values):
410
+ assert issubclass(col_nc_class, NamedConstant), f'{col_nc_class} must be a subclass of NamedConstant'
411
+ self.col_named_constant_class = col_nc_class
412
+ super().__init__(row_nc_class, **named_tuple_values)
413
+
414
+ def process_row(self, cdef: NamedConstant, data: dict, row):
415
+ assert type(row) is tuple, f'{cdef.name} = is not a tuple'
416
+ col_defs = self.col_named_constant_class.s_dir
417
+ assert len(row) == len(col_defs), f'{cdef.name} must have {len(col_defs)} values'
418
+ data[cdef] = NamedConstantValue(self.col_named_constant_class, **{col_name: row[i] for i, col_name in enumerate(col_defs)})
419
+
420
+ def primary_key(self, sec_key, value):
421
+ for primary_key, row in self.data.items():
422
+ if row[sec_key] == value:
423
+ return primary_key
424
+
425
+ return None
core_10x/nucleus.py ADDED
@@ -0,0 +1,81 @@
1
+ from __future__ import annotations
2
+
3
+ from py10x_core import BNucleus
4
+
5
+
6
+ class Nucleus:
7
+ # fmt: off
8
+ __slots__ = ()
9
+ TYPE_TAG = BNucleus.TYPE_TAG
10
+ CLASS_TAG = BNucleus.CLASS_TAG
11
+ REVISION_TAG = BNucleus.REVISION_TAG
12
+ OBJECT_TAG = BNucleus.OBJECT_TAG
13
+ COLLECTION_TAG = BNucleus.COLLECTION_TAG
14
+ ID_TAG = BNucleus.ID_TAG
15
+ NX_RECORD_TAG = BNucleus.NX_RECORD_TAG
16
+ TYPE_RECORD_TAG = BNucleus.TYPE_RECORD_TAG
17
+ PICKLE_RECORD_TAG = BNucleus.PICKLE_RECORD_TAG
18
+
19
+ serialize_any = BNucleus.serialize_any
20
+ deserialize_any = BNucleus.deserialize_any
21
+
22
+ serialize_type = BNucleus.serialize_type
23
+ deserialize_type = BNucleus.deserialize_type
24
+ serialize_complex = BNucleus.serialize_complex
25
+ deserialize_complex = BNucleus.deserialize_complex
26
+ serialize_date = BNucleus.serialize_date
27
+ deserialize_date = BNucleus.deserialize_date
28
+ serialize_list = BNucleus.serialize_list
29
+ deserialize_list = BNucleus.deserialize_list
30
+ serialize_dict = BNucleus.serialize_dict
31
+ deserialize_dict = BNucleus.deserialize_dict
32
+ deserialize_record = BNucleus.deserialize_record
33
+ # fmt: on
34
+ # ===============================================================================================================================
35
+ # The following methods must be implemented by a subclass of Nucleus
36
+ # ===============================================================================================================================
37
+
38
+ def __repr__(self):
39
+ return self.to_str()
40
+
41
+ def __eq__(self, other):
42
+ return self.__class__.same_values(self, other)
43
+
44
+ def to_str(self) -> str:
45
+ return str(self)
46
+
47
+ def to_id(self) -> str:
48
+ return self.to_str()
49
+
50
+ def serialize(self, embed: bool):
51
+ raise NotImplementedError
52
+
53
+ @classmethod
54
+ def deserialize(cls, serialized_data) -> Nucleus:
55
+ raise NotImplementedError
56
+
57
+ @classmethod
58
+ def from_str(cls, s: str) -> Nucleus:
59
+ raise NotImplementedError
60
+
61
+ @classmethod
62
+ def from_any_xstr(cls, value) -> Nucleus:
63
+ raise NotImplementedError
64
+
65
+ @classmethod
66
+ def from_any(cls, value) -> Nucleus:
67
+ if isinstance(value, cls):
68
+ return value
69
+
70
+ if isinstance(value, str):
71
+ return cls.from_str(value)
72
+
73
+ return cls.from_any_xstr(value)
74
+
75
+ @classmethod
76
+ def same_values(cls, value1, value2) -> bool:
77
+ raise NotImplementedError
78
+
79
+ @classmethod
80
+ def choose_from(cls):
81
+ return {}
@@ -0,0 +1,85 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from core_10x.data_domain import GeneralDomain
6
+ from core_10x.py_class import PyClass
7
+ from core_10x.resource import TS_STORE
8
+
9
+ if TYPE_CHECKING:
10
+ from core_10x.resource import ResourceRequirements
11
+
12
+
13
+ class PackageManifest:
14
+ """
15
+ To associate a subclass of Traitable to a particular Data Domain Category
16
+ it must have a record in a package manifest file.
17
+ Example:
18
+ # module x.etrading_domain
19
+ class ETradingDomain(DataDomain):
20
+ GENERAL = TS_STORE()
21
+ ORDERS = TS_STORE()
22
+ ALGO_ORDERS = TS_STORE()
23
+ ...
24
+
25
+ #module x.y.order
26
+ class Order(Traitable):
27
+ ...
28
+
29
+ class AlgoOrder(Order):
30
+ ...
31
+
32
+
33
+ #module x.y._package_manifest
34
+ from x.etrading_domain import ETradingDomain as ET
35
+
36
+ manifest = dict( #-- variable manifest: dict must be defined as follows
37
+ _category = ET.GENERAL, #-- default category for Traitables in x.y package, if any
38
+
39
+ order = dict( #-- specific association(s) for any module inside x.y package, if any
40
+ _category = ET.ORDERS #-- default category for Traitables in x.y.order, if any
41
+
42
+ AlgoOrder = ET.ALGO_ORDERS #-- specific association class x.y.order.AlgoOrder, if any
43
+ ...
44
+ ),
45
+ ...
46
+ )
47
+
48
+ If no association could be found for a subclass of Traitable, the default association will be used: GeneralDomain.GENERAL
49
+ """
50
+
51
+ # fmt: off
52
+ SYMBOL = '_package_manifest.manifest'
53
+ CATEGORY = '_category'
54
+ # fmt: on
55
+
56
+ @staticmethod
57
+ def _resource_requirements(cls) -> ResourceRequirements:
58
+ module = cls.__module__
59
+ parts = module.split('.')
60
+ if len(parts) < 2:
61
+ return None # -- should be at least package.module, so it's most probably '__main__.Class'
62
+
63
+ package = '.'.join(parts[:-1])
64
+ man_def: dict = PyClass.find_symbol(f'{package}.{PackageManifest.SYMBOL}')
65
+ if not man_def:
66
+ return None
67
+
68
+ short_module = parts[-1]
69
+ module_entry = man_def.get(short_module)
70
+ if module_entry:
71
+ rr: ResourceRequirements = module_entry.get(cls.__name__)
72
+ if not rr:
73
+ rr = module_entry.get(PackageManifest.CATEGORY)
74
+ if rr:
75
+ return rr
76
+
77
+ return man_def.get(PackageManifest.CATEGORY)
78
+
79
+ @staticmethod
80
+ def resource_requirements(cls) -> ResourceRequirements:
81
+ rr = PackageManifest._resource_requirements(cls) or GeneralDomain.GENERAL
82
+ assert rr.resource_type is TS_STORE, f'{cls} - invalid category in the _package_manifest'
83
+ return rr
84
+
85
+ # -- TODO: handle parent classes, if ResourceRequirements for the class in not found