PyDecisionGraph 0.3.2.post1__cp315-cp315-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.cp315-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.cp315-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.cp315-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.cp315-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.cp315-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.cp315-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.cp315-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.cp315-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.cp315-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.cp315-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.cp315-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.cp315-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.cp315-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.cp315-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.cp315-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.cp315-win_amd64.pyd +0 -0
  148. tests/bake_eval_probe.cp315-win_amd64.pyd +0 -0
@@ -0,0 +1,308 @@
1
+ from cpython.dict cimport PyDict_Contains
2
+ from cpython.unicode cimport PyUnicode_AsUTF8, PyUnicode_FromString
3
+ from libc.stdint cimport uintptr_t
4
+ from libc.string cimport strlen
5
+
6
+ from cbase.bytemap cimport c_bytemap_gen_seq_id
7
+
8
+ from .c_allocator_protocol cimport DCG_DEFAULT_ALLOCATOR
9
+ from .c_var cimport dcg_ret_code
10
+
11
+
12
+ cdef class LogicGroupNameRegistry(BoundByteMap):
13
+ @staticmethod
14
+ cdef LogicGroupNameRegistry c_from_header(dcg_logic_group_manager* header, bint owner=False):
15
+ if owner:
16
+ raise PermissionError('Must not assign dcg_logic_group_manager ownership to a <LogicGroupNameRegistry>')
17
+ cdef LogicGroupNameRegistry instance = LogicGroupNameRegistry.__new__(LogicGroupNameRegistry)
18
+ instance.owner = False
19
+ instance.seq_id = c_bytemap_gen_seq_id(<void*> instance)
20
+ instance.c_bind(&header.registry)
21
+ return instance
22
+
23
+ cdef const char* c_serialize_value(self, object obj, size_t* value_len):
24
+ cdef LogicGroup logic_group = <LogicGroup> obj
25
+ self._ws_ptr = <void*> logic_group.header
26
+ if value_len:
27
+ value_len[0] = sizeof(void*)
28
+ return <const char*> &self._ws_ptr
29
+
30
+ cdef object c_deserialize_value(self, const char* value, size_t value_len):
31
+ cdef void** vp = <void**> value
32
+ cdef dcg_logic_group* logic_group = <dcg_logic_group*> vp[0]
33
+ if not logic_group:
34
+ return None
35
+ return LogicGroup.c_from_header(logic_group, False)
36
+
37
+
38
+ cdef class LogicGroupManager:
39
+ def __init__(self):
40
+ self.header = c_dcg_lgm_new(DCG_DEFAULT_ALLOCATOR)
41
+ if not self.header:
42
+ raise MemoryError('Failed to allocate the LogicGroupManager.')
43
+
44
+ self.owner = True
45
+ self.registry = LogicGroupNameRegistry.c_from_header(self.header, False)
46
+ self.node_stack = []
47
+
48
+ def __dealloc__(self):
49
+ if not self.owner:
50
+ return
51
+
52
+ if self.header:
53
+ c_dcg_lgm_free(self.header)
54
+
55
+ # === Cython Internal Binding ===
56
+
57
+ cdef void c_register(self, dcg_logic_group* group):
58
+ cdef int ret_code = c_dcg_lgm_register(self.header, group)
59
+ if ret_code != dcg_ret_code.DCG_OK:
60
+ raise RuntimeError(f'c_dcg_lgm_register failed with err code: {ret_code}')
61
+ self.registry[PyUnicode_FromString(group.name)] = LogicGroup.c_from_header(group, False)
62
+
63
+ cdef dcg_logic_group* c_find(self, const char* name):
64
+ if not name:
65
+ return NULL
66
+ return c_dcg_lgm_find(self.header, name, strlen(name))
67
+
68
+ cdef void c_enter_group(self, dcg_logic_group* group):
69
+ cdef int ret_code = c_dcg_lgm_enter_group(self.header, group)
70
+ if ret_code != dcg_ret_code.DCG_OK:
71
+ raise RuntimeError(f'c_dcg_lgm_enter_group failed with err code: {ret_code}')
72
+
73
+ cdef void c_exit_group(self, dcg_logic_group* group):
74
+ cdef int ret_code = c_dcg_lgm_exit_group(self.header, group)
75
+ if ret_code != dcg_ret_code.DCG_OK:
76
+ raise RuntimeError(f'c_dcg_lgm_exit_group failed with err code: {ret_code}')
77
+
78
+ cdef int c_label_node(self, dcg_node* node):
79
+ cdef int added = c_dcg_lgm_label_node(self.header, node)
80
+ if added < 0:
81
+ raise RuntimeError(f'c_dcg_lgm_label_node failed with err code: {added}')
82
+ return added
83
+
84
+ cdef void c_break_inspection(self, dcg_logic_group* group):
85
+ cdef int ret_code = c_dcg_lgm_break_inspection(self.header, group)
86
+ if ret_code != dcg_ret_code.DCG_OK:
87
+ raise RuntimeError(f'c_dcg_lgm_break_inspection failed with err code: {ret_code}')
88
+
89
+ cdef void c_shelve(self):
90
+ cdef int ret_code = c_dcg_lgm_shelve(self.header)
91
+ if ret_code != dcg_ret_code.DCG_OK:
92
+ raise RuntimeError(f'c_dcg_lgm_shelve failed with err code: {ret_code}')
93
+
94
+ cdef void c_unshelve(self):
95
+ cdef int ret_code = c_dcg_lgm_unshelve(self.header)
96
+ if ret_code != dcg_ret_code.DCG_OK:
97
+ raise RuntimeError(f'c_dcg_lgm_unshelve failed with err code: {ret_code}')
98
+
99
+ # === Python Interfaces ===
100
+
101
+ cpdef void node_stack_append(self, LogicNode node):
102
+ self.node_stack.append(node)
103
+
104
+ cpdef void node_stack_pop(self, LogicNode node):
105
+ if self.node_stack and self.node_stack[-1] is node:
106
+ self.node_stack.pop()
107
+
108
+ def register(self, LogicGroup group):
109
+ if group.name is not None:
110
+ self.c_register(group.header)
111
+ GROUP_REGISTRY[<uintptr_t> group.header] = group
112
+
113
+ def find(self, str name):
114
+ return self.registry[name]
115
+
116
+ def shelve(self):
117
+ self.c_shelve()
118
+
119
+ def unshelve(self):
120
+ self.c_unshelve()
121
+
122
+ def clear(self):
123
+ c_dcg_lgm_clear(self.header)
124
+
125
+ def label_node(self, LogicNode node):
126
+ return self.c_label_node(node.header)
127
+
128
+ # === Python Properties ===
129
+
130
+ property inspection_mode:
131
+ def __get__(self):
132
+ return self.header.inspection_mode
133
+
134
+ def __set__(self, bint value):
135
+ self.header.inspection_mode = value
136
+
137
+ property vigilant_mode:
138
+ def __get__(self):
139
+ return self.header.vigilant_mode
140
+
141
+ def __set__(self, bint value):
142
+ self.header.vigilant_mode = value
143
+
144
+ property active_group:
145
+ def __get__(self):
146
+ cdef dcg_logic_group* active = c_dcg_lgm_active_group(self.header)
147
+ if active == NULL:
148
+ return None
149
+ return GROUP_REGISTRY[<uintptr_t> active]
150
+
151
+ property active_node:
152
+ def __get__(self):
153
+ if not self.node_stack:
154
+ return None
155
+ return self.node_stack[-1]
156
+
157
+ property address:
158
+ def __get__(self):
159
+ return <uintptr_t> self.header
160
+
161
+ property n_groups:
162
+ def __get__(self):
163
+ return self.header.n_groups
164
+
165
+ property n_nodes:
166
+ def __get__(self):
167
+ return self.header.n_nodes
168
+
169
+ property n_breakpoints:
170
+ def __get__(self):
171
+ return c_dcg_lgm_breakpoint_count(self.header)
172
+
173
+
174
+ cdef class LogicGroup:
175
+ def __init__(self, *, str name=None, LogicGroup parent=None, **kwargs):
176
+ self.header = c_dcg_logic_group_new(
177
+ DCG_LG_BASE,
178
+ PyUnicode_AsUTF8(name) if name is not None else NULL,
179
+ DCG_DEFAULT_ALLOCATOR,
180
+ )
181
+ if not self.header:
182
+ raise MemoryError(f'Failed to allocate {self.__class__.__name__}({name!r}).')
183
+
184
+ self.owner = True
185
+ if parent is not None:
186
+ self.header.parent = parent.header
187
+ LGM.register(self)
188
+
189
+ def __dealloc__(self):
190
+ # __dealloc__ chains through the hierarchy, so the release goes through
191
+ # one virtual method: a family that adds state of its own overrides it
192
+ # rather than freeing the block a second time in its own __dealloc__.
193
+ if not self.owner:
194
+ return
195
+
196
+ if self.header:
197
+ self.c_free_header()
198
+
199
+ cdef void c_free_header(self):
200
+ c_dcg_logic_group_free(self.header)
201
+
202
+ @staticmethod
203
+ cdef LogicGroup c_from_header(dcg_logic_group* header, bint owner=False):
204
+ cdef LogicGroup instance = LogicGroup.__new__(LogicGroup)
205
+ instance.header = header
206
+ instance.owner = owner
207
+ return instance
208
+
209
+ # === Python Dunders ===
210
+
211
+ def __repr__(self):
212
+ return f'<{self.__class__.__name__}({self.name!r})>'
213
+
214
+ def __enter__(self):
215
+ LGM.c_enter_group(self.header)
216
+ return self
217
+
218
+ def __exit__(self, exc_type, exc_value, traceback):
219
+ LGM.c_exit_group(self.header)
220
+ return False
221
+
222
+ # === Cython Internal Binding ===
223
+
224
+ cdef void c_break(self, dcg_logic_group* scope):
225
+ LGM.c_break_inspection(scope)
226
+
227
+ # === Python Interfaces ===
228
+
229
+ def break_(self, LogicGroup scope=None):
230
+ self.c_break(scope.header if scope is not None else self.header)
231
+
232
+ @classmethod
233
+ def break_active(cls, LogicGroup scope=None):
234
+ if scope is not None:
235
+ LGM.c_break_inspection(scope.header)
236
+
237
+ # === Python Properties ===
238
+
239
+ property name:
240
+ def __get__(self):
241
+ if not self.header or not self.header.name:
242
+ return None
243
+ return PyUnicode_FromString(self.header.name)
244
+
245
+ property parent:
246
+ def __get__(self):
247
+ if not self.header or not self.header.parent:
248
+ return None
249
+ return GROUP_REGISTRY[<uintptr_t> self.header.parent]
250
+
251
+ property lgtype:
252
+ def __get__(self):
253
+ if not self.header:
254
+ return None
255
+ return self.header.lgtype
256
+
257
+ property address:
258
+ def __get__(self):
259
+ return <uintptr_t> self.header
260
+
261
+
262
+ cdef class LogicGroupWrapperRegistry(BoundByteMap):
263
+ @staticmethod
264
+ cdef LogicGroupWrapperRegistry c_from_header(bytemap* header, bint owner=False):
265
+ cdef LogicGroupWrapperRegistry instance = LogicGroupWrapperRegistry.__new__(LogicGroupWrapperRegistry)
266
+ instance.owner = owner
267
+ instance.seq_id = c_bytemap_gen_seq_id(<void*> instance)
268
+ instance.c_bind(header)
269
+ return instance
270
+
271
+ cdef const char* c_serialize_key(self, object obj, size_t* key_len):
272
+ # A header address is provided in format of int (uintptr_t)
273
+ if isinstance(obj, int):
274
+ self._ws_key_buf = <void*> <uintptr_t> obj
275
+ if key_len:
276
+ key_len[0] = sizeof(void*)
277
+ return <const char*> &self._ws_key_buf
278
+ return BoundByteMap.c_serialize_key(self, obj, key_len)
279
+
280
+ cdef object c_deserialize_key(self, const char* key, size_t key_len):
281
+ return <uintptr_t> <void*> key
282
+
283
+ cdef const char* c_serialize_value(self, object obj, size_t* value_len):
284
+ cdef LogicGroup logic_group = <LogicGroup> obj
285
+ self._ws_ptr = <void*> logic_group.header
286
+ if value_len:
287
+ value_len[0] = sizeof(void*)
288
+ return <const char*> &self._ws_ptr
289
+
290
+ cdef object c_deserialize_value(self, const char* value, size_t value_len):
291
+ cdef void** vp = <void**> value
292
+ cdef dcg_logic_group* logic_group = <dcg_logic_group*> vp[0]
293
+ if not logic_group:
294
+ return None
295
+ return LogicGroup.c_from_header(logic_group, False)
296
+
297
+ def __getitem__(self, object key):
298
+ cdef int ret_code = PyDict_Contains(<dict> self, key)
299
+ if ret_code == 0:
300
+ return LogicGroup.c_from_header(<dcg_logic_group*> <uintptr_t> key, False)
301
+ return super().__getitem__(key)
302
+
303
+
304
+ cdef LogicGroupWrapperRegistry GROUP_REGISTRY = LogicGroupWrapperRegistry()
305
+ globals()['GROUP_REGISTRY'] = GROUP_REGISTRY
306
+
307
+ LGM = LogicGroupManager()
308
+ globals()['LGM'] = LGM