jaseci 1.4.2.5__py3-none-any.whl → 2.0.0__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.

Potentially problematic release.


This version of jaseci might be problematic. Click here for more details.

Files changed (186) hide show
  1. jaseci/__init__.py +3 -37
  2. jaseci-2.0.0.dist-info/METADATA +65 -0
  3. jaseci-2.0.0.dist-info/RECORD +4 -0
  4. {jaseci-1.4.2.5.dist-info → jaseci-2.0.0.dist-info}/WHEEL +1 -2
  5. jaseci/VERSION +0 -1
  6. jaseci/cli_tools/__init__.py +0 -0
  7. jaseci/cli_tools/book_tools.py +0 -457
  8. jaseci/cli_tools/jsctl.py +0 -500
  9. jaseci/cli_tools/tests/__init__.py +0 -0
  10. jaseci/cli_tools/tests/test_jsctl.py +0 -556
  11. jaseci/extens/__init__.py +0 -0
  12. jaseci/extens/act_lib/__init__.py +0 -0
  13. jaseci/extens/act_lib/date.py +0 -117
  14. jaseci/extens/act_lib/elastic.py +0 -87
  15. jaseci/extens/act_lib/file.py +0 -76
  16. jaseci/extens/act_lib/file_handler.py +0 -189
  17. jaseci/extens/act_lib/internal.py +0 -18
  18. jaseci/extens/act_lib/jaseci.py +0 -61
  19. jaseci/extens/act_lib/mail.py +0 -10
  20. jaseci/extens/act_lib/maths.py +0 -168
  21. jaseci/extens/act_lib/net.py +0 -191
  22. jaseci/extens/act_lib/rand.py +0 -82
  23. jaseci/extens/act_lib/regex.py +0 -85
  24. jaseci/extens/act_lib/request.py +0 -169
  25. jaseci/extens/act_lib/std.py +0 -235
  26. jaseci/extens/act_lib/storage.py +0 -53
  27. jaseci/extens/act_lib/stripe.py +0 -337
  28. jaseci/extens/act_lib/task.py +0 -13
  29. jaseci/extens/act_lib/tests/__init__.py +0 -0
  30. jaseci/extens/act_lib/tests/std_test_code.py +0 -37
  31. jaseci/extens/act_lib/tests/test_date.py +0 -26
  32. jaseci/extens/act_lib/tests/test_elastic.py +0 -159
  33. jaseci/extens/act_lib/tests/test_file.py +0 -116
  34. jaseci/extens/act_lib/tests/test_file_lib.py +0 -40
  35. jaseci/extens/act_lib/tests/test_mail_lib.py +0 -33
  36. jaseci/extens/act_lib/tests/test_maths.py +0 -147
  37. jaseci/extens/act_lib/tests/test_net_lib.py +0 -62
  38. jaseci/extens/act_lib/tests/test_regex.py +0 -61
  39. jaseci/extens/act_lib/tests/test_std.py +0 -51
  40. jaseci/extens/act_lib/tests/test_std_lib.py +0 -36
  41. jaseci/extens/act_lib/tests/test_url.py +0 -32
  42. jaseci/extens/act_lib/tests/test_vector.py +0 -36
  43. jaseci/extens/act_lib/tests/test_webtool.py +0 -44
  44. jaseci/extens/act_lib/tests/test_zlib.py +0 -24
  45. jaseci/extens/act_lib/url.py +0 -79
  46. jaseci/extens/act_lib/vector.py +0 -157
  47. jaseci/extens/act_lib/webtool.py +0 -28
  48. jaseci/extens/act_lib/zip.py +0 -33
  49. jaseci/extens/api/__init__.py +0 -0
  50. jaseci/extens/api/actions_api.py +0 -170
  51. jaseci/extens/api/alias_api.py +0 -139
  52. jaseci/extens/api/architype_api.py +0 -196
  53. jaseci/extens/api/config_api.py +0 -129
  54. jaseci/extens/api/global_api.py +0 -84
  55. jaseci/extens/api/graph_api.py +0 -167
  56. jaseci/extens/api/health_api.py +0 -20
  57. jaseci/extens/api/interface.py +0 -268
  58. jaseci/extens/api/jac_api.py +0 -171
  59. jaseci/extens/api/jsorc_api.py +0 -316
  60. jaseci/extens/api/logger_api.py +0 -89
  61. jaseci/extens/api/master_api.py +0 -133
  62. jaseci/extens/api/object_api.py +0 -101
  63. jaseci/extens/api/prometheus_api.py +0 -74
  64. jaseci/extens/api/queue_api.py +0 -140
  65. jaseci/extens/api/sentinel_api.py +0 -270
  66. jaseci/extens/api/super_api.py +0 -64
  67. jaseci/extens/api/tests/__init__.py +0 -0
  68. jaseci/extens/api/tests/test_architype_api.py +0 -66
  69. jaseci/extens/api/tests/test_global_api.py +0 -179
  70. jaseci/extens/api/tests/test_graph_api.py +0 -64
  71. jaseci/extens/api/tests/test_logger_api.py +0 -43
  72. jaseci/extens/api/tests/test_object_api.py +0 -20
  73. jaseci/extens/api/tests/test_sentinel_api.py +0 -66
  74. jaseci/extens/api/tests/test_uncommon.py +0 -107
  75. jaseci/extens/api/tests/test_user_api.py +0 -32
  76. jaseci/extens/api/tests/test_walker_api.py +0 -316
  77. jaseci/extens/api/user_api.py +0 -144
  78. jaseci/extens/api/walker_api.py +0 -298
  79. jaseci/extens/api/webhook_api.py +0 -74
  80. jaseci/extens/svc/__init__.py +0 -0
  81. jaseci/extens/svc/elastic_svc.py +0 -366
  82. jaseci/extens/svc/kube_svc.py +0 -432
  83. jaseci/extens/svc/mail_svc.py +0 -156
  84. jaseci/extens/svc/prome_svc.py +0 -378
  85. jaseci/extens/svc/redis_svc.py +0 -63
  86. jaseci/extens/svc/storage_svc.py +0 -193
  87. jaseci/extens/svc/stripe_svc.py +0 -51
  88. jaseci/extens/svc/task_svc.py +0 -155
  89. jaseci/extens/svc/tasks.py +0 -302
  90. jaseci/jac/__init__.py +0 -0
  91. jaseci/jac/interpreter/__init__.py +0 -0
  92. jaseci/jac/interpreter/architype_interp.py +0 -214
  93. jaseci/jac/interpreter/interp.py +0 -1783
  94. jaseci/jac/interpreter/sentinel_interp.py +0 -257
  95. jaseci/jac/interpreter/tests/__init__.py +0 -0
  96. jaseci/jac/interpreter/tests/test_interp.py +0 -42
  97. jaseci/jac/interpreter/walker_interp.py +0 -248
  98. jaseci/jac/ir/__init__.py +0 -0
  99. jaseci/jac/ir/ast.py +0 -73
  100. jaseci/jac/ir/ast_builder.py +0 -249
  101. jaseci/jac/ir/jac_code.py +0 -152
  102. jaseci/jac/ir/passes/__init__.py +0 -6
  103. jaseci/jac/ir/passes/ast_prune_pass.py +0 -9
  104. jaseci/jac/ir/passes/codegen_pass.py +0 -244
  105. jaseci/jac/ir/passes/ir_pass.py +0 -29
  106. jaseci/jac/ir/passes/printer_pass.py +0 -23
  107. jaseci/jac/ir/passes/pt_prune_pass.py +0 -29
  108. jaseci/jac/ir/passes/schedule.py +0 -23
  109. jaseci/jac/ir/passes/stats_pass.py +0 -16
  110. jaseci/jac/jac.g4 +0 -450
  111. jaseci/jac/jac_parse/__init__.py +0 -0
  112. jaseci/jac/jac_parse/jacLexer.py +0 -809
  113. jaseci/jac/jac_parse/jacListener.py +0 -853
  114. jaseci/jac/jac_parse/jacParser.py +0 -9192
  115. jaseci/jac/jac_set.py +0 -119
  116. jaseci/jac/jsci_vm/__init__.py +0 -0
  117. jaseci/jac/jsci_vm/disasm.py +0 -94
  118. jaseci/jac/jsci_vm/inst_ptr.py +0 -31
  119. jaseci/jac/jsci_vm/machine.py +0 -188
  120. jaseci/jac/jsci_vm/op_codes.py +0 -82
  121. jaseci/jac/jsci_vm/tests/__init__.py +0 -0
  122. jaseci/jac/jsci_vm/tests/test_codegen.py +0 -31
  123. jaseci/jac/machine/__init__.py +0 -0
  124. jaseci/jac/machine/jac_scope.py +0 -85
  125. jaseci/jac/machine/jac_value.py +0 -226
  126. jaseci/jac/machine/machine_state.py +0 -383
  127. jaseci/jac/tests/__init__.py +0 -0
  128. jaseci/jac/tests/book_code.py +0 -624
  129. jaseci/jac/tests/test_book.py +0 -380
  130. jaseci/jac/tests/test_lang_14.py +0 -49
  131. jaseci/jsorc/__init__.py +0 -7
  132. jaseci/jsorc/jsorc.py +0 -642
  133. jaseci/jsorc/jsorc_settings.py +0 -211
  134. jaseci/jsorc/jsorc_utils.py +0 -298
  135. jaseci/jsorc/live_actions.py +0 -364
  136. jaseci/jsorc/manifests/__init__.py +0 -0
  137. jaseci/jsorc/manifests/database.yaml +0 -109
  138. jaseci/jsorc/manifests/elastic.yaml +0 -6024
  139. jaseci/jsorc/manifests/prometheus.yaml +0 -1383
  140. jaseci/jsorc/manifests/redis.yaml +0 -64
  141. jaseci/jsorc/memory.py +0 -258
  142. jaseci/jsorc/redis.py +0 -139
  143. jaseci/jsorc/remote_actions.py +0 -157
  144. jaseci/jsorc/tests/__init__.py +0 -0
  145. jaseci/jsorc/tests/test_actions.py +0 -542
  146. jaseci/jsorc/tests/test_jsorc.py +0 -112
  147. jaseci/prim/__init__.py +0 -0
  148. jaseci/prim/ability.py +0 -93
  149. jaseci/prim/architype.py +0 -89
  150. jaseci/prim/edge.py +0 -172
  151. jaseci/prim/element.py +0 -233
  152. jaseci/prim/graph.py +0 -26
  153. jaseci/prim/master.py +0 -64
  154. jaseci/prim/node.py +0 -532
  155. jaseci/prim/obj_mixins.py +0 -235
  156. jaseci/prim/sentinel.py +0 -281
  157. jaseci/prim/super_master.py +0 -31
  158. jaseci/prim/walker.py +0 -261
  159. jaseci/svc/__init__.py +0 -0
  160. jaseci/tests/__init__.py +0 -0
  161. jaseci/tests/infer.py +0 -39
  162. jaseci/tests/jac_test_code.py +0 -1293
  163. jaseci/tests/jac_test_progs.py +0 -774
  164. jaseci/tests/test_core.py +0 -153
  165. jaseci/tests/test_jac.py +0 -824
  166. jaseci/tests/test_node.py +0 -89
  167. jaseci/tests/test_progs.py +0 -702
  168. jaseci/tests/test_stack.py +0 -220
  169. jaseci/tests/test_stripe.py +0 -225
  170. jaseci/utils/__init__.py +0 -0
  171. jaseci/utils/actions/__init__.py +0 -0
  172. jaseci/utils/actions/actions_manager.py +0 -254
  173. jaseci/utils/actions/actions_optimizer.py +0 -516
  174. jaseci/utils/actions/actions_state.py +0 -95
  175. jaseci/utils/file_handler.py +0 -171
  176. jaseci/utils/gprof2dot.py +0 -3786
  177. jaseci/utils/id_list.py +0 -168
  178. jaseci/utils/json_handler.py +0 -70
  179. jaseci/utils/log_utils.py +0 -57
  180. jaseci/utils/test_core.py +0 -62
  181. jaseci/utils/utils.py +0 -387
  182. jaseci-1.4.2.5.dist-info/LICENSE +0 -21
  183. jaseci-1.4.2.5.dist-info/METADATA +0 -39
  184. jaseci-1.4.2.5.dist-info/RECORD +0 -184
  185. jaseci-1.4.2.5.dist-info/entry_points.txt +0 -3
  186. jaseci-1.4.2.5.dist-info/top_level.txt +0 -1
