PyDecisionGraph 0.3.2.post1__cp315-cp315t-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 (148) hide show
  1. decision_graph/__infra__.pxd +1 -0
  2. decision_graph/__init__.pxd +1 -0
  3. decision_graph/__init__.py +39 -0
  4. decision_graph/decision_tree/__init__.pxd +2 -0
  5. decision_graph/decision_tree/__init__.py +85 -0
  6. decision_graph/decision_tree/bake/__infra__.pxd +502 -0
  7. decision_graph/decision_tree/bake/__init__.pxd +502 -0
  8. decision_graph/decision_tree/bake/__init__.py +29 -0
  9. decision_graph/decision_tree/bake/c_action.cp315t-win_amd64.pyd +0 -0
  10. decision_graph/decision_tree/bake/c_action.h +324 -0
  11. decision_graph/decision_tree/bake/c_action.pxd +54 -0
  12. decision_graph/decision_tree/bake/c_action.pyi +126 -0
  13. decision_graph/decision_tree/bake/c_action.pyx +65 -0
  14. decision_graph/decision_tree/bake/c_allocator_protocol.cp315t-win_amd64.pyd +0 -0
  15. decision_graph/decision_tree/bake/c_allocator_protocol.pxd +24 -0
  16. decision_graph/decision_tree/bake/c_allocator_protocol.pyi +61 -0
  17. decision_graph/decision_tree/bake/c_allocator_protocol.pyx +109 -0
  18. decision_graph/decision_tree/bake/c_bake.cp315t-win_amd64.pyd +0 -0
  19. decision_graph/decision_tree/bake/c_bake.h +629 -0
  20. decision_graph/decision_tree/bake/c_bake.pxd +52 -0
  21. decision_graph/decision_tree/bake/c_bake.pyi +151 -0
  22. decision_graph/decision_tree/bake/c_bake.pyx +142 -0
  23. decision_graph/decision_tree/bake/c_collections.cp315t-win_amd64.pyd +0 -0
  24. decision_graph/decision_tree/bake/c_collections.h +692 -0
  25. decision_graph/decision_tree/bake/c_collections.pxd +52 -0
  26. decision_graph/decision_tree/bake/c_collections.pyi +193 -0
  27. decision_graph/decision_tree/bake/c_collections.pyx +161 -0
  28. decision_graph/decision_tree/bake/c_const.cp315t-win_amd64.pyd +0 -0
  29. decision_graph/decision_tree/bake/c_const.h +395 -0
  30. decision_graph/decision_tree/bake/c_const.pxd +56 -0
  31. decision_graph/decision_tree/bake/c_const.pyi +305 -0
  32. decision_graph/decision_tree/bake/c_const.pyx +278 -0
  33. decision_graph/decision_tree/bake/c_edge.cp315t-win_amd64.pyd +0 -0
  34. decision_graph/decision_tree/bake/c_edge.h +511 -0
  35. decision_graph/decision_tree/bake/c_edge.pxd +117 -0
  36. decision_graph/decision_tree/bake/c_edge.pyi +192 -0
  37. decision_graph/decision_tree/bake/c_edge.pyx +270 -0
  38. decision_graph/decision_tree/bake/c_eval.h +848 -0
  39. decision_graph/decision_tree/bake/c_eval.pxd +40 -0
  40. decision_graph/decision_tree/bake/c_expr.cp315t-win_amd64.pyd +0 -0
  41. decision_graph/decision_tree/bake/c_expr.h +1900 -0
  42. decision_graph/decision_tree/bake/c_expr.pxd +129 -0
  43. decision_graph/decision_tree/bake/c_expr.pyi +280 -0
  44. decision_graph/decision_tree/bake/c_expr.pyx +272 -0
  45. decision_graph/decision_tree/bake/c_hierarchy.cp315t-win_amd64.pyd +0 -0
  46. decision_graph/decision_tree/bake/c_hierarchy.h +731 -0
  47. decision_graph/decision_tree/bake/c_hierarchy.pxd +71 -0
  48. decision_graph/decision_tree/bake/c_hierarchy.pyi +409 -0
  49. decision_graph/decision_tree/bake/c_hierarchy.pyx +277 -0
  50. decision_graph/decision_tree/bake/c_logic_group.cp315t-win_amd64.pyd +0 -0
  51. decision_graph/decision_tree/bake/c_logic_group.h +1226 -0
  52. decision_graph/decision_tree/bake/c_logic_group.pxd +162 -0
  53. decision_graph/decision_tree/bake/c_logic_group.pyi +264 -0
  54. decision_graph/decision_tree/bake/c_logic_group.pyx +308 -0
  55. decision_graph/decision_tree/bake/c_node.cp315t-win_amd64.pyd +0 -0
  56. decision_graph/decision_tree/bake/c_node.h +2660 -0
  57. decision_graph/decision_tree/bake/c_node.pxd +381 -0
  58. decision_graph/decision_tree/bake/c_node.pyi +438 -0
  59. decision_graph/decision_tree/bake/c_node.pyx +639 -0
  60. decision_graph/decision_tree/bake/c_reconstruct.cp315t-win_amd64.pyd +0 -0
  61. decision_graph/decision_tree/bake/c_reconstruct.pxd +63 -0
  62. decision_graph/decision_tree/bake/c_reconstruct.pyi +60 -0
  63. decision_graph/decision_tree/bake/c_reconstruct.pyx +252 -0
  64. decision_graph/decision_tree/bake/c_var.cp315t-win_amd64.pyd +0 -0
  65. decision_graph/decision_tree/bake/c_var.h +2054 -0
  66. decision_graph/decision_tree/bake/c_var.pxd +205 -0
  67. decision_graph/decision_tree/bake/c_var.pyi +271 -0
  68. decision_graph/decision_tree/bake/c_var.pyx +228 -0
  69. decision_graph/decision_tree/capi/__infra__.pxd +33 -0
  70. decision_graph/decision_tree/capi/__init__.pxd +33 -0
  71. decision_graph/decision_tree/capi/__init__.py +57 -0
  72. decision_graph/decision_tree/capi/c_abc.cp315t-win_amd64.pyd +0 -0
  73. decision_graph/decision_tree/capi/c_abc.pxd +246 -0
  74. decision_graph/decision_tree/capi/c_abc.pyi +770 -0
  75. decision_graph/decision_tree/capi/c_abc.pyx +1532 -0
  76. decision_graph/decision_tree/capi/c_collection.cp315t-win_amd64.pyd +0 -0
  77. decision_graph/decision_tree/capi/c_collection.pxd +22 -0
  78. decision_graph/decision_tree/capi/c_collection.pyi +245 -0
  79. decision_graph/decision_tree/capi/c_collection.pyx +138 -0
  80. decision_graph/decision_tree/capi/c_node.cp315t-win_amd64.pyd +0 -0
  81. decision_graph/decision_tree/capi/c_node.pxd +95 -0
  82. decision_graph/decision_tree/capi/c_node.pyi +492 -0
  83. decision_graph/decision_tree/capi/c_node.pyx +551 -0
  84. decision_graph/decision_tree/exc.py +189 -0
  85. decision_graph/decision_tree/native/__init__.py +57 -0
  86. decision_graph/decision_tree/native/abc.py +1167 -0
  87. decision_graph/decision_tree/native/collection.py +134 -0
  88. decision_graph/decision_tree/native/node.py +521 -0
  89. decision_graph/includes/decision_graph/decision_tree/bake/c_action.c +16320 -0
  90. decision_graph/includes/decision_graph/decision_tree/bake/c_action.h +324 -0
  91. decision_graph/includes/decision_graph/decision_tree/bake/c_allocator_protocol.c +12473 -0
  92. decision_graph/includes/decision_graph/decision_tree/bake/c_bake.c +16485 -0
  93. decision_graph/includes/decision_graph/decision_tree/bake/c_bake.h +629 -0
  94. decision_graph/includes/decision_graph/decision_tree/bake/c_collections.c +17381 -0
  95. decision_graph/includes/decision_graph/decision_tree/bake/c_collections.h +692 -0
  96. decision_graph/includes/decision_graph/decision_tree/bake/c_const.c +20815 -0
  97. decision_graph/includes/decision_graph/decision_tree/bake/c_const.h +395 -0
  98. decision_graph/includes/decision_graph/decision_tree/bake/c_edge.c +20696 -0
  99. decision_graph/includes/decision_graph/decision_tree/bake/c_edge.h +511 -0
  100. decision_graph/includes/decision_graph/decision_tree/bake/c_eval.h +848 -0
  101. decision_graph/includes/decision_graph/decision_tree/bake/c_expr.c +22065 -0
  102. decision_graph/includes/decision_graph/decision_tree/bake/c_expr.h +1900 -0
  103. decision_graph/includes/decision_graph/decision_tree/bake/c_hierarchy.c +23267 -0
  104. decision_graph/includes/decision_graph/decision_tree/bake/c_hierarchy.h +731 -0
  105. decision_graph/includes/decision_graph/decision_tree/bake/c_logic_group.c +22434 -0
  106. decision_graph/includes/decision_graph/decision_tree/bake/c_logic_group.h +1226 -0
  107. decision_graph/includes/decision_graph/decision_tree/bake/c_node.c +28385 -0
  108. decision_graph/includes/decision_graph/decision_tree/bake/c_node.h +2660 -0
  109. decision_graph/includes/decision_graph/decision_tree/bake/c_reconstruct.c +15955 -0
  110. decision_graph/includes/decision_graph/decision_tree/bake/c_var.c +16881 -0
  111. decision_graph/includes/decision_graph/decision_tree/bake/c_var.h +2054 -0
  112. decision_graph/includes/decision_graph/decision_tree/capi/c_abc.c +59196 -0
  113. decision_graph/includes/decision_graph/decision_tree/capi/c_collection.c +19967 -0
  114. decision_graph/includes/decision_graph/decision_tree/capi/c_node.c +39229 -0
  115. decision_graph/logic_group/__init__.py +25 -0
  116. decision_graph/logic_group/base.py +100 -0
  117. decision_graph/logic_group/pending_request.py +384 -0
  118. decision_graph/webui/__init__.py +24 -0
  119. decision_graph/webui/bake/__init__.py +65 -0
  120. decision_graph/webui/bake/app.py +488 -0
  121. decision_graph/webui/bake/static/d3.v7.min.js +2 -0
  122. decision_graph/webui/bake/static/script.js +1440 -0
  123. decision_graph/webui/bake/static/style.css +920 -0
  124. decision_graph/webui/bake/templates/index.html +183 -0
  125. decision_graph/webui/bake/templates/offline.html +184 -0
  126. decision_graph/webui/capi/__init__.py +54 -0
  127. decision_graph/webui/capi/app.py +366 -0
  128. decision_graph/webui/capi/main.py +53 -0
  129. decision_graph/webui/capi/static/d3.v7.min.js +2 -0
  130. decision_graph/webui/capi/static/script.js +1026 -0
  131. decision_graph/webui/capi/static/style.css +656 -0
  132. decision_graph/webui/capi/templates/index.html +93 -0
  133. decision_graph/webui/capi/templates/offline.html +94 -0
  134. decision_graph/webui/native/__init__.py +54 -0
  135. decision_graph/webui/native/app.py +366 -0
  136. decision_graph/webui/native/main.py +53 -0
  137. decision_graph/webui/native/static/d3.v7.min.js +2 -0
  138. decision_graph/webui/native/static/script.js +1026 -0
  139. decision_graph/webui/native/static/style.css +656 -0
  140. decision_graph/webui/native/templates/index.html +93 -0
  141. decision_graph/webui/native/templates/offline.html +94 -0
  142. pydecisiongraph-0.3.2.post1.dist-info/METADATA +136 -0
  143. pydecisiongraph-0.3.2.post1.dist-info/RECORD +148 -0
  144. pydecisiongraph-0.3.2.post1.dist-info/WHEEL +5 -0
  145. pydecisiongraph-0.3.2.post1.dist-info/licenses/LICENSE +373 -0
  146. pydecisiongraph-0.3.2.post1.dist-info/top_level.txt +2 -0
  147. tests/bake_c_evaluator.cp315t-win_amd64.pyd +0 -0
  148. tests/bake_eval_probe.cp315t-win_amd64.pyd +0 -0
