memory-graph 0.3.30__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.
@@ -0,0 +1,322 @@
1
+ # This file is part of memory_graph.
2
+ # Copyright (c) 2023, Bas Terwijn.
3
+ # SPDX-License-Identifier: BSD-2-Clause
4
+
5
+ import memory_graph.memory_to_nodes as memory_to_nodes
6
+ import memory_graph.config as config
7
+ import memory_graph.config_default
8
+ import memory_graph.config_helpers as config_helper
9
+ import memory_graph.utils as utils
10
+
11
+ import inspect
12
+ import sys
13
+ import itertools as it
14
+ from memory_graph.call_stack import call_stack
15
+
16
+ import graphviz
17
+
18
+ # Add 'mg' to builtins so it is available in all subsequent imports
19
+ import memory_graph as mg
20
+ import builtins
21
+ if not hasattr(builtins, "mg"):
22
+ builtins.mg = mg
23
+
24
+ __version__ = "0.3.30"
25
+ __author__ = 'Bas Terwijn'
26
+ render_filename = 'memory_graph.pdf'
27
+ render_filename_count = 0
28
+ last_show_filename = None
29
+ block_prints_location = True
30
+ press_enter_message = "Press <Enter> to continue..."
31
+
32
+ def get_source_location(stack_index=0):
33
+ """ Helper function to get the source location of the stack with 'stack_index' of the call stack. """
34
+ frameInfo = inspect.stack()[1+stack_index] # get frameInfo of calling frame
35
+ filename= frameInfo.filename
36
+ line_nr= frameInfo.lineno
37
+ function = frameInfo.function
38
+ return f'{filename}:{line_nr} in "{function}"'
39
+
40
+ def block(fun=None, *args, **kwargs):
41
+ """
42
+ Calls the given function `fun` with specified arguments and keyword arguments,
43
+ waits for the user to press Enter, and returns the result of `fun`.
44
+ """
45
+ stack_index = 0
46
+ if 'stack_index' in kwargs:
47
+ stack_index = kwargs['stack_index']
48
+ del kwargs['stack_index']
49
+ result = None
50
+ if callable(fun):
51
+ result = fun(*args, **kwargs)
52
+ if memory_graph.block_prints_location:
53
+ print('blocked at ' + get_source_location(1+stack_index), end=', ')
54
+ if memory_graph.press_enter_message:
55
+ print(memory_graph.press_enter_message)
56
+ input()
57
+ return result
58
+
59
+ def block_deprecated_message():
60
+ print("Warning: 'block=True' deprecated, use mg.block(fun) instead.")
61
+ input(f"{get_source_location(3)}, Press <Enter> to continue...")
62
+
63
+ def create_graph(data,
64
+ colors = None,
65
+ vertical_orientations = None,
66
+ slicers = None):
67
+ """ Creates and returns a memory graph from 'data'. """
68
+ config_helper.set_config(colors, vertical_orientations, slicers)
69
+ graphviz_graph = memory_to_nodes.memory_to_nodes(data)
70
+ return graphviz_graph
71
+
72
+ def number_filename(outfile):
73
+ """ Returns the 'outfile' with 'render_filename_count'. """
74
+ global render_filename_count
75
+ splits = outfile.split('.')
76
+ if len(splits)>1:
77
+ splits[-2]+=str(render_filename_count)
78
+ render_filename_count += 1
79
+ return '.'.join(splits)
80
+ return self.filename
81
+
82
+ def render(data, outfile=None, view=False, block=False,
83
+ colors = None,
84
+ vertical_orientations = None,
85
+ slicers = None,
86
+ numbered = False):
87
+ """ Renders the graph of 'data' to 'outfile' or `memory_graph.render_filename` when not specified. """
88
+ if outfile is None:
89
+ outfile = memory_graph.render_filename
90
+ graph = create_graph(data, colors, vertical_orientations, slicers)
91
+ if numbered:
92
+ outfile = number_filename(outfile)
93
+ if outfile.endswith('.gv') or outfile.endswith('.dot'):
94
+ graph.save(filename=outfile)
95
+ else:
96
+ graph.render(outfile=outfile, view=view, cleanup=False, quiet=False, quiet_view=False)
97
+ if block:
98
+ block_deprecated_message()
99
+
100
+ def show(data, outfile=None, view=False, block=False,
101
+ colors = None,
102
+ vertical_orientations = None,
103
+ slicers = None,
104
+ numbered = False):
105
+ """ Shows the graph of 'data' by first rendering and then opening the default viewer
106
+ application by file extension at first call, when the outfile changes, or
107
+ when view is True. """
108
+ if outfile is None:
109
+ outfile = memory_graph.render_filename
110
+ open_view = (outfile != memory_graph.last_show_filename) or view
111
+ render(data=data, outfile=outfile, view=open_view, block=block,
112
+ colors=colors,
113
+ vertical_orientations=vertical_orientations,
114
+ slicers=slicers, numbered=numbered)
115
+ memory_graph.last_show_filename = outfile
116
+
117
+
118
+ # ------------ aliases
119
+
120
+ def sl(stack_index=0, colors = None, vertical_orientations = None, slicers = None):
121
+ """
122
+ Shows the graph of locals() and blocks.
123
+ """
124
+ data = get_locals_from_call_stack(stack_index=1+stack_index)
125
+ memory_graph.show(data, colors=colors, vertical_orientations=vertical_orientations, slicers=slicers)
126
+
127
+ def ss(stack_index=0, colors = None, vertical_orientations = None, slicers = None):
128
+ """
129
+ Shows the graph of mg.stack() and blocks.
130
+ """
131
+ data = stack(stack_index=1+stack_index)
132
+ memory_graph.show(data, colors=colors, vertical_orientations=vertical_orientations, slicers=slicers)
133
+
134
+ def bsl(stack_index=0, colors = None, vertical_orientations = None, slicers = None):
135
+ """
136
+ Shows the graph of locals() and blocks.
137
+ """
138
+ data = get_locals_from_call_stack(stack_index=1+stack_index)
139
+ memory_graph.block(memory_graph.show, data, stack_index=1+stack_index, block=False,
140
+ colors=colors, vertical_orientations=vertical_orientations, slicers=slicers)
141
+
142
+ def bss(stack_index=0, colors = None, vertical_orientations = None, slicers = None):
143
+ """
144
+ Shows the graph of mg.stack() and blocks.
145
+ """
146
+ data = stack(stack_index=1+stack_index)
147
+ memory_graph.block(memory_graph.show, data, stack_index=1+stack_index, block=False,
148
+ colors=colors, vertical_orientations=vertical_orientations, slicers=slicers)
149
+
150
+ def rl(stack_index=0, colors = None, vertical_orientations = None, slicers = None):
151
+ """
152
+ Shows the graph of locals() and blocks.
153
+ """
154
+ data = get_locals_from_call_stack(stack_index=1+stack_index)
155
+ memory_graph.render(data, block=False, colors=colors, vertical_orientations=vertical_orientations, slicers=slicers)
156
+
157
+ def rs(stack_index=0, colors = None, vertical_orientations = None, slicers = None):
158
+ """
159
+ Shows the graph of mg.stack() and blocks.
160
+ """
161
+ data = stack(stack_index=1+stack_index)
162
+ memory_graph.render(data, block=False, colors=colors, vertical_orientations=vertical_orientations, slicers=slicers)
163
+
164
+ def brl(stack_index=0, colors = None, vertical_orientations = None, slicers = None):
165
+ """
166
+ Shows the graph of locals() and blocks.
167
+ """
168
+ data = get_locals_from_call_stack(stack_index=1+stack_index)
169
+ memory_graph.block(memory_graph.render, data, stack_index=1+stack_index, block=False,
170
+ colors=colors, vertical_orientations=vertical_orientations, slicers=slicers)
171
+
172
+ def brs(stack_index=0, colors = None, vertical_orientations = None, slicers = None):
173
+ """
174
+ Shows the graph of mg.stack() and blocks.
175
+ """
176
+ data = stack(stack_index=1+stack_index)
177
+ memory_graph.block(memory_graph.render, data, stack_index=1+stack_index, block=False,
178
+ colors=colors, vertical_orientations=vertical_orientations, slicers=slicers)
179
+
180
+ def l(stack_index=0, colors = None, vertical_orientations = None, slicers = None):
181
+ """
182
+ Shows the graph of locals() and blocks.
183
+ """
184
+ bsl(stack_index=1+stack_index, colors=colors, vertical_orientations=vertical_orientations, slicers=slicers)
185
+
186
+ def s(stack_index=0, colors = None, vertical_orientations = None, slicers = None):
187
+ """
188
+ Shows the graph of mg.stack() and blocks.
189
+ """
190
+ bss(stack_index=1+stack_index, colors=colors, vertical_orientations=vertical_orientations, slicers=slicers)
191
+
192
+
193
+ # ------------ call stack
194
+
195
+ def get_locals_from_call_stack(stack_index=0):
196
+ """ Helper function to get locals of the stack with 'stack_inex' of the call stack. """
197
+ frameInfo = inspect.stack()[1+stack_index] # get frameInfo of calling frame
198
+ return frameInfo.frame.f_locals
199
+
200
+ def get_function_name(frameInfo):
201
+ frame = frameInfo.frame
202
+ func_name = frame.f_code.co_name
203
+ if 'self' in frame.f_locals: # instance method
204
+ return f"{frame.f_locals['self'].__class__.__name__}.{func_name}"
205
+ elif 'cls' in frame.f_locals: # class method
206
+ return f"{frame.f_locals['cls'].__name__}.{func_name}"
207
+ else: # forget about static method, too complex
208
+ return func_name # just the function
209
+
210
+ def stack_frames_to_dict(frames):
211
+ """ Returns a dictionary representing the data on the call stack.
212
+ Each key is the stack level and function name, each value is the locals of the frame at that level.
213
+ """
214
+ def to_dict(value): # fix by TerenceTux for Python 3.13
215
+ return {k: v for k, v in value.items()}
216
+ return call_stack({f"{level}: {get_function_name(frameInfo)}" : to_dict(frameInfo.frame.f_locals)
217
+ for level, frameInfo in enumerate(frames)})
218
+
219
+ def locals():
220
+ """ Returns local variables. """
221
+ return locals()
222
+
223
+ def stack(through_function="<module>",stack_index=0):
224
+ return get_call_stack(through_function, 1+stack_index)
225
+ def get_call_stack(through_function="<module>",stack_index=0):
226
+ """ Gets the call stack up to and including the function 'through_function'. """
227
+ frames = reversed(list(
228
+ utils.take_through(lambda i: i.function==through_function, inspect.stack()[1+stack_index:])
229
+ ))
230
+ return stack_frames_to_dict(frames)
231
+
232
+ def stack_after_through(after_function,through_function="<module>"):
233
+ return get_call_stack_after_through(after_function, through_function)
234
+ def get_call_stack_after_through(after_function,through_function="<module>", drop=0):
235
+ """ Gets the call stack after the function 'after_function' up to and includeing the function 'through_function'
236
+ and drops the first 'drop' stack frames. """
237
+ frames = reversed(list(it.islice(
238
+ utils.take_through(lambda i: i.function == through_function,
239
+ utils.take_after(lambda i: i.function == after_function, inspect.stack()))
240
+ , drop, None)))
241
+ return stack_frames_to_dict(frames)
242
+
243
+ def stack_pdb(after_function="trace_dispatch",through_function="<module>"):
244
+ return get_call_stack_pdb(after_function, through_function)
245
+ def get_call_stack_pdb(after_function="trace_dispatch",through_function="<module>"):
246
+ """ Get the call stack in a 'pdb' debugger session, filtering out the 'pdb' functions that polute the graph. """
247
+ return get_call_stack_after_through(after_function,through_function)
248
+
249
+ def stack_vscode(after_function="do_wait_suspend",through_function="<module>"):
250
+ return get_call_stack_vscode(after_function, through_function)
251
+ def get_call_stack_vscode(after_function="do_wait_suspend",through_function="<module>"):
252
+ """ Get the call stack in a 'vscode' debugger session, filtering out the 'vscode' functions that polute the graph. """
253
+ return get_call_stack_after_through(after_function,through_function)
254
+
255
+ def stack_cursor(after_function="do_wait_suspend",through_function="<module>"):
256
+ return get_call_stack_cursor(after_function, through_function)
257
+ def get_call_stack_cursor(after_function="do_wait_suspend",through_function="<module>"):
258
+ """ Get the call stack in a 'cursor' debugger session, filtering out the 'cursor' functions that polute the graph. """
259
+ return get_call_stack_after_through(after_function,through_function)
260
+
261
+ def stack_pycharm(after_function="do_wait_suspend",through_function="<module>"):
262
+ return get_call_stack_pycharm(after_function, through_function)
263
+ def get_call_stack_pycharm(after_function="do_wait_suspend",through_function="<module>"):
264
+ """ Get the call stack in a 'vscode' debugger session, filtering out the 'vscode' functions that polute the graph. """
265
+ return get_call_stack_after_through(after_function,through_function, 1)
266
+
267
+ def save_call_stack(filename):
268
+ """ Saves the call stack to 'filename' for inspection to see what functions need to be
269
+ filtered out to create the desired graph. """
270
+ with open(filename,'w') as file:
271
+ for frame in inspect.stack():
272
+ file.write(f"function:{frame.function} filename:{frame.filename}\n")
273
+
274
+ def print_call_stack_vars(stack_index=0):
275
+ """ Prints all variables on the call stack. """
276
+ for level, frameInfo in enumerate(reversed(inspect.stack())):
277
+ print('=====',level,frameInfo.function)
278
+ print(tuple(frameInfo.frame.f_locals.keys()))
279
+
280
+
281
+ # ------------ jupyter filtering
282
+
283
+ jupyter_filter_keys = {'exit','quit','v','In','Out','jupyter_filter_keys'}
284
+ def jupyter_locals_filter(jupyter_locals):
285
+ """ Filter out the jupyter specific keys that polute the graph. """
286
+ return {k:v for k,v in utils.filter_dict(jupyter_locals)
287
+ if k not in jupyter_filter_keys and k[0] != '_'}
288
+
289
+ def locals_jupyter(stack_index=0):
290
+ """ Get the locals of the calling frame in a jupyter notebook, filtering out the jupyter specific keys. """
291
+ return jupyter_locals_filter(get_locals_from_call_stack(1+stack_index))
292
+
293
+ def stack_jupyter(through_function="<module>",stack_index=0):
294
+ return get_call_stack_jupyter(through_function, 1+stack_index)
295
+ def get_call_stack_jupyter(through_function="<module>",stack_index=0):
296
+ """ Get the call stack in a jupyter notebook, filtering out the jupyter specific keys. """
297
+ call_stack = get_call_stack(through_function,1+stack_index)
298
+ globals_frame = next(iter(call_stack))
299
+ call_stack[globals_frame] = jupyter_locals_filter(call_stack[globals_frame])
300
+ return call_stack
301
+
302
+
303
+ # ------------ ipython filtering
304
+
305
+ ipython_filter_keys = {'mg_visualization_status', 'sys', 'ipython', 'In', 'Out', 'get_ipython', 'exit', 'quit', 'open'}
306
+ def ipython_locals_filter(ipython_locals):
307
+ """ Filter out the ipython specific keys that polute the graph. """
308
+ return {k:v for k,v in utils.filter_dict(ipython_locals)
309
+ if k not in ipython_filter_keys and k[0] != '_'}
310
+
311
+ def locals_ipython(stack_index=0):
312
+ """ Get the locals of the calling frame in a ipython, filtering out the ipython specific keys. """
313
+ return ipython_locals_filter(get_locals_from_call_stack(1+stack_index))
314
+
315
+ def stack_ipython(through_function="<module>",stack_index=0):
316
+ return get_call_stack_ipython(through_function, 1+stack_index)
317
+ def get_call_stack_ipython(through_function="<module>",stack_index=0):
318
+ """ Get the call stack in a ipython, filtering out the ipython specific keys. """
319
+ call_stack = get_call_stack(through_function,1+stack_index)
320
+ globals_frame = next(iter(call_stack))
321
+ call_stack[globals_frame] = ipython_locals_filter(call_stack[globals_frame])
322
+ return call_stack
@@ -0,0 +1,9 @@
1
+ # This file is part of memory_graph.
2
+ # Copyright (c) 2023, Bas Terwijn.
3
+ # SPDX-License-Identifier: BSD-2-Clause
4
+
5
+ class call_stack(dict):
6
+ """Inherits from dict to give the call stack it own name and color. """
7
+
8
+ def __init__(self, *args, **kwargs):
9
+ super().__init__(*args, **kwargs)
memory_graph/config.py ADDED
@@ -0,0 +1,35 @@
1
+ # This file is part of memory_graph.
2
+ # Copyright (c) 2023, Bas Terwijn.
3
+ # SPDX-License-Identifier: BSD-2-Clause
4
+
5
+ """ Configuration file for the graph visualizer. The configuration values are set later by the 'config_default.py' file. """
6
+
7
+
8
+ max_string_length = None
9
+ graph_stability = None
10
+
11
+ not_node_types = {}
12
+ no_child_references_types = set()
13
+
14
+ type_to_string = { }
15
+
16
+ def to_string(data):
17
+ """ Convert data to string. """
18
+ data_type = type(data)
19
+ if data_type in type_to_string:
20
+ return type_to_string[data_type](data)
21
+ return str(data)
22
+
23
+ type_to_node = { }
24
+
25
+ type_to_color = { }
26
+
27
+ type_to_vertical_orientation = { }
28
+
29
+ type_to_slicer = { }
30
+
31
+ max_graph_depth = None
32
+ graph_cut_symbol = None
33
+ max_missing_edges = None
34
+
35
+ type_to_depth = { }
@@ -0,0 +1,108 @@
1
+ # This file is part of memory_graph.
2
+ # Copyright (c) 2023, Bas Terwijn.
3
+ # SPDX-License-Identifier: BSD-2-Clause
4
+
5
+ """ Sets the default configuration values for the memory graph. """
6
+ from memory_graph.node_leaf import Node_Leaf
7
+ from memory_graph.node_linear import Node_Linear
8
+ from memory_graph.node_key_value import Node_Key_Value
9
+ from memory_graph.node_table import Node_Table
10
+
11
+ from memory_graph.call_stack import call_stack
12
+ from memory_graph.slicer import Slicer
13
+
14
+ import memory_graph.config as config
15
+ import memory_graph.utils as utils
16
+
17
+ import types
18
+
19
+
20
+ """ The maximum length of strings shown in the graph. Longer strings will be truncated. """
21
+ config.max_string_length = 42
22
+
23
+ """ The number of references keeping child nodes in order versus other references pulling them out. """
24
+ config.graph_stability = 10
25
+
26
+ """ Types that by default will not have references pointing to them in the graph but instead will be visualized in the node of their parent. """
27
+ config.not_node_types = {
28
+ type(None), bool, int, float, complex, str,
29
+ types.FunctionType,
30
+ types.MethodType,
31
+ classmethod,
32
+ staticmethod,
33
+ type(len),
34
+ }
35
+
36
+ """ Types that will not have references pointing to their children in the graph but instead will have their children visualized in their node. """
37
+ config.no_child_references_types = {dict, types.MappingProxyType}
38
+
39
+ """ Types that need an special conversion """
40
+ config.type_to_string = {
41
+ types.FunctionType: lambda data: data.__qualname__,
42
+ types.MethodType: lambda data: data.__qualname__,
43
+ classmethod: lambda data: data.__qualname__,
44
+ staticmethod: lambda data: data.__qualname__,
45
+ type(len): lambda data: data.__qualname__,
46
+ }
47
+
48
+ """ Conversion from type to Node objects. """
49
+ config.type_to_node = {
50
+ str: lambda data: Node_Leaf(data, data), # visit as whole string, don't iterate over characters
51
+ call_stack: lambda data: Node_Key_Value(data, data.items()),
52
+ type: lambda data: Node_Key_Value(data, utils.filter_type_attributes(vars(data).items())),
53
+ range: lambda data: Node_Key_Value(data, {'start':data.start, 'stop':data.stop, 'step':data.step}.items()),
54
+ dict: lambda data: (
55
+ Node_Key_Value(data, utils.filter_dict(data) )
56
+ if dict in config.no_child_references_types else
57
+ Node_Linear(data, utils.filter_dict(data) )
58
+ ),
59
+ }
60
+
61
+ """ Colors of different types in the graph. """
62
+ config.type_to_color = {
63
+ # ================= singular
64
+ type(None) : "gray",
65
+ bool : "pink",
66
+ int : "green",
67
+ float : "violetred1",
68
+ complex : "yellow",
69
+ str : "cyan",
70
+ # ================= linear
71
+ tuple : "orange",
72
+ list : "lightcoral",
73
+ set : "orchid1",
74
+ frozenset : "orchid2",
75
+ bytes : "khaki1",
76
+ bytearray : "khaki2",
77
+ # ================= key_value
78
+ Node_Key_Value : "seagreen1", # for classes
79
+ call_stack : 'khaki',
80
+ type: "seagreen3", # where class variables are stored
81
+ dict : "#60a5ff",
82
+ types.MappingProxyType : "dodgerblue2", # not used
83
+ range : "cornsilk2",
84
+ }
85
+
86
+ """ Types that will be visualized in vertical orientation if 'True', or horizontal orientation
87
+ if 'False'. Otherwise the Node decides based on it having references."""
88
+ config.type_to_vertical_orientation = {
89
+ }
90
+
91
+ """ Slicer objects for different types. """
92
+ config.type_to_slicer = {
93
+ Node_Linear: Slicer(5,3,5),
94
+ Node_Key_Value: Slicer(5,3,5),
95
+ Node_Table: (Slicer(3,2,3), Slicer(3,2,3)),
96
+ }
97
+
98
+ """ The maximum depth of nodes in the graph. When the graph gets too big set this to a small positive number. A `✂` symbol indictes where the graph is cut short. """
99
+ config.max_graph_depth = 12
100
+ config.graph_cut_symbol = '✂'
101
+
102
+
103
+ """ Maximum introspection depth for different types. """
104
+ config.type_to_depth = {
105
+ }
106
+
107
+ """ Maximum number of missing edges that are shown. """
108
+ config.max_missing_edges = 2
@@ -0,0 +1,56 @@
1
+ # This file is part of memory_graph.
2
+ # Copyright (c) 2023, Bas Terwijn.
3
+ # SPDX-License-Identifier: BSD-2-Clause
4
+
5
+ """ This module provides helper functions to access the configuration of the memory graph. """
6
+ from memory_graph.slicer import Slicer
7
+
8
+ import memory_graph.config as config
9
+
10
+ type_to_color = None
11
+ type_to_vertical_orientation = None
12
+ type_to_slicer = None
13
+
14
+ def set_config(colors=None, vertical_orientations=None, slicers=None):
15
+ global type_to_color
16
+ global type_to_vertical_orientation
17
+ global type_to_slicer
18
+ type_to_color = config.type_to_color.copy()
19
+ type_to_vertical_orientation = config.type_to_vertical_orientation.copy()
20
+ type_to_slicer = config.type_to_slicer.copy()
21
+ if colors:
22
+ type_to_color |= colors
23
+ if vertical_orientations:
24
+ type_to_vertical_orientation |= vertical_orientations
25
+ if slicers:
26
+ type_to_slicer |= slicers
27
+
28
+ def get_property(data_id, data_type, node_type, dictionary, default):
29
+ if data_id in dictionary:
30
+ return dictionary[data_id]
31
+ if data_type in dictionary:
32
+ return dictionary[data_type]
33
+ if node_type in dictionary:
34
+ return dictionary[node_type]
35
+ return default
36
+
37
+ def get_color(node, default='white'):
38
+ return get_property(node.get_id(),
39
+ node.get_type(),
40
+ type(node),
41
+ type_to_color,
42
+ default)
43
+
44
+ def get_vertical_orientation(node, default):
45
+ return get_property(node.get_id(),
46
+ node.get_type(),
47
+ type(node),
48
+ type_to_vertical_orientation,
49
+ default)
50
+
51
+ def get_slicer(node, data, default=Slicer(3,2,3)):
52
+ return get_property(id(data),
53
+ type(data),
54
+ type(node),
55
+ type_to_slicer,
56
+ default)
@@ -0,0 +1,30 @@
1
+ # This file is part of memory_graph.
2
+ # Copyright (c) 2023, Bas Terwijn.
3
+ # SPDX-License-Identifier: BSD-2-Clause
4
+
5
+ """ Extension to add the memory graph configuration for Numpy types. """
6
+ from memory_graph.node_linear import Node_Linear
7
+ from memory_graph.node_table import Node_Table
8
+
9
+ import memory_graph.config as config
10
+
11
+ import numpy as np
12
+
13
+ config.not_node_types |= {
14
+ np.int8, np.int16, np.int32, np.int64, np.uint8, np.uint16, np.uint32, np.uint64,
15
+ np.float16, np.float32, np.float64,
16
+ np.complex64, np.complex128,
17
+ np.bool_, np.bytes_, np.str_, np.datetime64, np.timedelta64
18
+ }
19
+
20
+ def ndarrayy_to_node(ndarrayy_data):
21
+ if len(ndarrayy_data.shape) == 2:
22
+ return Node_Table(ndarrayy_data, ndarrayy_data)
23
+ else:
24
+ return Node_Linear(ndarrayy_data, ndarrayy_data)
25
+
26
+ config.type_to_node[np.matrix] = lambda data : Node_Table(data, np.asarray(data)) # convert to ndarray to avoid infinite recursion due to index issue
27
+ config.type_to_node[np.ndarray] = lambda data : ndarrayy_to_node(data)
28
+
29
+ config.type_to_color[np.ndarray] = "hotpink1"
30
+ config.type_to_color[np.matrix] = "hotpink2"
@@ -0,0 +1,26 @@
1
+ # This file is part of memory_graph.
2
+ # Copyright (c) 2023, Bas Terwijn.
3
+ # SPDX-License-Identifier: BSD-2-Clause
4
+
5
+ """ Extension to add the memory graph configuration for Pandas type. """
6
+ from memory_graph.node_linear import Node_Linear
7
+ from memory_graph.node_table import Node_Table
8
+
9
+ import memory_graph.config as config
10
+
11
+ import pandas as pd
12
+
13
+ config.type_to_node[pd.DataFrame] = lambda data : (
14
+ Node_Table(data,
15
+ data.values.tolist(),
16
+ col_names = data.columns.tolist(),
17
+ row_names = [ str(i) for i in data.index.tolist()]
18
+ )
19
+ )
20
+
21
+ config.type_to_node[pd.Series] = lambda data : (
22
+ Node_Linear(data, data.tolist())
23
+ )
24
+
25
+ config.type_to_color[pd.DataFrame] = "olivedrab1"
26
+ config.type_to_color[pd.Series] = "olivedrab2"