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,48 @@
1
+ import re
2
+
3
+ from core_10x.resource import TS_STORE, ResourceRequirements
4
+
5
+
6
+ def _raise_type_error(cls, **kwargs):
7
+ raise TypeError(f'{cls} - subclassing is not allowed')
8
+
9
+
10
+ class DataDomain:
11
+ s_dir = {}
12
+
13
+ s_resource_requirements = {}
14
+
15
+ def __init_subclass__(cls, **kwargs):
16
+ name = cls.name()
17
+ ed = DataDomain.s_dir.get(name)
18
+ assert ed is None, f"DataDomain '{name}' is already registered in {ed}"
19
+ DataDomain.s_dir[name] = cls
20
+
21
+ cls.__init_subclass__ = lambda **kwargs: _raise_type_error(cls, **kwargs)
22
+ category: str
23
+ rrs = cls.s_resource_requirements
24
+ for category, resource_reqs in cls.__dict__.items():
25
+ if isinstance(resource_reqs, ResourceRequirements):
26
+ assert category.isupper(), f"Category '{category}' must be an uppercase name"
27
+ resource_reqs.domain = cls
28
+ resource_reqs.category = category
29
+ rrs[category] = resource_reqs
30
+
31
+ assert rrs, f"DataDomain '{cls} must define at least one category"
32
+
33
+ @classmethod
34
+ def name(cls: str) -> str:
35
+ return re.sub(r'([a-z])([A-Z])', r'\1_\2', cls.__qualname__).upper()
36
+
37
+ @classmethod
38
+ def resource_requirement(cls, category: str, throw: bool = True) -> ResourceRequirements:
39
+ rr = cls.s_resource_requirements.get(category)
40
+ if rr is None and throw:
41
+ raise ValueError(f"DataDomain {cls} - unknown category '{category}'")
42
+
43
+ return rr
44
+
45
+
46
+ class GeneralDomain(DataDomain):
47
+ GENERAL = TS_STORE()
48
+ ...
@@ -0,0 +1,45 @@
1
+ from core_10x.environment_variables import EnvVars
2
+ from core_10x.global_cache import cache
3
+ from core_10x.py_class import PyClass
4
+
5
+
6
+ # ===================================================================================================================================
7
+ # Data Domain Bindings
8
+ #
9
+ # from core_10x.data_domain import GeneralDomain
10
+ # from xxx.yyy.mdu_domain import MDU
11
+ # ...
12
+ # DATA_DOMAIN_BINDINGS = dict(
13
+ # dev = {
14
+ # GeneralDomain: dict(
15
+ # GENERAL = R(TS_STORE.MONGO_DB, hostname = 'dev.mongo.general.io', tsl = True, ...),
16
+ # ),
17
+ #
18
+ # MDU: dict(
19
+ # SYMBOLOGY = R(REL_DB.ORACLE_DB, hostname = 'dev.oracle.io', a = '...', b = '...'),
20
+ # MKT_CLOSE_CLUSTER = R(CLOUD_CLUSTER.RAY_CLUSTER, hostname = 'dev.ray1.io', ...),
21
+ # ),
22
+ # },
23
+ #
24
+ # prod = {
25
+ # GeneralDomain: dict(
26
+ # GENERAL = R(TS_STORE.MONGO_DB, hostname = 'prod.mongo.general.io', tsl = True, ...),
27
+ # ),
28
+ #
29
+ # MDU: dict(
30
+ # SYMBOLOGY = R(REL_DB.ORACLE_DB, hostname = 'prod.oracle.io', a = '...', b = '...'),
31
+ # MKT_CLOSE_CLUSTER = R(CLOUD_CLUSTER.RAY_CLUSTER, hostname = 'prod.ray2.io', ...),
32
+ # ),
33
+ # },
34
+ #
35
+ # )
36
+ # ===================================================================================================================================
37
+ class DataDomainBinder:
38
+ @staticmethod
39
+ @cache
40
+ def all_bindings() -> dict:
41
+ dd_bindings_symbol = EnvVars.data_domain_bindings
42
+ if not dd_bindings_symbol:
43
+ return None
44
+
45
+ return PyClass.find_symbol(dd_bindings_symbol)
core_10x/directory.py ADDED
@@ -0,0 +1,250 @@
1
+ from __future__ import annotations
2
+
3
+ import inspect
4
+ from typing import Any
5
+
6
+ from core_10x.entity import Entity
7
+ from core_10x.py_class import PyClass
8
+ from core_10x.xnone import XNone
9
+
10
+
11
+ class Directory:
12
+ @staticmethod
13
+ def _dir_class(value):
14
+ if isinstance(value, Entity):
15
+ return DxEntity
16
+
17
+ if inspect.isclass(value) and issubclass(value, Entity):
18
+ return DxClass
19
+
20
+ return Directory
21
+
22
+ @staticmethod
23
+ def instance(value: Any = None, **kwargs) -> Directory:
24
+ dir_class = Directory._dir_class(value)
25
+ return dir_class(value=value, **kwargs)
26
+
27
+ # fmt: off
28
+ def __init__(
29
+ self,
30
+ name: str = '',
31
+ value = None,
32
+ members: dict = None,
33
+ parent: Directory = None
34
+ ):
35
+ # fmt: on
36
+ self.check_dir_value(value)
37
+
38
+ self.name = name
39
+ self.value = value
40
+ self.members = members or {}
41
+ self.parent = parent
42
+
43
+ @classmethod
44
+ def check_dir_value(cls, value):
45
+ f = getattr(value, '__hash__', None)
46
+ assert f, f'Directory value must be hashable ({value})'
47
+
48
+ def show_value(self) -> str:
49
+ return str(self.value) if self.value else self.name
50
+
51
+ def is_leaf(self) -> bool:
52
+ return not self.members
53
+
54
+ def subdirs(self) -> dict:
55
+ return self.members
56
+
57
+ def _add_subdir(self, subdir: Directory):
58
+ self.members[subdir.value] = subdir
59
+ subdir.parent = self
60
+
61
+ def _get_or_add_subdir(self, value, **subdir_values):
62
+ subdir = self.members.get(value)
63
+ if subdir is None:
64
+ subdir = Directory.instance(value, **subdir_values)
65
+ subdir.parent = self
66
+ self.members[value] = subdir
67
+
68
+ return subdir
69
+
70
+ def insert(self, value, *path, **subdir_values):
71
+ if not path:
72
+ self._get_or_add_subdir(value, **subdir_values)
73
+ else:
74
+ p_value = path[0]
75
+ subdir = self._get_or_add_subdir(p_value)
76
+ subdir.insert(value, *path[1:], **subdir_values)
77
+
78
+ def insert_many(self, values: list, **subdir_values):
79
+ for value in values:
80
+ self._get_or_add_subdir(value, **subdir_values)
81
+
82
+ def subdir_at(self, *path) -> Directory:
83
+ if not path:
84
+ return self
85
+
86
+ subdir = self.members.get(path[0])
87
+ return subdir.subdir_at(*path[1:]) if subdir else None
88
+
89
+ def remove(self, value, *path) -> bool:
90
+ subdir = self.subdir_at(*path)
91
+ if not subdir:
92
+ return False
93
+
94
+ return self.members.pop(value, XNone) is not XNone
95
+
96
+ def remove_everywhere(self, value):
97
+ self.remove(value)
98
+ for subdir in self.members.values():
99
+ subdir.remove(value)
100
+
101
+ def _find_paths(self, value, paths_found: list, *current_path):
102
+ found = self.members.get(value)
103
+ if found:
104
+ paths_found.append((*current_path, value))
105
+
106
+ for sub_value, subdir in self.members.items():
107
+ subdir._find_paths(value, paths_found, *current_path, sub_value)
108
+
109
+ def find_paths(self, value) -> list:
110
+ paths_found = [()] if value == self.value else []
111
+ self._find_paths(value, paths_found)
112
+ return paths_found
113
+
114
+ def _flatten(self, res: dict, *current_path):
115
+ path = *current_path, self.value
116
+ label = self.name
117
+ if not label:
118
+ label = self.show_value()
119
+ res[path] = label
120
+ for subdir in self.members.values():
121
+ subdir._flatten(res, *path)
122
+
123
+ def flatten(self, with_root: bool = False) -> dict:
124
+ res = {}
125
+ if with_root:
126
+ self._flatten(res)
127
+ else:
128
+ for subdir in self.members.values():
129
+ subdir._flatten(res)
130
+
131
+ return res
132
+
133
+ def choices(self, with_root: bool = False, path_delimiter: str = '/') -> dict:
134
+ f = self.flatten(with_root = with_root)
135
+ v_n_map = { path[-1]: name for path, name in f.items() }
136
+ res = {}
137
+ cr = 1
138
+ for path in f.keys():
139
+ label = path_delimiter.join(v_n_map[p] for p in path)
140
+ value = path[-1]
141
+ already_in = res.get(label)
142
+ if already_in:
143
+ if already_in == value:
144
+ continue
145
+
146
+ label = f'{label}({cr})'
147
+ cr += 1
148
+
149
+ res[label] = value
150
+
151
+ return res
152
+
153
+ def contains(self, value) -> bool:
154
+ if self.value == value:
155
+ return True
156
+
157
+ for subdir in self.members.values():
158
+ if subdir.contains(value):
159
+ return True
160
+
161
+ return False
162
+
163
+ def is_value_contained(self, value, by_other_value) -> bool:
164
+ if self.value == by_other_value:
165
+ return self.contains(value)
166
+
167
+ for subdir in self.members.values():
168
+ if subdir.is_value_contained(value, by_other_value):
169
+ return True
170
+
171
+ return False
172
+
173
+ def _collect_leaf_values(self, res: set, data_accessor):
174
+ if self.is_leaf():
175
+ res.add(data_accessor(self.value))
176
+ else:
177
+ for subdir in self.members.values():
178
+ subdir._collect_leaf_values(res, data_accessor)
179
+
180
+ def leaf_values(self, data_accessor): #-- data_accessor: callable(leaf_value)
181
+ res = set()
182
+ self._collect_leaf_values(res, data_accessor)
183
+ return list(res)
184
+
185
+ @classmethod
186
+ def define(cls, value_name, members: list) -> Directory:
187
+ if isinstance(value_name, tuple): #-- ( value, name ) is given
188
+ assert len(value_name) == 2, 'a pair of ( value, name ) is expected'
189
+ value, name = value_name
190
+
191
+ else: #-- just a value
192
+ value = value_name
193
+ name = None
194
+
195
+ dir = Directory.instance(value, name = name)
196
+
197
+ sub_value_name = None
198
+ for elem in members:
199
+ if not sub_value_name:
200
+ sub_value_name = elem
201
+ continue
202
+
203
+ if isinstance(elem, list): #-- sub dirs are given
204
+ sudir = cls.define(sub_value_name, elem)
205
+ dir._add_subdir(sudir)
206
+ sub_value_name = None
207
+
208
+ else: #-- no sub dirs are given, just value_name
209
+ sudir = cls.define(sub_value_name, [])
210
+ dir._add_subdir(sudir)
211
+ sub_value_name = elem
212
+
213
+ if sub_value_name:
214
+ sudir = cls.define(sub_value_name, [])
215
+ dir._add_subdir(sudir)
216
+
217
+ return dir
218
+
219
+
220
+ class DxEntity(Directory):
221
+ def __init__(self, **kwargs):
222
+ super().__init__(**kwargs)
223
+ self.value: Entity
224
+ self.name = self.value.id()
225
+
226
+ @classmethod
227
+ def check_dir_value(cls, value):
228
+ assert isinstance(value, Entity), f'entity is expected ({value})'
229
+
230
+ def show_value(self) -> str:
231
+ return self.value.id() # -- TODO: id_repr()
232
+
233
+
234
+ class DxClass(Directory):
235
+ def __init__(self, **kwargs):
236
+ super().__init__(**kwargs)
237
+ cls = self.value
238
+ self.name = PyClass.name(cls) if cls else ''
239
+
240
+ @classmethod
241
+ def check_dir_value(cls, value):
242
+ assert inspect.isclass(value) and issubclass(value, Entity), f'subclass of Entity is expected ({value})'
243
+
244
+ # def matching_entities(self) -> dict:
245
+ # """
246
+ # Applicable for an entity class with a "reasonable" number of entities in the collection
247
+ # TODO: need to provide a different mechanism (a view) for huge collections
248
+ # """
249
+ # cls = self.value
250
+ # return { e.id(): e for e in cls.sharedInstances( _cache = self.cache_only(), **self.filters() ) }
core_10x/entity.py ADDED
@@ -0,0 +1,8 @@
1
+ from core_10x.rc import RC, RC_TRUE
2
+ from core_10x.trait import Trait
3
+ from core_10x.trait_definition import RT, M, T, Ui
4
+ from core_10x.traitable import Traitable
5
+
6
+
7
+ # -- A higher-level Traitable to be used for general purposes
8
+ class Entity(Traitable): ...
@@ -0,0 +1,5 @@
1
+ from core_10x.traitable import T, Traitable
2
+
3
+
4
+ class TraitFilter(Traitable):
5
+ trait_name: str = T()
@@ -0,0 +1,147 @@
1
+ import ast
2
+ import os
3
+
4
+ from py10x_core import OsUser
5
+
6
+ from core_10x.global_cache import cache
7
+ from core_10x.rc import RC
8
+ from core_10x.xdate_time import XDateTime, date, datetime
9
+ from core_10x.resource import Resource
10
+
11
+ # ===================================================================================================================================
12
+ # date_format: str = default_value
13
+ #
14
+ # def date_format_apply(cls, fmt: str):
15
+ # XDateTime.set_default_format(fmt)
16
+ #
17
+ # datetime_format: str
18
+ #
19
+ # def datetime_format_get(cls):
20
+ # return f'{cls.date_format} %H:%M%S'
21
+ #
22
+ # def datetime_format_apply(cls, value):
23
+ # ...
24
+ # ===================================================================================================================================
25
+
26
+
27
+ class classproperty(property):
28
+ def __get__(self, obj, objtype: type = None):
29
+ return self.fget(objtype)
30
+
31
+
32
+ class _EnvVars:
33
+ # fmt: off
34
+ s_converters = {
35
+ bool: lambda s: ast.literal_eval(s.lower().capitalize()),
36
+ int: lambda s: ast.literal_eval(s),
37
+ float: lambda s: ast.literal_eval(s),
38
+ str: lambda s: s,
39
+ date: lambda s: XDateTime.str_to_date(s),
40
+ datetime: lambda s: XDateTime.str_to_datetime(s),
41
+ #Resource: lambda s: Resource
42
+ }
43
+ # fmt: on
44
+
45
+ @classmethod
46
+ def _getter(cls, data_type, var_name: str, f_get, f_apply):
47
+ # print(var_name)
48
+ str_value = os.getenv(var_name)
49
+ if str_value is not None:
50
+ f_convert = cls.s_converters.get(data_type)
51
+ assert f_convert, f'Unknown data type {data_type}'
52
+ try:
53
+ value = f_convert(str_value)
54
+ except Exception as e:
55
+ raise TypeError(f'Variable {var_name} - could not convert {str_value} to {data_type}') from e
56
+ else:
57
+ try:
58
+ value = f_get(cls)
59
+ except Exception as e:
60
+ rc = RC(False) # -- capture the exc
61
+ raise RuntimeError(f'{cls}.{var_name} - failed while getting a value\n{rc.error()}') from e
62
+
63
+ if f_apply:
64
+ try:
65
+ f_apply.__get__(cls)(value)
66
+ except Exception as e:
67
+ rc = RC(False) # -- capture the exc
68
+ raise ValueError(f'{cls}.{var_name} - failed while applying value: {value}\n{rc.error()}') from e
69
+
70
+ return value
71
+
72
+ @classmethod
73
+ def full_getter(cls, data_type, var_name: str, f_get, f_apply):
74
+ f = lambda cls: cls._getter(data_type, var_name, f_get, f_apply)
75
+ # return classmethod(cache(f))
76
+ return cache(f)
77
+
78
+ s_env_name: str = None
79
+ assert_var = None
80
+
81
+ def __init_subclass__(cls, env_name: str = None, **kwargs):
82
+ assert env_name, 'env_name is required'
83
+
84
+ cls.s_env_name = env_name
85
+ annotations = cls.__annotations__
86
+ assert annotations, 'No variables are defined'
87
+
88
+ cls_dict = cls.__dict__
89
+ for name, data_type in annotations.items():
90
+ def_value = cls_dict.get(name)
91
+ if def_value is None: # -- no default value, let's locate the getter
92
+ f_get_name = f'{name}_get'
93
+ f_get = cls_dict.get(f_get_name)
94
+ assert f_get, f'Variable {name} must define either a default value or a getter {f_get_name}(cls)'
95
+ # -- TODO: check signature: f_get(cls)
96
+ else:
97
+ f_get = lambda cls, def_value=def_value: def_value
98
+
99
+ f_apply_name = f'{name}_apply'
100
+ f_apply = cls_dict.get(f_apply_name) # -- f(cls, value)
101
+
102
+ var_name = f'{env_name}_{name.upper()}'
103
+ full_getter = cls.full_getter(data_type, var_name, f_get, f_apply)
104
+ setattr(cls, name, classproperty(full_getter))
105
+
106
+ cls.assert_var = cls.AssertVar(cls)
107
+
108
+ class AssertVar:
109
+ def __init__(self, env_vars_class):
110
+ self.env_vars_class = env_vars_class
111
+
112
+ def __getattr__(self, item):
113
+ value = getattr(self.env_vars_class, item)
114
+ if not value:
115
+ raise AssertionError(f'{self.env_vars_class.s_env_name}_{item.upper()} is not defined')
116
+ return value
117
+
118
+
119
+ class EnvVars(_EnvVars, env_name='XX'):
120
+ # fmt: off
121
+ build_area: str
122
+ parent_build_area: str = 'dev'
123
+
124
+ master_password_key: str = 'XX_MASTER_PASSWORD'
125
+
126
+ examples_ts_store_uri: str = '' #-- e.g., mongodb://localhost/examples
127
+ vault_ts_store_uri: str = '' #-- if defined, used to store/auto retrieve security credentials for each user/resource
128
+ main_ts_store_uri: str = '' #-- e.g., 'mongodb://localhost:27018/main'
129
+ use_ts_store_per_class: bool = True #-- use TsStore per Traitable class associations
130
+ functional_account_prefix: str = 'xx' #-- used in user names to distinguish a regular user name from a functional account
131
+
132
+ date_format: str = XDateTime.FORMAT_ISO
133
+
134
+ sdlc_area: str
135
+ # fmt: on
136
+
137
+ def build_area_get(self) -> str:
138
+ return OsUser.me.name()
139
+
140
+ @classmethod
141
+ def date_format_apply(cls, value):
142
+ XDateTime.set_default_format(value)
143
+
144
+ def sdlc_area_get(self) -> str:
145
+ ba = self.build_area
146
+ pba = self.parent_build_area
147
+ return f'{ba}/{pba}' if pba else ba
@@ -0,0 +1,84 @@
1
+ from py10x_core import BProcessContext
2
+ from py10x_core import BTraitableProcessor as BTP # noqa: N817
3
+
4
+ # TODO: rename DEBUG to TYPE_CHECK?
5
+ # TODO: make CONVERT/DEBUG mode default?
6
+
7
+
8
+ def CHANGE_MODE(debug: bool = -1, convert_values: bool = -1): # noqa: N802
9
+ return BTP.create(-1, convert_values, debug, True, False)
10
+
11
+
12
+ def DEFAULT_CACHE(debug: bool = -1, convert_values: bool = -1): # noqa: N802
13
+ return BTP.create(0, convert_values, debug, False, True)
14
+
15
+
16
+ def GRAPH_ON(debug: bool = -1, convert_values: bool = -1): # noqa: N802
17
+ return BTP.create(1, convert_values, debug, False, False)
18
+
19
+
20
+ def GRAPH_OFF(debug: bool = -1, convert_values: bool = -1): # noqa: N802
21
+ return BTP.create(0, convert_values, debug, False, False)
22
+
23
+
24
+ def DEBUG_ON(convert_values: bool = -1): # noqa: N802
25
+ return BTP.create(-1, convert_values, 1, True, False)
26
+
27
+
28
+ def DEBUG_OFF(convert_values: bool = -1): # noqa: N802
29
+ return BTP.create(-1, convert_values, 0, True, False)
30
+
31
+
32
+ def CONVERT_VALUES_ON(debug: bool = -1): # noqa: N802
33
+ return BTP.create(-1, 1, debug, True, False)
34
+
35
+
36
+ def CONVERT_VALUES_OFF(debug: bool = -1): # noqa: N802
37
+ return BTP.create(-1, 0, debug, True, False)
38
+
39
+
40
+ def INTERACTIVE(): # noqa: N802
41
+ return BTP.create_interactive()
42
+
43
+
44
+ # noinspection PyMethodOverriding
45
+ class ProcessContext(BProcessContext):
46
+ @staticmethod
47
+ def set_flags(flags: int) -> int:
48
+ old_flags = BProcessContext.BPC.flags()
49
+ BProcessContext.BPC.set_flags(flags)
50
+ return old_flags
51
+
52
+ @staticmethod
53
+ def reset_flags(flags: int) -> int:
54
+ old_flags = BProcessContext.BPC.flags()
55
+ BProcessContext.BPC.reset_flags(flags)
56
+ return old_flags
57
+
58
+ @staticmethod
59
+ def replace_flags(flags: int) -> int:
60
+ old_flags = BProcessContext.BPC.flags()
61
+ BProcessContext.BPC.replace_flags(flags)
62
+ return old_flags
63
+
64
+ @staticmethod
65
+ def flags() -> int:
66
+ return BProcessContext.BPC.flags()
67
+
68
+
69
+ class FlagsContext:
70
+ s_default_flags = 0
71
+
72
+ def __init__(self, flags=None):
73
+ self._flags = flags if flags is not None else self.s_default_flags
74
+
75
+ def __enter__(self):
76
+ self._old_flags = ProcessContext.set_flags(self._flags)
77
+ return self
78
+
79
+ def __exit__(self, exc_type, exc_val, exc_tb):
80
+ ProcessContext.BPC.replace_flags(self._old_flags)
81
+
82
+
83
+ class CACHE_ONLY(FlagsContext):
84
+ s_default_flags = ProcessContext.CACHE_ONLY
File without changes
@@ -0,0 +1,34 @@
1
+ import functools
2
+
3
+
4
+ class T:
5
+ def __init__(self, name, get, *args):
6
+ self.name = name
7
+ self.get = get
8
+ self.args = args
9
+
10
+ def __get__(self, instance, owner):
11
+ if not self.args:
12
+ return self.get(instance)
13
+
14
+ return functools.partial(self.get, self)
15
+
16
+ class E:
17
+ def __init__(self, fn, ln):
18
+ self.fn = fn
19
+ self.ln = ln
20
+
21
+ def full_name(self):
22
+ return f'{self.ln}, {self.fn}'
23
+
24
+ def w(self, q):
25
+ return q * 10
26
+
27
+ name = T('name', full_name )
28
+ weight = T('weight', w, 10 )
29
+
30
+ if __name__ == '__main__':
31
+ e = E('Sasha', 'Davidovich')
32
+
33
+ print(e.name)
34
+ print(e.weight(5))