@@ -0,0 +1,551 @@
1
+ import json
2
+ import operator
3
+ import traceback
4
+
5
+ from cpython.mem cimport PyMem_Free
6
+
7
+ from .c_abc cimport LogicNodeFrame, LogicGroupStack, PlaceholderNode, ActionNode, LGM, NO_CONDITION, AUTO_CONDITION, NodeEdgeCondition
8
+ from .c_collection cimport LogicMapping, LogicSequence
9
+ from ..exc import NO_DEFAULT, TooManyChildren, TooFewChildren, EdgeValueError, ContextsNotFound, ExpressEvaluationError
10
+
11
+
12
+ cdef class NodeEvalPath(list):
13
+ def to_clipboard(self):
14
+ from pyperclip import copy as clipboard_copy
15
+ cdef LogicNode node
16
+ cdef list path = []
17
+ for node in self:
18
+ path.append(str(node.uid))
19
+ cdef str payload = json.dumps(path)
20
+ clipboard_copy(payload)
21
+ return payload
22
+
23
+
24
+ cdef class RootLogicNode(LogicNode):
25
+ def __cinit__(self, *, str name='Entry Point', object expression=None, type dtype=None, str repr=None, object uid=None, bint inherit_contexts=False, **kwargs):
26
+ self.expression = True if expression is None else expression
27
+ self.dtype = bool if dtype is None else dtype
28
+ self.repr = name if repr is None else repr
29
+ self.inherit_contexts = inherit_contexts
30
+ self._eval_path = []
31
+
32
+ cdef bint c_entry_check(self):
33
+ return True
34
+
35
+ cdef void c_on_enter(self):
36
+ cdef LogicGroupStack* active_groups
37
+ # Step 0: Append placeholder
38
+ self.c_append(PlaceholderNode(auto_connect=False), NO_CONDITION)
39
+
40
+ # Step 1: Pre-shelving enter
41
+ LGM.c_ln_enter(self)
42
+
43
+ # Step 2: Shelve LGM
44
+ if self.inherit_contexts:
45
+ active_groups = LGM._active_groups
46
+ LGM.c_shelve()
47
+ PyMem_Free(LGM._active_groups)
48
+ LGM._active_groups = active_groups
49
+ else:
50
+ LGM.c_shelve()
51
+
52
+ # Step 3: Mark as inspection_mode
53
+ LGM.inspection_mode = True
54
+
55
+ # Step 4: Post-shelving enter
56
+ LGM.c_ln_enter(self)
57
+
58
+ cdef void c_on_exit(self):
59
+ cdef LogicGroupStack* active_groups
60
+ self.c_consolidate_placeholder()
61
+ LGM.c_ln_exit(self)
62
+ # Prevent accidentally free the active_group when inherited
63
+ if self.inherit_contexts:
64
+ LGM._active_groups = NULL
65
+ LGM.c_unshelve()
66
+ LGM.c_ln_exit(self)
67
+
68
+ cdef void c_append(self, LogicNode child, NodeEdgeCondition condition):
69
+ if self.subordinates.size:
70
+ raise TooManyChildren()
71
+
72
+ if not (condition is AUTO_CONDITION or condition is NO_CONDITION):
73
+ raise EdgeValueError()
74
+
75
+ LogicNode.c_append(self, child, NO_CONDITION)
76
+
77
+ def __call__(self, object default=None):
78
+ self._eval_path.clear()
79
+ cdef object value = self.c_eval_recursively(self._eval_path, default)[0]
80
+ return value
81
+
82
+ def eval_recursively(self, list path=None, object default=NO_DEFAULT):
83
+ self._eval_path.clear()
84
+
85
+ cdef object v
86
+ cdef list p
87
+ if path is None:
88
+ v, p = self.c_eval_recursively(self._eval_path, default)
89
+ else:
90
+ v, p = self.c_eval_recursively(path, default)
91
+ self._eval_path.extend(p)
92
+ return v, p
93
+
94
+ def dry_run(self, bint enforce_dtype=False):
95
+ cdef LogicNode child
96
+ for child in self.descendants:
97
+ if isinstance(child, ActionNode):
98
+ continue
99
+ try:
100
+ child.c_eval(enforce_dtype)
101
+ except Exception as e:
102
+ raise ExpressEvaluationError(f"Failed to evaluate {self}, {traceback.format_exc()}") from e
103
+
104
+ cpdef BreakpointNode get_breakpoint(self):
105
+ for leaf in self.leaves:
106
+ if isinstance(leaf, BreakpointNode):
107
+ return leaf
108
+ return None
109
+
110
+ def to_html(self, str file_name=None, bint with_eval=True):
111
+ from ...webui.capi import to_html
112
+ to_html(self, file_name or f'{self.repr}.html', with_eval)
113
+
114
+ def show(self, **kwargs):
115
+ from ...webui.capi import show
116
+ show(self, **kwargs)
117
+
118
+ def watch(self, **kwargs):
119
+ from ...webui.capi import watch
120
+ watch(self, **kwargs)
121
+
122
+ property child:
123
+ def __get__(self) -> LogicNode:
124
+ cdef LogicNodeFrame* frame = self.subordinates.top
125
+ if frame:
126
+ return <LogicNode> <object> frame.logic_node
127
+ raise TooFewChildren()
128
+
129
+ property eval_path:
130
+ def __get__(self) -> NodeEvalPath:
131
+ return NodeEvalPath(self._eval_path)
132
+
133
+
134
+ cdef class ContextLogicExpression(LogicNode):
135
+ def __cinit__(self, *, LogicGroup logic_group=None, **kwargs):
136
+ if logic_group is None:
137
+ logic_group = LGM.active_group
138
+ if logic_group is None:
139
+ raise ContextsNotFound(f'Must assign a logic group or initialize {self.__class__.__name__} with in a LogicGroup with statement!')
140
+
141
+ self.logic_group = logic_group
142
+
143
+ @staticmethod
144
+ cdef inline object c_safe_eval(object v):
145
+ if isinstance(v, LogicNode):
146
+ return (<LogicNode> v).c_eval(False)
147
+ return v
148
+
149
+ @staticmethod
150
+ cdef inline str c_safe_alias(object v):
151
+ if isinstance(v, LogicNode):
152
+ return v.repr
153
+ return str(v)
154
+
155
+ # === Python Interfaces ===
156
+
157
+ def __getitem__(self, str key):
158
+ return AttrExpression(attr=key, logic_group=self.logic_group)
159
+
160
+ def __getattr__(self, str key) -> AttrExpression:
161
+ return AttrExpression(attr=key, logic_group=self.logic_group)
162
+
163
+ # math operation to invoke MathExpression
164
+
165
+ def __add__(self, object other):
166
+ return MathExpression(left=self, op=MathExpressionOperator.add, right=other, logic_group=self.logic_group)
167
+
168
+ def __sub__(self, object other):
169
+ return MathExpression(left=self, op=MathExpressionOperator.sub, right=other, logic_group=self.logic_group)
170
+
171
+ def __mul__(self, object other):
172
+ return MathExpression(left=self, op=MathExpressionOperator.mul, right=other, logic_group=self.logic_group)
173
+
174
+ def __truediv__(self, object other):
175
+ return MathExpression(left=self, op=MathExpressionOperator.truediv, right=other, logic_group=self.logic_group)
176
+
177
+ def __floordiv__(self, object other):
178
+ return MathExpression(left=self, op=MathExpressionOperator.floordiv, right=other, logic_group=self.logic_group)
179
+
180
+ def __pow__(self, object other):
181
+ return MathExpression(left=self, op=MathExpressionOperator.pow, right=other, logic_group=self.logic_group)
182
+
183
+ def __neg__(self):
184
+ return MathExpression(left=self, op=MathExpressionOperator.neg, repr=f'-{self.repr}', logic_group=self.logic_group)
185
+
186
+ # Comparison operation to invoke ComparisonExpression
187
+
188
+ def __eq__(self, object other):
189
+ return ComparisonExpression(left=self, op=ComparisonExpressionOperator.eq, right=other, logic_group=self.logic_group)
190
+
191
+ def __ne__(self, object other):
192
+ return ComparisonExpression(left=self, op=ComparisonExpressionOperator.ne, right=other, logic_group=self.logic_group)
193
+
194
+ def __gt__(self, object other):
195
+ return ComparisonExpression(left=self, op=ComparisonExpressionOperator.gt, right=other, logic_group=self.logic_group)
196
+
197
+ def __ge__(self, object other):
198
+ return ComparisonExpression(left=self, op=ComparisonExpressionOperator.ge, right=other, logic_group=self.logic_group)
199
+
200
+ def __lt__(self, object other):
201
+ return ComparisonExpression(left=self, op=ComparisonExpressionOperator.lt, right=other, logic_group=self.logic_group)
202
+
203
+ def __le__(self, object other):
204
+ return ComparisonExpression(left=self, op=ComparisonExpressionOperator.le, right=other, logic_group=self.logic_group)
205
+
206
+ # Logical operation to invoke LogicalExpression
207
+
208
+ def __and__(self, object other):
209
+ return LogicalExpression(left=self, op=LogicalExpressionOperator.and_, right=other, logic_group=self.logic_group)
210
+
211
+ def __or__(self, object other):
212
+ return LogicalExpression(left=self, op=LogicalExpressionOperator.or_, right=other, logic_group=self.logic_group)
213
+
214
+ def __invert__(self):
215
+ return LogicalExpression(left=self, op=LogicalExpressionOperator.not_, repr=f'~{self.repr}', logic_group=self.logic_group)
216
+
217
+
218
+ cdef class AttrExpression(ContextLogicExpression):
219
+ def __cinit__(self, *, str attr, **kwargs):
220
+ self.attr = attr
221
+ self.repr = kwargs['repr'] if 'repr' in kwargs else f'{self.logic_group.name}.{attr}'
222
+
223
+ cdef object c_eval(self, bint enforce_dtype):
224
+ if isinstance(self.logic_group, LogicMapping):
225
+ return (<LogicMapping> self.logic_group).c_get(self.attr)
226
+ else:
227
+ if self.attr in self.logic_group.contexts:
228
+ return self.logic_group.contexts[self.attr]
229
+ raise AttributeError(f'Attribute {self.attr} does not exist in {self.logic_group}')
230
+
231
+ def __getitem__(self, str key):
232
+ return AttrNestedExpression(attrs=[self.attr, key], logic_group=self.logic_group)
233
+
234
+ def __getattr__(self, str key) -> AttrNestedExpression:
235
+ return AttrNestedExpression(attrs=[self.attr, key], logic_group=self.logic_group)
236
+
237
+
238
+ cdef class AttrNestedExpression(ContextLogicExpression):
239
+ def __cinit__(self, *, list attrs, **kwargs):
240
+ self.attrs = attrs
241
+ self.repr = kwargs['repr'] if 'repr' in kwargs else f'{self.logic_group.name}.{".".join(attrs)}'
242
+
243
+ cdef object c_eval(self, bint enforce_dtype):
244
+ cdef object mapping
245
+ if isinstance(self.logic_group, LogicMapping):
246
+ mapping = (<LogicMapping> self.logic_group).data
247
+ else:
248
+ mapping = self.logic_group.contexts
249
+
250
+ cdef str attr
251
+ for attr in self.attrs:
252
+ mapping = mapping[attr]
253
+ return mapping
254
+
255
+ def __getitem__(self, str key):
256
+ return AttrNestedExpression(attrs=self.attrs + [key], logic_group=self.logic_group)
257
+
258
+ def __getattr__(self, str key) -> AttrExpression:
259
+ return AttrNestedExpression(attrs=self.attrs + [key], logic_group=self.logic_group)
260
+
261
+
262
+ cdef class GetterExpression(ContextLogicExpression):
263
+ def __cinit__(self, *, object key, **kwargs):
264
+ self.key = key
265
+ self.repr = kwargs['repr'] if 'repr' in kwargs else f'{self.logic_group.name}.{key}'
266
+
267
+ cdef object c_eval(self, bint enforce_dtype):
268
+ if isinstance(self.logic_group, LogicMapping):
269
+ return (<LogicMapping> self.logic_group).c_get(self.key)
270
+ elif isinstance(self.logic_group, LogicSequence):
271
+ return (<LogicSequence> self.logic_group).c_get(self.key)
272
+ else:
273
+ if self.key in self.logic_group.contexts:
274
+ return self.logic_group.contexts[self.key]
275
+ raise AttributeError(f'Attribute {self.key} does not exist in {self.logic_group}')
276
+
277
+ def __getitem__(self, str key):
278
+ return GetterNestedExpression(keys=[self.key, key], logic_group=self.logic_group)
279
+
280
+
281
+ cdef class GetterNestedExpression(ContextLogicExpression):
282
+ def __cinit__(self, *, list keys, **kwargs):
283
+ self.keys = keys
284
+ self.repr = kwargs['repr'] if 'repr' in kwargs else f'{self.logic_group.name}.{".".join(keys)}'
285
+
286
+ cdef object c_eval(self, bint enforce_dtype):
287
+ cdef object nested
288
+ if isinstance(self.logic_group, LogicMapping):
289
+ nested = (<LogicMapping> self.logic_group).data
290
+ elif isinstance(self.logic_group, LogicSequence):
291
+ return (<LogicSequence> self.logic_group).c_get(self.key)
292
+ else:
293
+ nested = self.logic_group.contexts
294
+
295
+ cdef object key
296
+ for key in self.keys:
297
+ nested = nested[key]
298
+ return nested
299
+
300
+ def __getitem__(self, str key):
301
+ return GetterNestedExpression(keys=self.keys + [key], logic_group=self.logic_group)
302
+
303
+
304
+ cdef class MathExpressionOperator:
305
+ add = MathExpressionOperator.__new__(MathExpressionOperator, 'add', '+')
306
+ sub = MathExpressionOperator.__new__(MathExpressionOperator, 'sub', '-')
307
+ mul = MathExpressionOperator.__new__(MathExpressionOperator, 'mul', '*')
308
+ truediv = MathExpressionOperator.__new__(MathExpressionOperator, 'truediv', '/')
309
+ floordiv = MathExpressionOperator.__new__(MathExpressionOperator, 'floordiv', '//')
310
+ pow = MathExpressionOperator.__new__(MathExpressionOperator, 'pow', '**')
311
+ neg = MathExpressionOperator.__new__(MathExpressionOperator, 'neg', '--')
312
+
313
+ def __cinit__(self, str name, str op):
314
+ self.name = name
315
+ self.value = op
316
+
317
+ def to_func(self):
318
+ return getattr(operator, self.name)
319
+
320
+ @classmethod
321
+ def from_str(cls, str op_str):
322
+ cdef MathExpressionOperator op
323
+ for op in [cls.add, cls.sub, cls.mul, cls.truediv, cls.floordiv, cls.pow, cls.neg]:
324
+ if op.name == op_str:
325
+ return op
326
+ elif op.value == op_str:
327
+ return op
328
+ raise ValueError(f'Unknown MathExpressionOperator: {op_str}')
329
+
330
+
331
+ cdef class MathExpression(ContextLogicExpression):
332
+ def __cinit__(self, *, object left, object op, object right=NO_DEFAULT, **kwargs):
333
+ self.left = left
334
+ self.right = right
335
+ self.dtype = kwargs.get('dtype', float)
336
+ cdef MathExpressionOperator _op
337
+
338
+ if isinstance(op, MathExpressionOperator):
339
+ _op = <MathExpressionOperator> op
340
+ self.op_name = kwargs.get('op_name', _op.name)
341
+ self.op_repr = kwargs.get('op_repr', _op.value)
342
+ self.op_func = _op.to_func()
343
+ self.repr = kwargs.get('repr', self.c_op_style_repr())
344
+ elif isinstance(op, str):
345
+ _op = MathExpressionOperator.from_str(op)
346
+ self.op_name = kwargs.get('op_name', _op.name)
347
+ self.op_repr = kwargs.get('op_name', _op.value)
348
+ self.op_func = _op.to_func()
349
+ self.repr = kwargs.get('repr', self.c_op_style_repr())
350
+ elif callable(op):
351
+ self.op_name = op.__name__
352
+ self.op_repr = op.__name__
353
+ self.op_func = op
354
+ self.repr = kwargs.get('repr', self.c_func_style_repr())
355
+ else:
356
+ raise TypeError(f'Expected op to be MathExpressionOperator, str or callable, got {type(op).__name__} instead.')
357
+
358
+ cdef str c_op_style_repr(self):
359
+ if self.right is NO_DEFAULT:
360
+ return f'{self.op_repr}{ContextLogicExpression.c_safe_alias(self.left)}'
361
+ return f'{ContextLogicExpression.c_safe_alias(self.left)} {self.op_repr} {ContextLogicExpression.c_safe_alias(self.right)}'
362
+
363
+ cdef str c_func_style_repr(self):
364
+ if self.right is NO_DEFAULT:
365
+ return f'{self.op_repr}({ContextLogicExpression.c_safe_alias(self.left)})'
366
+ return f'{self.op_repr}({ContextLogicExpression.c_safe_alias(self.left)}, {ContextLogicExpression.c_safe_alias(self.right)})'
367
+
368
+ cdef object c_eval(self, bint enforce_dtype):
369
+ if self.right is NO_DEFAULT:
370
+ return self.op_func(ContextLogicExpression.c_safe_eval(self.left))
371
+ return self.op_func(
372
+ ContextLogicExpression.c_safe_eval(self.left),
373
+ ContextLogicExpression.c_safe_eval(self.right)
374
+ )
375
+
376
+
377
+ cdef class ComparisonExpressionOperator:
378
+ eq = ComparisonExpressionOperator.__new__(ComparisonExpressionOperator, 'eq', '==', 1)
379
+ ne = ComparisonExpressionOperator.__new__(ComparisonExpressionOperator, 'ne', '!=', 2)
380
+ gt = ComparisonExpressionOperator.__new__(ComparisonExpressionOperator, 'gt', '>', 3)
381
+ ge = ComparisonExpressionOperator.__new__(ComparisonExpressionOperator, 'ge', '>=', 4)
382
+ lt = ComparisonExpressionOperator.__new__(ComparisonExpressionOperator, 'lt', '<', 5)
383
+ le = ComparisonExpressionOperator.__new__(ComparisonExpressionOperator, 'le', '<=', 6)
384
+
385
+ def __cinit__(self, str name, str op, uint8_t int_enum):
386
+ self.name = name
387
+ self.value = op
388
+ self.int_enum = int_enum
389
+
390
+ def to_func(self):
391
+ return getattr(operator, self.name)
392
+
393
+ @classmethod
394
+ def from_str(cls, str op_str):
395
+ cdef ComparisonExpressionOperator op
396
+ for op in [cls.eq, cls.ne, cls.gt, cls.ge, cls.lt, cls.le]:
397
+ if op.name == op_str:
398
+ return op
399
+ elif op.value == op_str:
400
+ return op
401
+ raise ValueError(f'Unknown ComparisonExpressionOperator: {op_str}')
402
+
403
+
404
+ cdef class ComparisonExpression(ContextLogicExpression):
405
+ def __cinit__(self, *, object left, object op, object right, **kwargs):
406
+ self.left = left
407
+ self.right = right
408
+ self.dtype = kwargs.get('dtype', bool)
409
+ cdef ComparisonExpressionOperator _op
410
+
411
+ if isinstance(op, ComparisonExpressionOperator):
412
+ _op = <ComparisonExpressionOperator> op
413
+ self.op_name = kwargs.get('op_name', _op.name)
414
+ self.op_repr = kwargs.get('op_repr', _op.value)
415
+ self.op_func = _op.to_func()
416
+ self.repr = kwargs.get('repr', self.c_op_style_repr())
417
+ self.op_enum = _op.int_enum
418
+ elif isinstance(op, str):
419
+ _op = ComparisonExpressionOperator.from_str(op)
420
+ self.op_name = kwargs.get('op_name', _op.name)
421
+ self.op_repr = kwargs.get('op_name', _op.value)
422
+ self.op_func = _op.to_func()
423
+ self.repr = kwargs.get('repr', self.c_op_style_repr())
424
+ self.op_enum = _op.int_enum
425
+ elif callable(op):
426
+ self.op_name = op.__name__
427
+ self.op_repr = op.__name__
428
+ self.op_func = op
429
+ self.repr = kwargs.get('repr', self.c_func_style_repr())
430
+ self.builtin = False
431
+ self.op_enum = 0
432
+ else:
433
+ raise TypeError(f'Expected op to be ComparisonExpressionOperator, str or callable, got {type(op).__name__} instead.')
434
+
435
+ cdef str c_op_style_repr(self):
436
+ if self.right is NO_DEFAULT:
437
+ return f'{self.op_repr}{ContextLogicExpression.c_safe_alias(self.left)}'
438
+ return f'{ContextLogicExpression.c_safe_alias(self.left)} {self.op_repr} {ContextLogicExpression.c_safe_alias(self.right)}'
439
+
440
+ cdef str c_func_style_repr(self):
441
+ if self.right is NO_DEFAULT:
442
+ return f'{self.op_repr}({ContextLogicExpression.c_safe_alias(self.left)})'
443
+ return f'{self.op_repr}({ContextLogicExpression.c_safe_alias(self.left)}, {ContextLogicExpression.c_safe_alias(self.right)})'
444
+
445
+ cdef object c_eval(self, bint enforce_dtype):
446
+ cdef object left = ContextLogicExpression.c_safe_eval(self.left)
447
+ cdef object right = ContextLogicExpression.c_safe_eval(self.right)
448
+ cdef uint8_t op_enum = self.op_enum
449
+
450
+ if op_enum == 0:
451
+ return self.op_func(left, right)
452
+ elif op_enum == 1:
453
+ return left == right
454
+ elif op_enum == 2:
455
+ return left != right
456
+ elif op_enum == 3:
457
+ return left > right
458
+ elif op_enum == 4:
459
+ return left >= right
460
+ elif op_enum == 5:
461
+ return left < right
462
+ elif op_enum == 6:
463
+ return left <= right
464
+ else:
465
+ raise RuntimeError(f'Invalid comparison op_enum {op_enum}')
466
+
467
+
468
+ cdef class LogicalExpressionOperator:
469
+ and_ = LogicalExpressionOperator.__new__(LogicalExpressionOperator, 'and_', '&', 1)
470
+ or_ = LogicalExpressionOperator.__new__(LogicalExpressionOperator, 'or_', '|', 2)
471
+ not_ = LogicalExpressionOperator.__new__(LogicalExpressionOperator, 'not_', '~', 3)
472
+
473
+ def __cinit__(self, str name, str op, uint8_t int_enum):
474
+ self.name = name
475
+ self.value = op
476
+ self.int_enum = int_enum
477
+
478
+ def to_func(self):
479
+ return getattr(operator, self.name)
480
+
481
+ @classmethod
482
+ def from_str(cls, str op_str):
483
+ cdef LogicalExpressionOperator op
484
+ for op in [cls.and_, cls.or_, cls.not_]:
485
+ if op.name == op_str:
486
+ return op
487
+ elif op.value == op_str:
488
+ return op
489
+ raise ValueError(f'Unknown LogicalExpressionOperator: {op_str}')
490
+
491
+
492
+ cdef class LogicalExpression(ContextLogicExpression):
493
+ def __cinit__(self, *, object left, object op, object right=NO_DEFAULT, **kwargs):
494
+ self.left = left
495
+ self.right = right
496
+ self.dtype = kwargs.get('dtype', bool)
497
+ cdef LogicalExpressionOperator _op
498
+
499
+ if isinstance(op, LogicalExpressionOperator):
500
+ _op = <LogicalExpressionOperator> op
501
+ self.op_name = kwargs.get('op_name', _op.name)
502
+ self.op_repr = kwargs.get('op_repr', _op.value)
503
+ self.op_func = _op.to_func()
504
+ self.repr = kwargs.get('repr', self.c_op_style_repr())
505
+ self.op_enum = _op.int_enum
506
+ elif isinstance(op, str):
507
+ _op = LogicalExpressionOperator.from_str(op)
508
+ self.op_name = kwargs.get('op_name', _op.name)
509
+ self.op_repr = kwargs.get('op_name', _op.value)
510
+ self.op_func = _op.to_func()
511
+ self.repr = kwargs.get('repr', self.c_op_style_repr())
512
+ self.op_enum = _op.int_enum
513
+ elif callable(op):
514
+ self.op_name = op.__name__
515
+ self.op_repr = op.__name__
516
+ self.op_func = op
517
+ self.repr = kwargs.get('repr', self.c_func_style_repr())
518
+ self.builtin = False
519
+ self.op_enum = 0
520
+ else:
521
+ raise TypeError(f'Expected op to be LogicalExpressionOperator, str or callable, got {type(op).__name__} instead.')
522
+
523
+ cdef str c_op_style_repr(self):
524
+ if self.right is NO_DEFAULT:
525
+ return f'{self.op_repr}{ContextLogicExpression.c_safe_alias(self.left)}'
526
+ return f'{ContextLogicExpression.c_safe_alias(self.left)} {self.op_repr} {ContextLogicExpression.c_safe_alias(self.right)}'
527
+
528
+ cdef str c_func_style_repr(self):
529
+ if self.right is NO_DEFAULT:
530
+ return f'{self.op_repr}({ContextLogicExpression.c_safe_alias(self.left)})'
531
+ return f'{self.op_repr}({ContextLogicExpression.c_safe_alias(self.left)}, {ContextLogicExpression.c_safe_alias(self.right)})'
532
+
533
+ cdef object c_eval(self, bint enforce_dtype):
534
+ cdef uint8_t op_enum = self.op_enum
535
+
536
+ if op_enum == 0:
537
+ return self.op_func(ContextLogicExpression.c_safe_eval(self.left), ContextLogicExpression.c_safe_eval(self.right))
538
+
539
+ cdef bint left = ContextLogicExpression.c_safe_eval(self.left)
540
+
541
+ if op_enum == 3:
542
+ return not left
543
+
544
+ cdef bint right = ContextLogicExpression.c_safe_eval(self.right)
545
+
546
+ if op_enum == 1:
547
+ return left and right
548
+ elif op_enum == 2:
549
+ return left or right
550
+
551
+ raise RuntimeError(f'Invalid comparison op_enum {op_enum}')