memory-graph 0.3.23__tar.gz → 0.3.25__tar.gz
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.
- {memory_graph-0.3.23/memory_graph.egg-info → memory_graph-0.3.25}/PKG-INFO +152 -78
- {memory_graph-0.3.23 → memory_graph-0.3.25}/README.md +151 -77
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/add_one.gv +20 -20
- memory_graph-0.3.25/images/add_one.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/avltree_dir.gv +6 -6
- memory_graph-0.3.25/images/avltree_dir.png +0 -0
- memory_graph-0.3.25/images/avltree_fail.gv +22 -0
- memory_graph-0.3.25/images/avltree_fail.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/avltree_key_value.gv +13 -13
- memory_graph-0.3.25/images/avltree_key_value.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/avltree_leaf.gv +6 -6
- memory_graph-0.3.25/images/avltree_leaf.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/avltree_linear.gv +13 -13
- memory_graph-0.3.25/images/avltree_linear.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/avltree_table.gv +13 -13
- memory_graph-0.3.25/images/avltree_table.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/bin_tree.gv +39 -39
- memory_graph-0.3.25/images/bin_tree.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/copies.gv +21 -21
- memory_graph-0.3.25/images/copies.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/copy_method.gv +17 -17
- memory_graph-0.3.25/images/copy_method.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/create_images.sh +1 -0
- memory_graph-0.3.25/images/debugging.gif +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/debugging01.gv +9 -9
- memory_graph-0.3.25/images/debugging01.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/debugging02.gv +12 -12
- memory_graph-0.3.25/images/debugging02.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/debugging03.gv +14 -14
- memory_graph-0.3.25/images/debugging03.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/debugging04.gv +16 -16
- memory_graph-0.3.25/images/debugging04.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/debugging05.gv +18 -18
- memory_graph-0.3.25/images/debugging05.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/debugging06.gv +18 -18
- memory_graph-0.3.25/images/debugging06.png +0 -0
- memory_graph-0.3.25/images/depth.gv +178 -0
- memory_graph-0.3.25/images/depth.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/extension_numpy.gv +31 -33
- memory_graph-0.3.25/images/extension_numpy.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/extension_pandas.gv +9 -11
- memory_graph-0.3.25/images/extension_pandas.png +0 -0
- memory_graph-0.3.25/images/factorial.gif +0 -0
- memory_graph-0.3.25/images/factorial.py +16 -0
- memory_graph-0.3.25/images/factorial0.gv +15 -0
- memory_graph-0.3.25/images/factorial0.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/factorial01.gv +4 -4
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/factorial02.gv +8 -8
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/factorial03.gv +11 -11
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/factorial04.gv +14 -14
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/factorial05.gv +14 -14
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/factorial06.gv +11 -11
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/factorial07.gv +8 -8
- memory_graph-0.3.25/images/factorial1.gv +22 -0
- memory_graph-0.3.25/images/factorial1.png +0 -0
- memory_graph-0.3.25/images/factorial2.gv +28 -0
- memory_graph-0.3.25/images/factorial2.png +0 -0
- memory_graph-0.3.25/images/factorial3.gv +34 -0
- memory_graph-0.3.25/images/factorial3.png +0 -0
- memory_graph-0.3.25/images/factorial4.gv +35 -0
- memory_graph-0.3.25/images/factorial4.png +0 -0
- memory_graph-0.3.25/images/factorial5.gv +29 -0
- memory_graph-0.3.25/images/factorial5.png +0 -0
- memory_graph-0.3.25/images/factorial6.gv +23 -0
- memory_graph-0.3.25/images/factorial6.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/hash_set.gv +30 -30
- memory_graph-0.3.25/images/hash_set.png +0 -0
- memory_graph-0.3.25/images/hidden_edges.gv +37 -0
- memory_graph-0.3.25/images/hidden_edges.png +0 -0
- memory_graph-0.3.25/images/hidden_edges.py +8 -0
- memory_graph-0.3.25/images/hidden_edges.py~ +9 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/highlight.gv +17 -23
- memory_graph-0.3.25/images/highlight.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/immutable1.gv +5 -5
- memory_graph-0.3.25/images/immutable1.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/immutable2.gv +7 -7
- memory_graph-0.3.25/images/immutable2.png +0 -0
- memory_graph-0.3.25/images/introspect_depth.gv +178 -0
- memory_graph-0.3.25/images/introspect_depth.png +0 -0
- memory_graph-0.3.25/images/introspect_depth.py +43 -0
- memory_graph-0.3.25/images/introspect_depth.py~ +26 -0
- memory_graph-0.3.25/images/linked_list.gv +55 -0
- memory_graph-0.3.25/images/linked_list.png +0 -0
- memory_graph-0.3.25/images/linked_list.py +35 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/many_types.gv +13 -13
- memory_graph-0.3.25/images/many_types.png +0 -0
- memory_graph-0.3.25/images/memory_graph.gv +70 -0
- memory_graph-0.3.25/images/memory_graph.pdf +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/mutable1.gv +5 -5
- memory_graph-0.3.25/images/mutable1.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/mutable2.gv +5 -5
- memory_graph-0.3.25/images/mutable2.png +0 -0
- memory_graph-0.3.25/images/my_graph.gv +31 -0
- memory_graph-0.3.25/images/my_graph.pdf +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/not_node_types1.gv +7 -7
- memory_graph-0.3.25/images/not_node_types1.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/not_node_types2.gv +15 -15
- memory_graph-0.3.25/images/not_node_types2.png +0 -0
- memory_graph-0.3.25/images/power_set.gif +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/power_set.py +4 -6
- memory_graph-0.3.25/images/power_set0.gv +38 -0
- memory_graph-0.3.25/images/power_set0.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/power_set1.gv +21 -21
- memory_graph-0.3.25/images/power_set1.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/power_set10.gv +42 -42
- memory_graph-0.3.25/images/power_set10.png +0 -0
- memory_graph-0.3.23/images/power_set12.gv → memory_graph-0.3.25/images/power_set11.gv +38 -38
- memory_graph-0.3.25/images/power_set11.png +0 -0
- memory_graph-0.3.23/images/power_set11.gv → memory_graph-0.3.25/images/power_set12.gv +38 -38
- memory_graph-0.3.25/images/power_set12.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/power_set13.gv +42 -42
- memory_graph-0.3.25/images/power_set13.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/power_set14.gv +48 -48
- memory_graph-0.3.25/images/power_set14.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/power_set15.gv +50 -50
- memory_graph-0.3.25/images/power_set15.png +0 -0
- memory_graph-0.3.23/images/power_set17.gv → memory_graph-0.3.25/images/power_set16.gv +48 -48
- memory_graph-0.3.25/images/power_set16.png +0 -0
- memory_graph-0.3.23/images/power_set16.gv → memory_graph-0.3.25/images/power_set17.gv +48 -48
- memory_graph-0.3.25/images/power_set17.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/power_set18.gv +52 -52
- memory_graph-0.3.25/images/power_set18.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/power_set19.gv +54 -54
- memory_graph-0.3.25/images/power_set19.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/power_set2.gv +27 -27
- memory_graph-0.3.25/images/power_set2.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/power_set20.gv +50 -50
- memory_graph-0.3.25/images/power_set20.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/power_set21.gv +44 -44
- memory_graph-0.3.25/images/power_set21.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/power_set22.gv +38 -38
- memory_graph-0.3.25/images/power_set22.png +0 -0
- memory_graph-0.3.25/images/power_set23.gv +93 -0
- memory_graph-0.3.25/images/power_set23.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/power_set3.gv +33 -33
- memory_graph-0.3.25/images/power_set3.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/power_set4.gv +39 -39
- memory_graph-0.3.25/images/power_set4.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/power_set5.gv +41 -41
- memory_graph-0.3.25/images/power_set5.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/power_set6.gv +38 -38
- memory_graph-0.3.25/images/power_set6.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/power_set7.gv +38 -38
- memory_graph-0.3.25/images/power_set7.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/power_set8.gv +44 -44
- memory_graph-0.3.25/images/power_set8.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/power_set9.gv +46 -46
- memory_graph-0.3.25/images/power_set9.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/rebinding1.gv +5 -5
- memory_graph-0.3.25/images/rebinding1.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/rebinding2.gv +7 -7
- memory_graph-0.3.25/images/rebinding2.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph/__init__.py +20 -5
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph/config.py +7 -3
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph/config_default.py +17 -9
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph/memory_to_nodes.py +10 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25/memory_graph.egg-info}/PKG-INFO +152 -78
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph.egg-info/SOURCES.txt +29 -7
- {memory_graph-0.3.23 → memory_graph-0.3.25}/setup.py +1 -1
- memory_graph-0.3.23/images/add_one.png +0 -0
- memory_graph-0.3.23/images/avltree_dir.png +0 -0
- memory_graph-0.3.23/images/avltree_fail.gv +0 -26
- memory_graph-0.3.23/images/avltree_fail.png +0 -0
- memory_graph-0.3.23/images/avltree_key_value.png +0 -0
- memory_graph-0.3.23/images/avltree_leaf.png +0 -0
- memory_graph-0.3.23/images/avltree_linear.png +0 -0
- memory_graph-0.3.23/images/avltree_table.png +0 -0
- memory_graph-0.3.23/images/bin_tree.png +0 -0
- memory_graph-0.3.23/images/copies.png +0 -0
- memory_graph-0.3.23/images/copy_method.png +0 -0
- memory_graph-0.3.23/images/debugging.gif +0 -0
- memory_graph-0.3.23/images/debugging01.png +0 -0
- memory_graph-0.3.23/images/debugging02.png +0 -0
- memory_graph-0.3.23/images/debugging03.png +0 -0
- memory_graph-0.3.23/images/debugging04.png +0 -0
- memory_graph-0.3.23/images/debugging05.png +0 -0
- memory_graph-0.3.23/images/debugging06.png +0 -0
- memory_graph-0.3.23/images/extension_numpy.png +0 -0
- memory_graph-0.3.23/images/extension_pandas.png +0 -0
- memory_graph-0.3.23/images/factorial.gif +0 -0
- memory_graph-0.3.23/images/factorial.py +0 -24
- memory_graph-0.3.23/images/factorial01.png +0 -0
- memory_graph-0.3.23/images/factorial02.png +0 -0
- memory_graph-0.3.23/images/factorial03.png +0 -0
- memory_graph-0.3.23/images/factorial04.png +0 -0
- memory_graph-0.3.23/images/factorial05.png +0 -0
- memory_graph-0.3.23/images/factorial06.png +0 -0
- memory_graph-0.3.23/images/factorial07.png +0 -0
- memory_graph-0.3.23/images/hash_set.png +0 -0
- memory_graph-0.3.23/images/highlight.png +0 -0
- memory_graph-0.3.23/images/immutable1.png +0 -0
- memory_graph-0.3.23/images/immutable2.png +0 -0
- memory_graph-0.3.23/images/linked_list.gv +0 -69
- memory_graph-0.3.23/images/linked_list.png +0 -0
- memory_graph-0.3.23/images/linked_list.py +0 -39
- memory_graph-0.3.23/images/many_types.png +0 -0
- memory_graph-0.3.23/images/memory_graph.pdf +0 -0
- memory_graph-0.3.23/images/mutable1.png +0 -0
- memory_graph-0.3.23/images/mutable2.png +0 -0
- memory_graph-0.3.23/images/my_graph.gv +0 -35
- memory_graph-0.3.23/images/my_graph.pdf +0 -0
- memory_graph-0.3.23/images/not_node_types1.png +0 -0
- memory_graph-0.3.23/images/not_node_types2.png +0 -0
- memory_graph-0.3.23/images/power_set.gif +0 -0
- memory_graph-0.3.23/images/power_set1.png +0 -0
- memory_graph-0.3.23/images/power_set10.png +0 -0
- memory_graph-0.3.23/images/power_set11.png +0 -0
- memory_graph-0.3.23/images/power_set12.png +0 -0
- memory_graph-0.3.23/images/power_set13.png +0 -0
- memory_graph-0.3.23/images/power_set14.png +0 -0
- memory_graph-0.3.23/images/power_set15.png +0 -0
- memory_graph-0.3.23/images/power_set16.png +0 -0
- memory_graph-0.3.23/images/power_set17.png +0 -0
- memory_graph-0.3.23/images/power_set18.png +0 -0
- memory_graph-0.3.23/images/power_set19.png +0 -0
- memory_graph-0.3.23/images/power_set2.png +0 -0
- memory_graph-0.3.23/images/power_set20.png +0 -0
- memory_graph-0.3.23/images/power_set21.png +0 -0
- memory_graph-0.3.23/images/power_set22.png +0 -0
- memory_graph-0.3.23/images/power_set3.png +0 -0
- memory_graph-0.3.23/images/power_set4.png +0 -0
- memory_graph-0.3.23/images/power_set5.png +0 -0
- memory_graph-0.3.23/images/power_set6.png +0 -0
- memory_graph-0.3.23/images/power_set7.png +0 -0
- memory_graph-0.3.23/images/power_set8.png +0 -0
- memory_graph-0.3.23/images/power_set9.png +0 -0
- memory_graph-0.3.23/images/rebinding1.png +0 -0
- memory_graph-0.3.23/images/rebinding2.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/LICENSE.txt +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/MANIFEST.in +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/.ipynb_checkpoints/jupyter_example-checkpoint.ipynb +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/add_one.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/avltree.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/avltree.py~ +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/bin_tree.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/bin_tree2.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/bin_tree2.py~ +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/copies.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/copy_method.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/create_gif.sh +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/debug_vscode.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/debugging.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/extension_numpy.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/extension_pandas.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/hash_set.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/highlight.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/immutable.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/ipython.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/jupyter_example.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/log.txt +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/many_types.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/memory_graph.gv.pdf +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/mutable.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/name_rebinding.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/not_node_types.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/not_node_types.py~ +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/pyodide.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/images/uva.png +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/install.txt +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph/call_stack.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph/config_helpers.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph/extension_numpy.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph/extension_pandas.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph/html_table.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph/list_view.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph/node_base.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph/node_key_value.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph/node_leaf.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph/node_linear.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph/node_table.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph/sequence.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph/slicer.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph/slices.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph/slices_iterator.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph/slices_table_iterator.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph/test.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph/test_max_graph_depth.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph/test_memory_graph.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph/test_memory_to_nodes.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph/test_sequence.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph/test_slicer.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph/test_slices.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph/test_slices_iterator.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph/utils.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph.egg-info/dependency_links.txt +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph.egg-info/requires.txt +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/memory_graph.egg-info/top_level.txt +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/setup.cfg +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/src/auto_memory_graph.py +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/src/jupyter_example.ipynb +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/src/pyodide.html +0 -0
- {memory_graph-0.3.23 → memory_graph-0.3.25}/uml/memory_graph.uxf +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: memory_graph
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.25
|
|
4
4
|
Summary: Generate intuitive graphs of your Python data, great for debugging and understanding complex relationships.
|
|
5
5
|
Home-page: https://github.com/bterwijn/memory_graph
|
|
6
6
|
Author: Bas Terwijn
|
|
@@ -24,6 +24,11 @@ pip install --upgrade memory_graph
|
|
|
24
24
|
```
|
|
25
25
|
Additionally [Graphviz](https://graphviz.org/download/) needs to be installed.
|
|
26
26
|
|
|
27
|
+
# Videos #
|
|
28
|
+
| [](https://www.youtube.com/watch?v=8csmPga6Upw) | [](https://www.youtube.com/watch?v=pvIJgHCaXhU) |
|
|
29
|
+
|:--:|:--:|
|
|
30
|
+
| [Quick Intro](https://www.youtube.com/watch?v=8csmPga6Upw) | [Mutability](https://www.youtube.com/watch?v=pvIJgHCaXhU) |
|
|
31
|
+
|
|
27
32
|
# Memory Graph #
|
|
28
33
|
For program understanding and debugging, the [memory_graph](https://pypi.org/project/memory-graph/) package can visualize your data, supporting many different data types, including but not limited to:
|
|
29
34
|
|
|
@@ -93,13 +98,6 @@ identical?: True
|
|
|
93
98
|
```
|
|
94
99
|
A better way to understand what data is shared is to draw a graph of the data using the [memory_graph](https://pypi.org/project/memory-graph/) package.
|
|
95
100
|
|
|
96
|
-
# Videos #
|
|
97
|
-
|
|
98
|
-
| [](https://www.youtube.com/watch?v=pvIJgHCaXhU) |
|
|
99
|
-
|:--:|
|
|
100
|
-
| [Mutability](https://www.youtube.com/watch?v=pvIJgHCaXhU) |
|
|
101
|
-
|
|
102
|
-
|
|
103
101
|
# Chapters #
|
|
104
102
|
|
|
105
103
|
[Python Data Model](#python-data-model)
|
|
@@ -108,7 +106,7 @@ A better way to understand what data is shared is to draw a graph of the data us
|
|
|
108
106
|
|
|
109
107
|
[Debugging](#Debugging)
|
|
110
108
|
|
|
111
|
-
[
|
|
109
|
+
[Data Structure Examples](#data-structure-examples)
|
|
112
110
|
|
|
113
111
|
[Configuration](#configuration)
|
|
114
112
|
|
|
@@ -116,6 +114,8 @@ A better way to understand what data is shared is to draw a graph of the data us
|
|
|
116
114
|
|
|
117
115
|
[Introspection](#introspection)
|
|
118
116
|
|
|
117
|
+
[Introspection Depth](#introspection-depth)
|
|
118
|
+
|
|
119
119
|
[Jupyter Notebook](#jupyter-notebook)
|
|
120
120
|
|
|
121
121
|
[ipython](#ipython)
|
|
@@ -137,14 +137,14 @@ Inspired by [Python Tutor](https://pythontutor.com/).
|
|
|
137
137
|
___
|
|
138
138
|
___
|
|
139
139
|
|
|
140
|
-
|
|
140
|
+
# Python Data Model #
|
|
141
141
|
The [Python Data Model](https://docs.python.org/3/reference/datamodel.html) makes a distiction between immutable and mutable types:
|
|
142
142
|
|
|
143
143
|
* **immutable**: bool, int, float, complex, str, tuple, bytes, frozenset
|
|
144
144
|
* **mutable**: list, set, dict, classes, ... (most other types)
|
|
145
145
|
|
|
146
146
|
|
|
147
|
-
|
|
147
|
+
## Immutable Type ##
|
|
148
148
|
In the code below variable `a` and `b` both reference the same tuple value (4, 3, 2). A tuple is an immutable type and therefore when we change variable `b` its value **cannot** be mutated in place, and thus an automatic copy is made and `a` and `b` reference a different value afterwards.
|
|
149
149
|
|
|
150
150
|
```python
|
|
@@ -162,7 +162,7 @@ mg.render(locals(), 'immutable2.png')
|
|
|
162
162
|
| immutable1.png | immutable2.png |
|
|
163
163
|
|
|
164
164
|
|
|
165
|
-
|
|
165
|
+
## Mutable Type ##
|
|
166
166
|
With mutable types the result is different. In the code below variable `a` and `b` both reference the same `list` value [4, 3, 2]. A `list` is a mutable type and therefore when we change variable `b` its value **can** be mutated in place and thus `a` and `b` both reference the same new value afterwards. Thus changing `b` also changes `a` and vice versa. Sometimes we want this but other times we don't and then we will have to make a copy ourselfs so that `a` and `b` are independent.
|
|
167
167
|
|
|
168
168
|
```python
|
|
@@ -181,7 +181,7 @@ mg.render(locals(), 'mutable2.png')
|
|
|
181
181
|
|
|
182
182
|
One practical reason why Python makes the distinction between mutable and immutable types is that a value of a mutable type can be large, making it inefficient to copy each time we change it. Immutable values generally don't need to change as much, or are small making copying less of a concern.
|
|
183
183
|
|
|
184
|
-
|
|
184
|
+
## Copying ##
|
|
185
185
|
Python offers three different "copy" options that we will demonstrate using a nested list:
|
|
186
186
|
|
|
187
187
|
```python
|
|
@@ -205,7 +205,7 @@ mg.show(locals())
|
|
|
205
205
|

|
|
206
206
|
|
|
207
207
|
|
|
208
|
-
|
|
208
|
+
## Custom Copy ##
|
|
209
209
|
We can write our own custom copy function or method in case the three standard "copy" options don't do what we want. For example, in the code below the copy() method of My_Class copies the `digits` but shares the `letters` between two objects.
|
|
210
210
|
|
|
211
211
|
```python
|
|
@@ -231,7 +231,7 @@ mg.show(locals())
|
|
|
231
231
|
```
|
|
232
232
|

|
|
233
233
|
|
|
234
|
-
|
|
234
|
+
## Name Rebinding ##
|
|
235
235
|
When `a` and `b` share a mutable value, then changing the value of `b` changes the value of `a` and vice versa. However, reassigning `b` does not change `a`. When you reassign `b`, you only rebind the name `b` to a new value without effecting any other variables.
|
|
236
236
|
|
|
237
237
|
```python
|
|
@@ -249,7 +249,7 @@ mg.render(locals(), 'rebinding2.png')
|
|
|
249
249
|
|:-----------------------------------------------------------:|:-------------------------------------------------------------:|
|
|
250
250
|
| rebinding1.png | rebinding2.png |
|
|
251
251
|
|
|
252
|
-
|
|
252
|
+
# Call Stack #
|
|
253
253
|
The `mg.stack()` function retrieves the entire call stack, including the local variables for each function on the stack. This enables us to visualize the local variables across all active functions simultaneously. By examining the graph, we can determine whether any local variables from different functions share data. For instance, consider the function `add_one()` which adds the value `1` to each of its parameters `a`, `b`, and `c`.
|
|
254
254
|
|
|
255
255
|
```python
|
|
@@ -277,7 +277,7 @@ a:[4, 3, 2, 1] b:(4, 3, 2) c:[4, 3, 2]
|
|
|
277
277
|
|
|
278
278
|
This is because `b` is of immutable type 'tuple' so its value gets copied automatically when it is changed. And because the function is called with a copy of `c`, its original value is not changed by the function. The value of variable `a` is the only value of mutable type that is shared between the root stack frame **'0: \<module>'** and the **'1: add_one'** stack frame of the function so only that variable is affected as a result of the function call. The other changes remain confined to the local variables of the ```add_one()``` function.
|
|
279
279
|
|
|
280
|
-
|
|
280
|
+
## Block ##
|
|
281
281
|
It is often helpful to temporarily block program execution to inspect the graph. For this we can use the `mg.block()` function:
|
|
282
282
|
|
|
283
283
|
```python
|
|
@@ -294,7 +294,7 @@ To change its behavior:
|
|
|
294
294
|
* Set `mg.block_prints_location = False` to skip printing the source location.
|
|
295
295
|
* Set `mg.press_enter_message = None` to skip printing "Press <Enter> to continue...".
|
|
296
296
|
|
|
297
|
-
|
|
297
|
+
## Recursion ##
|
|
298
298
|
The call stack is also helpful to visualize how recursion works. Here we use `mg.block()` to show each step of how recursively ```factorial(3)``` is computed:
|
|
299
299
|
|
|
300
300
|
```python
|
|
@@ -315,7 +315,7 @@ print(factorial(3))
|
|
|
315
315
|
|
|
316
316
|
and the result is: 1 x 2 x 3 = 6
|
|
317
317
|
|
|
318
|
-
|
|
318
|
+
## Power Set ##
|
|
319
319
|
A more interesting recursive example that shows sharing of data is power_set(). A power set is the set of all subsets of a collection of values.
|
|
320
320
|
|
|
321
321
|
```python
|
|
@@ -345,7 +345,7 @@ print( power_set(['a', 'b', 'c']) )
|
|
|
345
345
|
[['a', 'b', 'c'], ['a', 'b'], ['a', 'c'], ['a'], ['b', 'c'], ['b'], ['c'], []]
|
|
346
346
|
```
|
|
347
347
|
|
|
348
|
-
|
|
348
|
+
# Debugging #
|
|
349
349
|
|
|
350
350
|
For the best debugging experience with memory_graph set for example expression:
|
|
351
351
|
```
|
|
@@ -353,7 +353,7 @@ mg.render(locals(), "my_graph.pdf")
|
|
|
353
353
|
```
|
|
354
354
|
as a *watch* in a debugger tool such as the integrated debugger in Visual Studio Code. Then open the "my_graph.pdf" output file to continuously see all the local variables while debugging. This avoids having to add any memory_graph `show()` or `render()` calls to your code.
|
|
355
355
|
|
|
356
|
-
|
|
356
|
+
## Call Stack in Watch Context ##
|
|
357
357
|
The ```mg.stack()``` doesn't work well in *watch* context in most debuggers because debuggers introduce additional stack frames that cause problems. Use these alternative functions for various debuggers to filter out these problematic stack frames:
|
|
358
358
|
|
|
359
359
|
| debugger | function to get the call stack |
|
|
@@ -364,7 +364,7 @@ The ```mg.stack()``` doesn't work well in *watch* context in most debuggers beca
|
|
|
364
364
|
|
|
365
365
|

|
|
366
366
|
|
|
367
|
-
|
|
367
|
+
## Other Debuggers ##
|
|
368
368
|
For other debuggers, invoke this function within the *watch* context. Then, in the "call_stack.txt" file, identify the slice of functions you wish to include in the call stack.
|
|
369
369
|
```
|
|
370
370
|
mg.save_call_stack("call_stack.txt")
|
|
@@ -374,7 +374,7 @@ Choose 'after' and 'up_to' what function you want to slice and then call this fu
|
|
|
374
374
|
mg.stack_after_up_to(after_function, up_to_function="<module>")
|
|
375
375
|
```
|
|
376
376
|
|
|
377
|
-
|
|
377
|
+
## Debugging without Debugger Tool ##
|
|
378
378
|
|
|
379
379
|
To simplify debugging without a debugger tool, we offer these alias functions that you can insert into your code at the point where you want to visualize a graph:
|
|
380
380
|
|
|
@@ -407,48 +407,44 @@ and pressing <Enter> a number of times, results in:
|
|
|
407
407
|
|
|
408
408
|

|
|
409
409
|
|
|
410
|
-
|
|
411
|
-
Module memory_graph can be very useful in a course about
|
|
410
|
+
# Data Structure Examples #
|
|
411
|
+
Module memory_graph can be very useful in a course about data structures, some examples:
|
|
412
412
|
|
|
413
|
-
|
|
413
|
+
## Doubly Linked List ##
|
|
414
414
|
```python
|
|
415
415
|
import memory_graph as mg
|
|
416
416
|
import random
|
|
417
417
|
random.seed(0) # use same random numbers each run
|
|
418
418
|
|
|
419
|
-
class
|
|
419
|
+
class Linked_List:
|
|
420
420
|
|
|
421
|
-
def __init__(self, value):
|
|
422
|
-
self.prev =
|
|
421
|
+
def __init__(self, value=None, prev=None, next=None):
|
|
422
|
+
self.prev = prev
|
|
423
423
|
self.value = value
|
|
424
|
-
self.next =
|
|
425
|
-
|
|
426
|
-
class LinkedList:
|
|
427
|
-
|
|
428
|
-
def __init__(self):
|
|
429
|
-
self.head = None
|
|
430
|
-
self.tail = None
|
|
424
|
+
self.next = next
|
|
431
425
|
|
|
432
426
|
def add_front(self, value):
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
427
|
+
if self.value == None:
|
|
428
|
+
self.value = value
|
|
429
|
+
elif self.next is None:
|
|
430
|
+
new_node = Linked_List(value)
|
|
431
|
+
self.prev = new_node
|
|
432
|
+
self.next = new_node
|
|
437
433
|
else:
|
|
438
|
-
new_node
|
|
439
|
-
self.
|
|
440
|
-
self.
|
|
441
|
-
mg.block(mg.show, locals()) # <--- draw locals
|
|
434
|
+
new_node = Linked_List(value, self.next)
|
|
435
|
+
self.next.next = new_node
|
|
436
|
+
self.next = new_node
|
|
442
437
|
|
|
443
|
-
linked_list =
|
|
438
|
+
linked_list = Linked_List()
|
|
444
439
|
n = 100
|
|
445
440
|
for i in range(n):
|
|
446
|
-
|
|
447
|
-
linked_list.add_front(
|
|
441
|
+
value = random.randrange(n)
|
|
442
|
+
linked_list.add_front(value)
|
|
443
|
+
mg.show(locals())
|
|
448
444
|
```
|
|
449
445
|

|
|
450
446
|
|
|
451
|
-
|
|
447
|
+
## Binary Tree ##
|
|
452
448
|
```python
|
|
453
449
|
import memory_graph as mg
|
|
454
450
|
import random
|
|
@@ -484,7 +480,7 @@ for i in range(n):
|
|
|
484
480
|
```
|
|
485
481
|

|
|
486
482
|
|
|
487
|
-
|
|
483
|
+
## Hash Set ##
|
|
488
484
|
```python
|
|
489
485
|
import memory_graph as mg
|
|
490
486
|
import random
|
|
@@ -523,34 +519,44 @@ for i in range(n):
|
|
|
523
519
|

|
|
524
520
|
|
|
525
521
|
|
|
526
|
-
|
|
522
|
+
# Configuration #
|
|
527
523
|
Different aspects of memory_graph can be configured. The default configuration is reset by importing 'memory_graph.config_default'.
|
|
528
524
|
|
|
529
|
-
- ***mg.config.max_graph_depth*** : int
|
|
530
|
-
- The maxium depth of the graph with default value 12. A `✂` (scissor) symbol indicates where the graph is cut short. Dashed references indicate that there are more references to a node than are shown.
|
|
531
|
-
|
|
532
525
|
- ***mg.config.max_string_length*** : int
|
|
533
526
|
- The maximum length of strings shown in the graph. Longer strings will be truncated.
|
|
534
527
|
|
|
535
|
-
- ***mg.config.not_node_types*** : set
|
|
528
|
+
- ***mg.config.not_node_types*** : set[type]
|
|
536
529
|
- Holds all types for which no seperate node is drawn but that instead are shown as elements in their parent Node.
|
|
537
530
|
|
|
538
|
-
- ***mg.config.no_child_references_types*** : set
|
|
531
|
+
- ***mg.config.no_child_references_types*** : set[type]
|
|
539
532
|
- The set of key_value types that don't draw references to their direct childeren but have their children shown as elements of their node.
|
|
540
533
|
|
|
541
|
-
- ***mg.config.type_to_node*** : dict
|
|
534
|
+
- ***mg.config.type_to_node*** : dict[type, fun(data) -> Node]
|
|
542
535
|
- Determines how a data types is converted to a Node (sub)class for visualization in the graph.
|
|
543
536
|
|
|
544
|
-
- ***mg.config.type_to_color*** : dict
|
|
545
|
-
- Maps
|
|
537
|
+
- ***mg.config.type_to_color*** : dict[type, color]
|
|
538
|
+
- Maps a type to the [graphviz color](https://graphviz.org/doc/info/colors.html) it gets in the graph.
|
|
539
|
+
|
|
540
|
+
- ***mg.config.type_to_vertical_orientation*** : dict[type, bool]
|
|
541
|
+
- Maps a type to its orientation. Use 'True' for vertical and 'False' for horizontal. If not specified Node_Linear and Node_Key_Value are vertical unless they have references to children.
|
|
542
|
+
|
|
543
|
+
- ***mg.config.type_to_slicer*** : dict[type, int]
|
|
544
|
+
- Maps a type to a Slicer. A slicer determines how many elements of a data type are shown in the graph to prevent the graph from getting too big. 'Slicer()' does no slicing, 'Slicer(1,2,3)' shows just 1 element at the beginning, 2 in the middle, and 3 at the end.
|
|
545
|
+
|
|
546
|
+
- ***mg.config.max_graph_depth*** : int
|
|
547
|
+
- The maxium depth of the graph with default value 12.
|
|
548
|
+
|
|
549
|
+
- ***config.graph_cut_symbol*** : str
|
|
550
|
+
- The symbol indicating where the graph is cut short with default `✂`.
|
|
551
|
+
|
|
552
|
+
- ***mg.config.type_to_depth*** : dict[type, int]
|
|
553
|
+
- Maps a type to graph depth to limit the graph size.
|
|
546
554
|
|
|
547
|
-
- ***
|
|
548
|
-
-
|
|
555
|
+
- ***max_missing_edges*** : int
|
|
556
|
+
- Maximum number of missing edges that are shown with default value 2. Dashed references are used to indicate that there are more references to a node than are shown.
|
|
549
557
|
|
|
550
|
-
- ***mg.config.type_to_slicer*** : dict
|
|
551
|
-
- Maps each type to a Slicer. A slicer determines how many elements of a data type are shown in the graph to prevent the graph from getting too big. 'Slicer()' does no slicing, 'Slicer(1,2,3)' shows just 1 element at the beginning, 2 in the middle, and 3 at the end.
|
|
552
558
|
|
|
553
|
-
|
|
559
|
+
## Simplified Graph ##
|
|
554
560
|
Memory_graph simplifies the visualization (and the viewer's mental model) by **not** showing separate nodes for immutable types like `bool`, `int`, `float`, `complex`, and `str` by default. This simplification can sometimes be slightly misleading. As in the example below, after a shallow copy, lists `a` and `b` technically share their `int` values, but the graph makes it appear as though `a` and `b` each have their own copies. However, since `int` is immutable, this simplification will never lead to unexpected changes (changing `a` won’t affect `b`) so will never result in bugs.
|
|
555
561
|
|
|
556
562
|
The simplification strikes a balance: it is slightly misleading but keeps the graph clean and easy to understand and focuses on the mutable types where unexpected changes can occur. This is why it is the default behavior. If you do want to show separate nodes for `int` values, such as for educational purposes, you can simply remove `int` from the `mg.config.not_node_types` set:
|
|
@@ -571,7 +577,7 @@ mg.render(locals(), 'not_node_types2.png')
|
|
|
571
577
|
|
|
572
578
|
Additionally, the simplification hides away the [reuse of small int values](https://docs.python.org/3/c-api/long.html#c.PyLong_FromLong) in the current CPython implementation, an optimization that might otherwise confuse beginner Python programmers. For instance, after executing `a[1]+=1; b[1]+=1` the `201` value is, maybe surprisingly, still shared between `a` and `b`, whereas executing `a[2]+=1; b[2]+=1` does not result in sharing the `301` value.
|
|
573
579
|
|
|
574
|
-
|
|
580
|
+
## Temporary Configuration ##
|
|
575
581
|
In addition to the global configuration, a temporary configuration can be set for a single `show()` or `render()` call to change the colors, orientation, and slicer. This example highlights a particular list element in red, gives it a horizontal orientation, and overwrites the default slicer for lists:
|
|
576
582
|
|
|
577
583
|
```python
|
|
@@ -589,10 +595,10 @@ mg.show( locals(),
|
|
|
589
595
|
```
|
|
590
596
|

|
|
591
597
|
|
|
592
|
-
|
|
598
|
+
# Extensions #
|
|
593
599
|
Different extensions are available for types from other Python packages.
|
|
594
600
|
|
|
595
|
-
|
|
601
|
+
## Numpy ##
|
|
596
602
|
Numpy types `array` and `matrix` and `ndarray` can be graphed with "memory_graph.extension_numpy":
|
|
597
603
|
|
|
598
604
|
```python
|
|
@@ -608,7 +614,7 @@ mg.show(locals())
|
|
|
608
614
|
```
|
|
609
615
|

|
|
610
616
|
|
|
611
|
-
|
|
617
|
+
## Pandas ##
|
|
612
618
|
Pandas types `Series` and `DataFrame` can be graphed with "memory_graph.extension_pandas":
|
|
613
619
|
|
|
614
620
|
```python
|
|
@@ -627,7 +633,7 @@ mg.show(locals())
|
|
|
627
633
|
```
|
|
628
634
|

|
|
629
635
|
|
|
630
|
-
|
|
636
|
+
# Introspection #
|
|
631
637
|
This section is likely to change. Sometimes the introspection fails or is not as desired. For example the `bintrees.avltree.Node` object doesn't show any attributes in the graph below.
|
|
632
638
|
|
|
633
639
|
```python
|
|
@@ -646,7 +652,7 @@ mg.show(locals())
|
|
|
646
652
|

|
|
647
653
|
|
|
648
654
|
|
|
649
|
-
|
|
655
|
+
## All attributes using dir() ##
|
|
650
656
|
A useful start is to give it some color, show the list of all its attributes using `dir()`, and setting an empty Slicer to see the attribute list in full.
|
|
651
657
|
|
|
652
658
|
```python
|
|
@@ -671,7 +677,7 @@ mg.show(locals())
|
|
|
671
677
|
|
|
672
678
|
Next figure out what are the attributes you want to graph and choose a Node type, there are four options:
|
|
673
679
|
|
|
674
|
-
|
|
680
|
+
## 1) Node_Leaf ##
|
|
675
681
|
Node_Leaf is a node with no children and shows just a single value.
|
|
676
682
|
```python
|
|
677
683
|
import memory_graph as mg
|
|
@@ -692,7 +698,7 @@ mg.show(locals())
|
|
|
692
698
|
```
|
|
693
699
|

|
|
694
700
|
|
|
695
|
-
|
|
701
|
+
## 2) Node_Linear ##
|
|
696
702
|
Node_Linear shows multiple values in a line like a list.
|
|
697
703
|
```python
|
|
698
704
|
import memory_graph as mg
|
|
@@ -716,7 +722,7 @@ mg.show(locals())
|
|
|
716
722
|
```
|
|
717
723
|

|
|
718
724
|
|
|
719
|
-
|
|
725
|
+
## 3) Node_Key_Value ##
|
|
720
726
|
Node_Key_Value shows key-value pairs like a dictionary. Note the required `items()` call at the end.
|
|
721
727
|
```python
|
|
722
728
|
import memory_graph as mg
|
|
@@ -740,7 +746,7 @@ mg.show(locals())
|
|
|
740
746
|
```
|
|
741
747
|

|
|
742
748
|
|
|
743
|
-
|
|
749
|
+
## 4) Node_Table ##
|
|
744
750
|
Node_Table shows all the values as a table.
|
|
745
751
|
```python
|
|
746
752
|
import memory_graph as mg
|
|
@@ -764,7 +770,75 @@ mg.show(locals())
|
|
|
764
770
|

|
|
765
771
|
|
|
766
772
|
|
|
767
|
-
|
|
773
|
+
# Introspection Depth #
|
|
774
|
+
To limit the size of the graph the maximum depth of the graph is set by `mg.config.max_graph_depth`. Additionally for each type a depth can be set to further limit the graph, as is done for type `B` in the example below. Scissors indicate where the graph is cut short. Alternatively the `id()` of a data elements can be used to limit the graph for that specific element, as is done for the value referenced by variable `c`.
|
|
775
|
+
|
|
776
|
+
The value of variable `x` is shown as it is at depth 1 from the root of the graph, but as it can also be reached via `b2`, that path need to be shown as well to avoid confusion, so this overwrites the depth limit set for type `B`.
|
|
777
|
+
|
|
778
|
+
```python
|
|
779
|
+
import memory_graph as mg
|
|
780
|
+
|
|
781
|
+
class Base:
|
|
782
|
+
|
|
783
|
+
def __init__(self, n):
|
|
784
|
+
self.elements = [1]
|
|
785
|
+
iter = self.elements
|
|
786
|
+
for i in range(2,n):
|
|
787
|
+
iter.append([i])
|
|
788
|
+
iter = iter[-1]
|
|
789
|
+
|
|
790
|
+
def get_last(self):
|
|
791
|
+
iter = self.elements
|
|
792
|
+
while len(iter)>1:
|
|
793
|
+
iter = iter[-1]
|
|
794
|
+
return iter
|
|
795
|
+
|
|
796
|
+
class A(Base):
|
|
797
|
+
|
|
798
|
+
def __init__(self, n):
|
|
799
|
+
super().__init__(n)
|
|
800
|
+
|
|
801
|
+
class B(Base):
|
|
802
|
+
|
|
803
|
+
def __init__(self, n):
|
|
804
|
+
super().__init__(n)
|
|
805
|
+
|
|
806
|
+
class C(Base):
|
|
807
|
+
|
|
808
|
+
def __init__(self, n):
|
|
809
|
+
super().__init__(n)
|
|
810
|
+
|
|
811
|
+
a = A(6)
|
|
812
|
+
b1 = B(6)
|
|
813
|
+
b2 = B(6)
|
|
814
|
+
c = C(6)
|
|
815
|
+
|
|
816
|
+
x = ['x']
|
|
817
|
+
b2.get_last().append(x)
|
|
818
|
+
|
|
819
|
+
mg.config.type_to_depth[B] = 3
|
|
820
|
+
mg.config.type_to_depth[id(c)] = 2
|
|
821
|
+
mg.show(locals())
|
|
822
|
+
```
|
|
823
|
+

|
|
824
|
+
|
|
825
|
+
## Hidden Edges ##
|
|
826
|
+
|
|
827
|
+
As the value of `x` is shown in the graph, we would want to show all the references to it, but the default list Slicer hides references by slicing the list to keep the graph small. The `max_missing_edges` variable then determines how many additional hidden references to `x` we show. If there are more references then we show, then theses hidden references are shown with dashed lines to indicate some references are left out.
|
|
828
|
+
|
|
829
|
+
```python
|
|
830
|
+
import memory_graph as mg
|
|
831
|
+
|
|
832
|
+
data = []
|
|
833
|
+
x = ['x']
|
|
834
|
+
for i in range(20):
|
|
835
|
+
data.append(x)
|
|
836
|
+
|
|
837
|
+
mg.show(locals())
|
|
838
|
+
```
|
|
839
|
+

|
|
840
|
+
|
|
841
|
+
# Jupyter Notebook #
|
|
768
842
|
In Jupyter Notebook `locals()` has additional variables that cause problems in the graph, use `mg.locals_jupyter()` to get the local variables with these problematic variables filtered out. Use `mg.stack_jupyter()` to get the whole call stack with these variables filtered out.
|
|
769
843
|
|
|
770
844
|
We can use `mg.show()` and `mg.render()` in a Jupyter Notebook, but alternatively we can also use `mg.create_graph()` to create a graph and the `display()` function to render it inline with for example:
|
|
@@ -777,7 +851,7 @@ mg.block(display, mg.create_graph(mg.locals_jupyter()) ) # the same but blocked
|
|
|
777
851
|
See for example [jupyter_example.ipynb](https://raw.githubusercontent.com/bterwijn/memory_graph/main/src/jupyter_example.ipynb).
|
|
778
852
|

|
|
779
853
|
|
|
780
|
-
|
|
854
|
+
# ipython #
|
|
781
855
|
In ipython `locals()` has additional variables that cause problems in the graph, use `mg.locals_ipython()` to get the local variables with these problematic variables filtered out. Use `mg.stack_ipython()` to get the whole call stack with these variables filtered out.
|
|
782
856
|
|
|
783
857
|
Additionally install file [auto_memory_graph.py](https://raw.githubusercontent.com/bterwijn/memory_graph/main/src/auto_memory_graph.py) in the ipython startup directory:
|
|
@@ -787,15 +861,15 @@ Additionally install file [auto_memory_graph.py](https://raw.githubusercontent.c
|
|
|
787
861
|
Then after starting 'ipython' call function `mg_switch()` to turn on/off the automatic visualization of local variables after each command.
|
|
788
862
|

|
|
789
863
|
|
|
790
|
-
|
|
864
|
+
# In the Browser #
|
|
791
865
|
We can also run memory_graph in the browser: <a href="https://bterwijn.github.io/memory_graph/src/pyodide.html" target="_blank">Pyodide Example</a>
|
|
792
866
|

|
|
793
867
|
|
|
794
|
-
|
|
868
|
+
# Troubleshooting #
|
|
795
869
|
|
|
796
870
|
- Adobe Acrobat Reader [doesn't refresh a PDF file](https://community.adobe.com/t5/acrobat-reader-discussions/reload-refresh-pdfs/td-p/9632292) when it changes on disk and blocks updates which results in an `Could not open 'somefile.pdf' for writing : Permission denied` error. One solution is to install a PDF reader that does refresh ([SumatraPDF](https://www.sumatrapdfreader.org/), [Okular](https://okular.kde.org/), ...) and set it as the default PDF reader. Another solution is to `render()` the graph to a different output format and to open it manually.
|
|
797
871
|
|
|
798
872
|
- When graph edges overlap it can be hard to distinguish them. Using an interactive graphviz viewer, such as [xdot](https://github.com/jrfonseca/xdot.py), on a '*.gv' DOT output file will help.
|
|
799
873
|
|
|
800
|
-
|
|
874
|
+
## Invocation_Tree Package ##
|
|
801
875
|
The [memory_graph](https://pypi.org/project/memory-graph/) package visualizes your data. If instead you want to visualize function calls, check out the [invocation_tree](https://pypi.org/project/invocation-tree/) package.
|