jaseci/prim/node.py DELETED
@@ -1,532 +0,0 @@
1
- """
2
- Node class for Jaseci
3
-
4
- Each node has an id, name, timestamp and it's set of edges.
5
- First node in list of 'member_node_ids' is designated root node
6
- """
7
- from collections import OrderedDict
8
- from jaseci.prim.element import Element
9
- from jaseci.prim.obj_mixins import Anchored
10
- from jaseci.prim.edge import Edge
11
- from jaseci.utils.id_list import IdList
12
- from jaseci.utils.utils import logger
13
-
14
- import uuid
15
-
16
- TO = 0
17
- FROM = 1
18
- BI = 2
19
-
20
-
21
- class Node(Element, Anchored):
22
- """Node class for Jaseci"""
23
-
24
- def __init__(self, dimension=0, **kwargs):
25
- self.edge_ids = IdList(self)
26
- self.fast_edges = {} # {name: [[NODEID, DIR, EDGEID, CONTEXT],...]}
27
- self._fast_edge_ids = IdList(self)
28
- self.parent_node_ids = IdList(self)
29
- self.member_node_ids = IdList(self)
30
- self.dimension = dimension # Nodes are always hdgd 0
31
- Element.__init__(self, **kwargs)
32
- Anchored.__init__(self)
33
-
34
- @property
35
- def smart_edges(self):
36
- obj_list = self.smart_edge_list.obj_list()
37
- for i in obj_list:
38
- if i.is_fast() and i.jid in self.edge_ids:
39
- self.edge_ids.remove_obj(i)
40
- self._fast_edge_ids.remove_obj(i)
41
- self.smart_add_edge(i)
42
- return obj_list
43
-
44
- @property
45
- def smart_edge_list(self):
46
- if not len(self._fast_edge_ids):
47
- self.smart_build_fast_edge_ids()
48
- return self._fast_edge_ids
49
-
50
- def smart_build_fast_edge_ids(self):
51
- self._fast_edge_ids = IdList(self, in_list=self.edge_ids)
52
- for k in self.fast_edges.keys():
53
- for v in self.fast_edges[k]:
54
- link_order = [v[0], self.jid] if v[1] == FROM else [self.jid, v[0]]
55
- if len(v) > 2 and self._h.has_obj(v[2]):
56
- edge = self._h.get_obj(self._m_id, v[2])
57
- if len(v) > 3:
58
- v[3] = edge.context
59
- else:
60
- v.append(edge.context)
61
- else:
62
- edge = Edge(
63
- m_id=self._m_id, h=self._h, kind="edge", name=k, auto_save=False
64
- )
65
- edge.from_node_id = link_order[0]
66
- edge.to_node_id = link_order[1]
67
- edge.bidirected = v[1] == BI
68
- edge.jid = v[2] if len(v) > 2 else uuid.uuid4().urn
69
- edge.context = v[3] if len(v) > 3 else {}
70
- # old `edge.save()` might be confusing
71
- # this line doesn't mean it has to be saved on db
72
- # it only needs to be available on cache (memory, redis)
73
- self._h.commit_obj_to_cache(edge, True)
74
- self._fast_edge_ids.add_obj(edge, bypass=True)
75
-
76
- def smart_add_edge(self, obj):
77
- # make sure fast edges built
78
- if not len(self._fast_edge_ids):
79
- self.smart_build_fast_edge_ids()
80
- # add new edge
81
- self._fast_edge_ids.add_obj(obj)
82
- # then store how needed
83
- if obj.is_fast():
84
- self.smart_edge_to_fast_edge(obj)
85
- else:
86
- self.edge_ids.add_obj(obj)
87
-
88
- def smart_edge_to_fast_edge(self, obj):
89
- if obj.name not in self.fast_edges:
90
- self.fast_edges[obj.name] = []
91
- details = [
92
- obj.opposing_node(self).jid,
93
- BI if obj.is_bidirected() else TO if obj.from_node() == self else FROM,
94
- obj.jid,
95
- obj.context,
96
- ]
97
- self.fast_edges[obj.name].append(details)
98
-
99
- def smart_remove_edge(self, obj):
100
- if obj.is_fast():
101
- pluck = None
102
- for i in self.fast_edges[obj.name]:
103
- other_node_id = obj.to_node_id if i[1] == TO else obj.from_node_id
104
- if i[0] == other_node_id:
105
- if obj.is_bidirected() or not (
106
- i[1] == TO and obj.to_node() == self
107
- ):
108
- pluck = i
109
- break
110
- self.fast_edges[obj.name].remove(pluck)
111
- if not len(self.fast_edges[obj.name]):
112
- del self.fast_edges[obj.name]
113
- elif obj and obj.jid in self.edge_ids:
114
- self.edge_ids.remove_obj(obj)
115
- self.clear_fast_edge_ids()
116
- self.save()
117
-
118
- def clear_fast_edge_ids(self):
119
- self._fast_edge_ids = IdList(self)
120
-
121
- def attach(self, node_obj, edge_set=None, as_outbound=True, as_bidirected=False):
122
- """
123
- Generalized attach function for attaching nodes with edges
124
- """
125
- if edge_set is None:
126
- edge_set = [
127
- Edge(
128
- m_id=self._m_id,
129
- h=self._h,
130
- kind="edge",
131
- name="generic",
132
- )
133
- ]
134
- link_order = [self, node_obj] if as_outbound else [node_obj, self]
135
- for e in edge_set:
136
- if not e.connect(link_order[0], link_order[1]):
137
- # Node not found error logged in set node function
138
- return []
139
- e.set_bidirected(as_bidirected)
140
- # save and return
141
- self.save()
142
- node_obj.save()
143
- return edge_set
144
-
145
- def attach_outbound(self, node_obj, edge_set=None):
146
- """
147
- Creates edge to a node and returns the edge
148
- edge_set is the list of edges to be used to make connections
149
- new edge is created if edge_set is empty
150
- """
151
- return self.attach(node_obj, edge_set, as_outbound=True)
152
-
153
- def attach_inbound(self, node_obj, edge_set=None):
154
- """
155
- Creates edge from a node and returns the edge
156
- edge_set is the list of edges to be used to make connections
157
- new edge is created if edge_set is empty
158
- """
159
- return self.attach(node_obj, edge_set, as_outbound=False)
160
-
161
- def attach_bidirected(self, node_obj, edge_set=None):
162
- """
163
- Creates bidirected edge to node returns the edge
164
- edge_set is the list of edges to be used to make connections
165
- new edge is created if edge_set is empty
166
- """
167
- return self.attach(node_obj, edge_set, as_bidirected=True)
168
-
169
- def detach(
170
- self,
171
- node_obj,
172
- edge_set=None,
173
- as_outbound=True,
174
- as_bidirected=False,
175
- ignore_direction=False,
176
- silent=True,
177
- ):
178
- """
179
- Generalized detach function for detaching nodes with edges
180
- """
181
- if edge_set is None:
182
- edge_set = self.attached_edges(node_obj)
183
- link_order = [self, node_obj] if as_outbound else [node_obj, self]
184
- num_detached = 0
185
- for e in edge_set:
186
- # validate edge connection exists
187
- if not e.connects(
188
- link_order[0], link_order[1], ignore_direction=ignore_direction
189
- ):
190
- if not silent:
191
- logger.warning(
192
- str(
193
- f"{e} does not connect "
194
- f"{link_order[0]} to {link_order[1]}"
195
- )
196
- )
197
- continue
198
- if as_bidirected and not ignore_direction and not e.is_bidirected():
199
- if not silent:
200
- logger.warning(str(f"{e} is not a bidirected edge "))
201
- continue
202
- # destroy edge
203
- num_detached += 1
204
- e.destroy()
205
- return num_detached
206
-
207
- def detach_outbound(self, node_obj, edge_set=None, silent=True):
208
- """
209
- Destroy edges to a node
210
- edge_set is the list of edges to be detached (and distroyed)
211
- all edges are deteached and destroyed if edge_set empty
212
- returns number of detachments
213
- """
214
- return self.detach(node_obj, edge_set, as_outbound=True)
215
-
216
- def detach_inbound(self, node_obj, edge_set=None, silent=True):
217
- """
218
- Destroy edges from a node
219
- edge_set is the list of edges to be detached (and distroyed)
220
- all edges are deteached and destroyed if edge_set empty
221
- returns number of detachments
222
- """
223
- return self.detach(node_obj, edge_set, as_outbound=False)
224
-
225
- def detach_bidirected(self, node_obj, edge_set=None, silent=True):
226
- """
227
- Destroy bidirected edges between nodes
228
- edge_set is the list of edges to be detached (and distroyed)
229
- all edges are deteached and destroyed if edge_set empty
230
- returns number of detachments
231
- """
232
- return self.detach(node_obj, edge_set, as_bidirected=True)
233
-
234
- def detach_edges(self, node_obj, edge_set=None, silent=True):
235
- """
236
- Destroy given edges between nodes without checking orientation
237
- edge_set is the list of edges to be detached (and distroyed)
238
- all edges are deteached and destroyed if edge_set empty
239
- returns number of detachments
240
- """
241
- return self.detach(node_obj, edge_set, ignore_direction=True)
242
-
243
- def destroy_outbound(self, node_obj, edge_set=None):
244
- """
245
- Destroys attached node and all relevant edges
246
- Node and all edges are destroyed if edge_set empty
247
- """
248
- if edge_set is None:
249
- edge_set = self.outbound_edges(node_obj)
250
- if self.detach_outbound(node_obj, edge_set):
251
- node_obj.destroy()
252
-
253
- def destroy_inbound(self, node_obj, edge_set=None):
254
- """
255
- Destroys attached node and all relevant edges
256
- Node and all edges are destroyed if edge_set empty
257
- """
258
- if edge_set is None:
259
- edge_set = self.inbound_edges(node_obj)
260
- if self.detach_inbound(node_obj, edge_set):
261
- node_obj.destroy()
262
-
263
- def destroy_bidirected(self, node_obj, edge_set=None):
264
- """
265
- Destroys attached node and all relevant edges
266
- Node and all edges are destroyed if edge_set empty
267
- """
268
- if edge_set is None:
269
- edge_set = self.bidirected_edges(node_obj)
270
- if self.detach_bidirected(node_obj, edge_set):
271
- node_obj.destroy()
272
-
273
- def is_attached_out(self, node_obj, edge_set=None):
274
- """
275
- Tests whether edges attach to a node
276
- """
277
- out_set = self.outbound_edges(node_obj)
278
- if edge_set is None:
279
- return len(out_set)
280
- else:
281
- for e in edge_set:
282
- if e not in out_set:
283
- return False
284
- return True
285
-
286
- def is_attached_in(self, node_obj, edge_set=None):
287
- """
288
- Tests whether edges attach from a node
289
- """
290
- in_set = self.inbound_edges(node_obj)
291
- if edge_set is None:
292
- return len(in_set)
293
- else:
294
- for e in edge_set:
295
- if e not in in_set:
296
- return False
297
- return True
298
-
299
- def is_attached_bi(self, node_obj, edge_set=None):
300
- """
301
- Tests whether edges attach either to or from a node
302
- """
303
- bi_set = self.bidirected_edges(node_obj)
304
- if edge_set is None:
305
- return len(bi_set)
306
- else:
307
- for e in edge_set:
308
- if e not in bi_set:
309
- return False
310
- return True
311
-
312
- def outbound_edges(self, node_obj=None):
313
- """Returns list of all edges out of node"""
314
- edge_set = []
315
- for e in self.smart_edges:
316
- if not e.is_bidirected() and e.connects(self, node_obj):
317
- edge_set.append(e)
318
- return edge_set
319
-
320
- def inbound_edges(self, node_obj=None):
321
- """Returns list of all edges in to node"""
322
- edge_set = []
323
- for e in self.smart_edges:
324
- if not e.is_bidirected() and e.connects(node_obj, self):
325
- edge_set.append(e)
326
- return edge_set
327
-
328
- def bidirected_edges(self, node_obj=None):
329
- """Returns list of all edges between nodes"""
330
- edge_set = []
331
- for e in self.smart_edges:
332
- if e.is_bidirected() and e.connects(self, node_obj):
333
- edge_set.append(e)
334
- return edge_set
335
-
336
- def attached_edges(self, node_obj=None, silent=False):
337
- """
338
- Returns the edges connecting self to or from a node
339
-
340
- silent is used to indicate whther the edge is intened to be used.
341
- (effectively turns off error checking when false)
342
- """
343
- edge_set = (
344
- self.outbound_edges(node_obj)
345
- + self.inbound_edges(node_obj)
346
- + self.bidirected_edges(node_obj)
347
- )
348
- if not silent and edge_set is None:
349
- logger.error(str(f"No edges found between {self} and {node_obj}"))
350
- return edge_set
351
-
352
- def outbound_nodes(self, edge_set=None):
353
- """Returns list of all nodes connected by edges out"""
354
- if edge_set is None:
355
- edge_set = self.smart_edges
356
- ret_list = []
357
- for e in edge_set:
358
- if not e.is_bidirected() and e.connects(source=self):
359
- ret_list.append(e.to_node())
360
- return ret_list
361
-
362
- def inbound_nodes(self, edge_set=None):
363
- """Returns list of all nodes connected by edges in"""
364
- if edge_set is None:
365
- edge_set = self.smart_edges
366
- ret_list = []
367
- for e in edge_set:
368
- if not e.is_bidirected() and e.connects(target=self):
369
- ret_list.append(e.from_node())
370
- return ret_list
371
-
372
- def bidirected_nodes(self, edge_set=None):
373
- """Returns list of all nodes connected by edges"""
374
- if edge_set is None:
375
- edge_set = self.smart_edges
376
- ret_list = []
377
- for e in edge_set:
378
- if e.is_bidirected():
379
- ret_list.append(e.opposing_node(self))
380
- return ret_list
381
-
382
- def attached_nodes(self):
383
- """Returns list of all nodes connected"""
384
- edge_set = self.smart_edges
385
- ret_list = []
386
- for e in edge_set:
387
- ret_list.append(e.opposing_node(self))
388
- return ret_list
389
-
390
- def dimension_matches(self, node_obj, silent=True):
391
- """Test if dimension matches another node"""
392
- matches = self.dimension == node_obj.dimension
393
- if not matches and not silent:
394
- logger.error(
395
- str(
396
- "'{}' cant connect to '{}' - dim mismatch {}->{}".format(
397
- self, node_obj, self.dimension, node_obj.dimension
398
- )
399
- )
400
- )
401
- return matches
402
-
403
- def make_member_of(self, node_obj):
404
- """
405
- Adds node to higher dimension node and does relevant checks
406
- """
407
- # check if valid inclusion
408
- if node_obj.dimension != self.dimension + 1:
409
- logger.error(
410
- str(
411
- "'{}' cant be member to '{}' - dimension mismatch {}->{}".format(
412
- self, node_obj, self.dimension, node_obj.dimension
413
- )
414
- )
415
- )
416
- # adds self to hdgd and hdgd to list of owners
417
- else:
418
- node_obj.member_node_ids.add_obj(self)
419
- self.parent_node_ids.add_obj(node_obj)
420
-
421
- def make_owner_of(self, node_obj):
422
- """
423
- Adds node to lower dimension node and does relevant checks
424
- """
425
- node_obj.make_member_of(self)
426
-
427
- def leave_memebership_of(self, node_obj):
428
- """Remove node from higher dimension node"""
429
- node_obj.member_node_ids.remove_obj(self)
430
- self.parent_node_ids.remove_obj(node_obj)
431
-
432
- def disown(self, node_obj):
433
- """Remove node from higher dimension node"""
434
- node_obj.leave_membership_of(self)
435
-
436
- def destroy(self):
437
- """
438
- Destroys self from memory and persistent storage
439
- """
440
- for i in self.smart_edges:
441
- i.destroy()
442
- super().destroy()
443
-
444
- def dot_str(self, node_map=None, detailed=False):
445
- """
446
- DOT representation
447
- """
448
-
449
- def handle_str(str):
450
- return str[:32].replace('"', '\\"')
451
-
452
- if node_map is None:
453
- nid = f"{uuid.UUID(self.jid).hex}"
454
- else:
455
- nid = f"{node_map.index(self.jid)}"
456
-
457
- dstr = f'"n{nid}" [ '
458
-
459
- if detailed:
460
- dstr += f'id="{uuid.UUID(self.jid).hex}", '
461
-
462
- dstr += f'label="n{nid}:{self.name}" '
463
-
464
- node_dict = self.context
465
- for i in self.private_values():
466
- node_dict.pop(i)
467
-
468
- if node_dict and detailed:
469
- for k, v in node_dict.items():
470
- if not isinstance(v, str) or v == "":
471
- continue
472
- dstr += f', {k}="{handle_str(v)}"'
473
-
474
- dstr += " ]"
475
-
476
- return dstr + "\n"
477
-
478
- def get_all_architypes(self, depth: int = 0):
479
- """
480
- Returns all reachable architypes
481
- """
482
-
483
- childs = {self.jid: self}
484
-
485
- edges = OrderedDict()
486
- nodes = OrderedDict(childs)
487
-
488
- depth -= 1
489
-
490
- while len(childs) and depth != 0:
491
- new_childs = OrderedDict()
492
-
493
- for node in childs.values():
494
- for edge in node.attached_edges():
495
- if not (edge.jid in edges):
496
- n_node = False
497
- to_node = edge.to_node()
498
-
499
- if to_node == node:
500
- n_node = edge.from_node()
501
- else:
502
- n_node = to_node
503
-
504
- if not (n_node.jid in nodes):
505
- edges.update({edge.jid: edge})
506
- new_childs.update({n_node.jid: n_node})
507
- else:
508
- edges.update({edge.jid: edge})
509
-
510
- childs = new_childs
511
- nodes.update(childs)
512
- depth -= 1
513
-
514
- return nodes, edges
515
-
516
- def traversing_dot_str(self, detailed=False, depth: int = 0):
517
- """
518
- DOT representation for graph.
519
- NOTE: This is different from the dot_str method for node intentionally
520
- because graph inherits node.
521
- """
522
- nodes, edges = self.get_all_architypes(depth)
523
-
524
- # Construct the graph string
525
- dstr = ""
526
- dstr += f"strict digraph {self.name} {{\n"
527
- for n in nodes.values():
528
- dstr += f" {n.dot_str(list(nodes.keys()), detailed)}"
529
- for e in edges.values():
530
- dstr += f" {e.dot_str(list(nodes.keys()), list(edges.keys()), detailed)}"
531
- dstr += "}"
532
- return dstr