memory-graph 0.3.17__tar.gz → 0.3.19__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.
Files changed (183) hide show
  1. {memory_graph-0.3.17/memory_graph.egg-info → memory_graph-0.3.19}/PKG-INFO +10 -8
  2. {memory_graph-0.3.17 → memory_graph-0.3.19}/README.md +9 -7
  3. memory_graph-0.3.19/images/add_one.png +0 -0
  4. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/avltree.py +2 -2
  5. memory_graph-0.3.19/images/avltree_leaf.png +0 -0
  6. memory_graph-0.3.19/images/bin_tree.png +0 -0
  7. memory_graph-0.3.19/images/copy_method.png +0 -0
  8. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/copy_method.py +3 -2
  9. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/debugging01.png +0 -0
  10. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/debugging02.png +0 -0
  11. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/debugging03.png +0 -0
  12. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/debugging04.png +0 -0
  13. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/debugging05.png +0 -0
  14. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/debugging06.png +0 -0
  15. memory_graph-0.3.19/images/factorial.gif +0 -0
  16. memory_graph-0.3.19/images/factorial01.png +0 -0
  17. memory_graph-0.3.19/images/factorial02.png +0 -0
  18. memory_graph-0.3.19/images/factorial03.png +0 -0
  19. memory_graph-0.3.19/images/factorial04.png +0 -0
  20. memory_graph-0.3.19/images/factorial05.png +0 -0
  21. memory_graph-0.3.19/images/factorial06.png +0 -0
  22. memory_graph-0.3.19/images/factorial07.png +0 -0
  23. memory_graph-0.3.19/images/highlight.png +0 -0
  24. memory_graph-0.3.19/images/linked_list.png +0 -0
  25. memory_graph-0.3.19/images/log.txt +186 -0
  26. memory_graph-0.3.19/images/many_types.png +0 -0
  27. memory_graph-0.3.19/images/not_node_types2.png +0 -0
  28. memory_graph-0.3.19/images/power_set.gif +0 -0
  29. memory_graph-0.3.19/images/power_set1.png +0 -0
  30. memory_graph-0.3.19/images/power_set10.png +0 -0
  31. memory_graph-0.3.19/images/power_set11.png +0 -0
  32. memory_graph-0.3.19/images/power_set12.png +0 -0
  33. memory_graph-0.3.19/images/power_set13.png +0 -0
  34. memory_graph-0.3.19/images/power_set14.png +0 -0
  35. memory_graph-0.3.19/images/power_set15.png +0 -0
  36. memory_graph-0.3.19/images/power_set16.png +0 -0
  37. memory_graph-0.3.19/images/power_set17.png +0 -0
  38. memory_graph-0.3.19/images/power_set18.png +0 -0
  39. memory_graph-0.3.19/images/power_set19.png +0 -0
  40. memory_graph-0.3.19/images/power_set2.png +0 -0
  41. memory_graph-0.3.19/images/power_set20.png +0 -0
  42. memory_graph-0.3.19/images/power_set21.png +0 -0
  43. memory_graph-0.3.19/images/power_set22.png +0 -0
  44. memory_graph-0.3.19/images/power_set3.png +0 -0
  45. memory_graph-0.3.19/images/power_set4.png +0 -0
  46. memory_graph-0.3.19/images/power_set5.png +0 -0
  47. memory_graph-0.3.19/images/power_set6.png +0 -0
  48. memory_graph-0.3.19/images/power_set7.png +0 -0
  49. memory_graph-0.3.19/images/power_set8.png +0 -0
  50. memory_graph-0.3.19/images/power_set9.png +0 -0
  51. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph/__init__.py +14 -3
  52. memory_graph-0.3.19/memory_graph/call_stack.py +9 -0
  53. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph/config_default.py +13 -8
  54. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph/memory_to_nodes.py +2 -2
  55. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph/node_base.py +6 -6
  56. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph/node_key_value.py +3 -1
  57. memory_graph-0.3.19/memory_graph/node_leaf.py +23 -0
  58. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph/node_linear.py +3 -1
  59. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph/node_table.py +2 -2
  60. {memory_graph-0.3.17 → memory_graph-0.3.19/memory_graph.egg-info}/PKG-INFO +10 -8
  61. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph.egg-info/SOURCES.txt +4 -2
  62. {memory_graph-0.3.17 → memory_graph-0.3.19}/setup.py +1 -1
  63. memory_graph-0.3.17/TODO.txt +0 -9
  64. memory_graph-0.3.17/images/add_one.png +0 -0
  65. memory_graph-0.3.17/images/avltree_base.png +0 -0
  66. memory_graph-0.3.17/images/bin_tree.png +0 -0
  67. memory_graph-0.3.17/images/copy_method.png +0 -0
  68. memory_graph-0.3.17/images/factorial.gif +0 -0
  69. memory_graph-0.3.17/images/factorial01.png +0 -0
  70. memory_graph-0.3.17/images/factorial02.png +0 -0
  71. memory_graph-0.3.17/images/factorial03.png +0 -0
  72. memory_graph-0.3.17/images/factorial04.png +0 -0
  73. memory_graph-0.3.17/images/factorial05.png +0 -0
  74. memory_graph-0.3.17/images/factorial06.png +0 -0
  75. memory_graph-0.3.17/images/factorial07.png +0 -0
  76. memory_graph-0.3.17/images/highlight.png +0 -0
  77. memory_graph-0.3.17/images/linked_list.png +0 -0
  78. memory_graph-0.3.17/images/many_types.png +0 -0
  79. memory_graph-0.3.17/images/not_node_types2.png +0 -0
  80. memory_graph-0.3.17/images/power_set.gif +0 -0
  81. memory_graph-0.3.17/images/power_set1.png +0 -0
  82. memory_graph-0.3.17/images/power_set10.png +0 -0
  83. memory_graph-0.3.17/images/power_set11.png +0 -0
  84. memory_graph-0.3.17/images/power_set12.png +0 -0
  85. memory_graph-0.3.17/images/power_set13.png +0 -0
  86. memory_graph-0.3.17/images/power_set14.png +0 -0
  87. memory_graph-0.3.17/images/power_set15.png +0 -0
  88. memory_graph-0.3.17/images/power_set16.png +0 -0
  89. memory_graph-0.3.17/images/power_set17.png +0 -0
  90. memory_graph-0.3.17/images/power_set18.png +0 -0
  91. memory_graph-0.3.17/images/power_set19.png +0 -0
  92. memory_graph-0.3.17/images/power_set2.png +0 -0
  93. memory_graph-0.3.17/images/power_set20.png +0 -0
  94. memory_graph-0.3.17/images/power_set21.png +0 -0
  95. memory_graph-0.3.17/images/power_set22.png +0 -0
  96. memory_graph-0.3.17/images/power_set3.png +0 -0
  97. memory_graph-0.3.17/images/power_set4.png +0 -0
  98. memory_graph-0.3.17/images/power_set5.png +0 -0
  99. memory_graph-0.3.17/images/power_set6.png +0 -0
  100. memory_graph-0.3.17/images/power_set7.png +0 -0
  101. memory_graph-0.3.17/images/power_set8.png +0 -0
  102. memory_graph-0.3.17/images/power_set9.png +0 -0
  103. {memory_graph-0.3.17 → memory_graph-0.3.19}/LICENSE.txt +0 -0
  104. {memory_graph-0.3.17 → memory_graph-0.3.19}/MANIFEST.in +0 -0
  105. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/.ipynb_checkpoints/jupyter_example-checkpoint.ipynb +0 -0
  106. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/add_one.py +0 -0
  107. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/avltree.py~ +0 -0
  108. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/avltree_dir.png +0 -0
  109. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/avltree_fail.gv +0 -0
  110. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/avltree_fail.png +0 -0
  111. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/avltree_key_value.png +0 -0
  112. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/avltree_linear.png +0 -0
  113. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/avltree_table.png +0 -0
  114. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/bin_tree.py +0 -0
  115. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/bin_tree2.py +0 -0
  116. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/bin_tree2.py~ +0 -0
  117. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/copies.png +0 -0
  118. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/copies.py +0 -0
  119. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/create_gif.sh +0 -0
  120. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/create_images.sh +0 -0
  121. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/debug_vscode.png +0 -0
  122. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/debugging.gif +0 -0
  123. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/debugging.py +0 -0
  124. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/extension_numpy.png +0 -0
  125. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/extension_numpy.py +0 -0
  126. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/extension_pandas.png +0 -0
  127. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/extension_pandas.py +0 -0
  128. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/factorial.py +0 -0
  129. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/hash_set.png +0 -0
  130. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/hash_set.py +0 -0
  131. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/highlight.py +0 -0
  132. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/immutable.py +0 -0
  133. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/immutable1.png +0 -0
  134. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/immutable2.png +0 -0
  135. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/ipython.png +0 -0
  136. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/jupyter_example.png +0 -0
  137. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/linked_list.py +0 -0
  138. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/many_types.py +0 -0
  139. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/memory_graph.gv.pdf +0 -0
  140. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/memory_graph.pdf +0 -0
  141. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/mutable.py +0 -0
  142. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/mutable1.png +0 -0
  143. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/mutable2.png +0 -0
  144. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/my_graph.gv +0 -0
  145. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/my_graph.pdf +0 -0
  146. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/name_rebinding.py +0 -0
  147. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/not_node_types.py +0 -0
  148. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/not_node_types.py~ +0 -0
  149. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/not_node_types1.png +0 -0
  150. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/power_set.py +0 -0
  151. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/pyodide.png +0 -0
  152. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/rebinding1.png +0 -0
  153. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/rebinding2.png +0 -0
  154. {memory_graph-0.3.17 → memory_graph-0.3.19}/images/uva.png +0 -0
  155. {memory_graph-0.3.17 → memory_graph-0.3.19}/install.txt +0 -0
  156. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph/config.py +0 -0
  157. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph/config_helpers.py +0 -0
  158. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph/extension_numpy.py +0 -0
  159. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph/extension_pandas.py +0 -0
  160. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph/html_table.py +0 -0
  161. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph/list_view.py +0 -0
  162. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph/sequence.py +0 -0
  163. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph/slicer.py +0 -0
  164. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph/slices.py +0 -0
  165. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph/slices_iterator.py +0 -0
  166. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph/slices_table_iterator.py +0 -0
  167. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph/test.py +0 -0
  168. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph/test_max_graph_depth.py +0 -0
  169. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph/test_memory_graph.py +0 -0
  170. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph/test_memory_to_nodes.py +0 -0
  171. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph/test_sequence.py +0 -0
  172. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph/test_slicer.py +0 -0
  173. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph/test_slices.py +0 -0
  174. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph/test_slices_iterator.py +0 -0
  175. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph/utils.py +0 -0
  176. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph.egg-info/dependency_links.txt +0 -0
  177. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph.egg-info/requires.txt +0 -0
  178. {memory_graph-0.3.17 → memory_graph-0.3.19}/memory_graph.egg-info/top_level.txt +0 -0
  179. {memory_graph-0.3.17 → memory_graph-0.3.19}/setup.cfg +0 -0
  180. {memory_graph-0.3.17 → memory_graph-0.3.19}/src/auto_memory_graph.py +0 -0
  181. {memory_graph-0.3.17 → memory_graph-0.3.19}/src/jupyter_example.ipynb +0 -0
  182. {memory_graph-0.3.17 → memory_graph-0.3.19}/src/pyodide.html +0 -0
  183. {memory_graph-0.3.17 → memory_graph-0.3.19}/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.17
3
+ Version: 0.3.19
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
@@ -211,13 +211,14 @@ class My_Class:
211
211
  self.digits = [1, 2]
212
212
  self.letters = ['x', 'y']
213
213
 
214
- def copy(self): # custom copy method copies the digits but shares the letters
214
+ def custom_copy(self):
215
+ """ Copies 'digits' but shares 'letters'. """
215
216
  c = copy.copy(self)
216
217
  c.digits = copy.copy(self.digits)
217
218
  return c
218
219
 
219
220
  a = My_Class()
220
- b = a.copy()
221
+ b = a.custom_copy()
221
222
 
222
223
  mg.show(locals())
223
224
  ```
@@ -663,8 +664,8 @@ mg.show(locals())
663
664
 
664
665
  Next figure out what are the attributes you want to graph and choose a Node type, there are four options:
665
666
 
666
- ### 1) Node_Base ###
667
- Node_base is a leaf node (with no children) and shows just a single value.
667
+ ### 1) Node_Leaf ###
668
+ Node_Leaf is a leaf node (with no children) and shows just a single value.
668
669
  ```python
669
670
  import memory_graph as mg
670
671
  import bintrees
@@ -677,11 +678,12 @@ tree.insert(20, "twenty")
677
678
  tree.insert(15, "fifteen")
678
679
 
679
680
  mg.config.type_to_color[bintrees.avltree.Node] = "sandybrown"
680
- mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.node_base.Node_Base(f"key:{data.key} value:{data.value}")
681
+ mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.node_leaf.Node_Leaf(data,
682
+ f"key:{data.key} value:{data.value}")
681
683
 
682
684
  mg.show(locals())
683
685
  ```
684
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_base.png)
686
+ ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_leaf.png)
685
687
 
686
688
  ### 2) Node_Linear ###
687
689
  Node_Linear shows all the values in a line like a list.
@@ -784,7 +786,7 @@ We can also run memory_graph in the browser: <a href="https://bterwijn.github.io
784
786
 
785
787
  ## Troubleshooting ##
786
788
 
787
- - Adobe Acrobat Reader [doesn't refresh a PDF file](https://superuser.com/questions/337011/windows-pdf-viewer-that-auto-refreshes-pdf-when-compiling-with-pdflatex) 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 ([Evince](https://www.fosshub.com/Evince.html), [Okular](https://okular.kde.org/), [SumatraPDF](https://www.sumatrapdfreader.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.
789
+ - Adobe Acrobat Reader [doesn't refresh a PDF file](https://superuser.com/questions/337011/windows-pdf-viewer-that-auto-refreshes-pdf-when-compiling-with-pdflatex) 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.
788
790
 
789
791
  - 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.
790
792
 
@@ -192,13 +192,14 @@ class My_Class:
192
192
  self.digits = [1, 2]
193
193
  self.letters = ['x', 'y']
194
194
 
195
- def copy(self): # custom copy method copies the digits but shares the letters
195
+ def custom_copy(self):
196
+ """ Copies 'digits' but shares 'letters'. """
196
197
  c = copy.copy(self)
197
198
  c.digits = copy.copy(self.digits)
198
199
  return c
199
200
 
200
201
  a = My_Class()
201
- b = a.copy()
202
+ b = a.custom_copy()
202
203
 
203
204
  mg.show(locals())
204
205
  ```
@@ -644,8 +645,8 @@ mg.show(locals())
644
645
 
645
646
  Next figure out what are the attributes you want to graph and choose a Node type, there are four options:
646
647
 
647
- ### 1) Node_Base ###
648
- Node_base is a leaf node (with no children) and shows just a single value.
648
+ ### 1) Node_Leaf ###
649
+ Node_Leaf is a leaf node (with no children) and shows just a single value.
649
650
  ```python
650
651
  import memory_graph as mg
651
652
  import bintrees
@@ -658,11 +659,12 @@ tree.insert(20, "twenty")
658
659
  tree.insert(15, "fifteen")
659
660
 
660
661
  mg.config.type_to_color[bintrees.avltree.Node] = "sandybrown"
661
- mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.node_base.Node_Base(f"key:{data.key} value:{data.value}")
662
+ mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.node_leaf.Node_Leaf(data,
663
+ f"key:{data.key} value:{data.value}")
662
664
 
663
665
  mg.show(locals())
664
666
  ```
665
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_base.png)
667
+ ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_leaf.png)
666
668
 
667
669
  ### 2) Node_Linear ###
668
670
  Node_Linear shows all the values in a line like a list.
@@ -765,7 +767,7 @@ We can also run memory_graph in the browser: <a href="https://bterwijn.github.io
765
767
 
766
768
  ## Troubleshooting ##
767
769
 
768
- - Adobe Acrobat Reader [doesn't refresh a PDF file](https://superuser.com/questions/337011/windows-pdf-viewer-that-auto-refreshes-pdf-when-compiling-with-pdflatex) 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 ([Evince](https://www.fosshub.com/Evince.html), [Okular](https://okular.kde.org/), [SumatraPDF](https://www.sumatrapdfreader.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.
770
+ - Adobe Acrobat Reader [doesn't refresh a PDF file](https://superuser.com/questions/337011/windows-pdf-viewer-that-auto-refreshes-pdf-when-compiling-with-pdflatex) 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.
769
771
 
770
772
  - 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.
771
773
 
Binary file
@@ -19,8 +19,8 @@ mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.node_linear.Node
19
19
  mg.config.type_to_slicer[bintrees.avltree.Node] = mg.slicer.Slicer()
20
20
  mg.render(locals(), 'avltree_dir.png')
21
21
 
22
- mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.node_base.Node_Base(f"key:{data.key} value:{data.value}")
23
- mg.render(locals(), 'avltree_base.png')
22
+ mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.node_leaf.Node_Leaf(data, f"key:{data.key} value:{data.value}")
23
+ mg.render(locals(), 'avltree_leaf.png')
24
24
 
25
25
  mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.node_linear.Node_Linear(data,
26
26
  ['left:', data.left,
Binary file
@@ -11,12 +11,13 @@ class My_Class:
11
11
  self.digits = [1, 2]
12
12
  self.letters = ['x', 'y']
13
13
 
14
- def copy(self): # custom copy method copies the digits but shares the letters
14
+ def custom_copy(self):
15
+ """ Copies 'digits' but shares 'letters'. """
15
16
  c = copy.copy(self)
16
17
  c.digits = copy.copy(self.digits)
17
18
  return c
18
19
 
19
20
  a = My_Class()
20
- b = a.copy()
21
+ b = a.custom_copy()
21
22
 
22
23
  mg.render(locals(), 'copy_method.png')
Binary file
Binary file
@@ -0,0 +1,186 @@
1
+ diff --git a/images/avltree.py b/images/avltree.py
2
+ index a8400e8..c984c04 100644
3
+ --- a/images/avltree.py
4
+ +++ b/images/avltree.py
5
+ @@ -19,7 +19,7 @@ mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.node_linear.Node
6
+ mg.config.type_to_slicer[bintrees.avltree.Node] = mg.slicer.Slicer()
7
+ mg.render(locals(), 'avltree_dir.png')
8
+
9
+ -mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.node_base.Node_Base(f"key:{data.key} value:{data.value}")
10
+ +mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.node_leaf.Node_Leaf(data, f"key:{data.key} value:{data.value}")
11
+ mg.render(locals(), 'avltree_base.png')
12
+
13
+ mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.node_linear.Node_Linear(data,
14
+ diff --git a/images/avltree_base.png b/images/avltree_base.png
15
+ index 324c36d..de59c50 100644
16
+ Binary files a/images/avltree_base.png and b/images/avltree_base.png differ
17
+ diff --git a/images/not_node_types2.png b/images/not_node_types2.png
18
+ index b001e4b..ee6e943 100644
19
+ Binary files a/images/not_node_types2.png and b/images/not_node_types2.png differ
20
+ diff --git a/memory_graph/config_default.py b/memory_graph/config_default.py
21
+ index 4945c75..02877c0 100644
22
+ --- a/memory_graph/config_default.py
23
+ +++ b/memory_graph/config_default.py
24
+ @@ -3,7 +3,7 @@
25
+ # SPDX-License-Identifier: BSD-2-Clause
26
+
27
+ """ Sets the default configuration values for the memory graph. """
28
+ -from memory_graph.node_base import Node_Base
29
+ +from memory_graph.node_leaf import Node_Leaf
30
+ from memory_graph.node_linear import Node_Linear
31
+ from memory_graph.node_key_value import Node_Key_Value
32
+ from memory_graph.node_table import Node_Table
33
+ @@ -37,14 +37,14 @@ config.not_node_types = {
34
+ """ Types that will not have references pointing to their children in the graph but instead will have their children visualized in their node. """
35
+ config.no_child_references_types = {dict, types.MappingProxyType}
36
+
37
+ -""" Conversion from type to Node_Base objects. """
38
+ +""" Conversion from type to Node objects. """
39
+ config.type_to_node = {
40
+ - str: lambda data: Node_Base(data), # visit as whole string, don't iterate over characters
41
+ + str: lambda data: Node_Leaf(data, data), # visit as whole string, don't iterate over characters
42
+ call_stack: lambda data: Node_Key_Value(data, data.items()),
43
+ - types.FunctionType: lambda data: Node_Base(data.__qualname__),
44
+ - types.MethodType: lambda data: Node_Base(data.__qualname__),
45
+ - classmethod: lambda data: Node_Base(data.__qualname__),
46
+ - staticmethod: lambda data: Node_Base(data.__qualname__),
47
+ + types.FunctionType: lambda data: Node_Leaf(data, data.__qualname__),
48
+ + types.MethodType: lambda data: Node_Leaf(data, data.__qualname__),
49
+ + classmethod: lambda data: Node_Leaf(data, data.__qualname__),
50
+ + staticmethod: lambda data: Node_Leaf(data, data.__qualname__),
51
+ range: lambda data: Node_Key_Value(data, {'start':data.start, 'stop':data.stop, 'step':data.step}.items()),
52
+ dict: lambda data: (
53
+ Node_Key_Value(data, utils.filter_dict(data.items()) )
54
+ @@ -79,7 +79,7 @@ config.type_to_color = {
55
+ }
56
+
57
+ """ Types that will be visualized in vertical orientation if 'True', or horizontal orientation
58
+ -if 'False'. Otherwise the Node_Base decides based on it having references."""
59
+ +if 'False'. Otherwise the Node decides based on it having references."""
60
+ config.type_to_vertical_orientation = {
61
+ }
62
+
63
+ diff --git a/memory_graph/memory_to_nodes.py b/memory_graph/memory_to_nodes.py
64
+ index a67662e..10c559a 100644
65
+ --- a/memory_graph/memory_to_nodes.py
66
+ +++ b/memory_graph/memory_to_nodes.py
67
+ @@ -2,7 +2,7 @@
68
+ # Copyright (c) 2023, Bas Terwijn.
69
+ # SPDX-License-Identifier: BSD-2-Clause
70
+
71
+ -from memory_graph.node_base import Node_Base
72
+ +from memory_graph.node_leaf import Node_Leaf
73
+ from memory_graph.node_linear import Node_Linear
74
+ from memory_graph.node_key_value import Node_Key_Value
75
+
76
+ @@ -21,7 +21,7 @@ def read_nodes(data):
77
+ elif utils.is_finite_iterable(data): # for lists, tuples, sets, ...
78
+ return Node_Linear(data, data)
79
+ else:
80
+ - return Node_Base(data)
81
+ + return Node_Leaf(data, data)
82
+
83
+ def memory_to_nodes_recursive(nodes, data, parent, parent_index):
84
+ data_type = type(data)
85
+ diff --git a/memory_graph/node_base.py b/memory_graph/node_base.py
86
+ index 1f46b9a..3d1fbe1 100644
87
+ --- a/memory_graph/node_base.py
88
+ +++ b/memory_graph/node_base.py
89
+ @@ -7,7 +7,9 @@ import memory_graph.config as config
90
+ import memory_graph.config_helpers as config_helpers
91
+ from memory_graph.sequence import Sequence1D
92
+
93
+ -class Node_Base:
94
+ +from abc import ABC, abstractmethod
95
+ +
96
+ +class Node_Base(ABC):
97
+ """
98
+ Node_Base represents a node in the memory graph. This base class has different subclasses for different types of nodes.
99
+ """
100
+ @@ -99,10 +101,7 @@ class Node_Base:
101
+ from memory_graph.html_table import HTML_Table
102
+ import memory_graph.node_base
103
+ html_table = HTML_Table()
104
+ - if type(self) is memory_graph.node_base.Node_Base:
105
+ - html_table.add_string(f'{self.data}')
106
+ - elif not slices is None:
107
+ - self.fill_html_table(nodes, html_table, slices, id_to_slices)
108
+ + self.fill_html_table(nodes, html_table, slices, id_to_slices)
109
+ return html_table
110
+
111
+ def get_slicer(self):
112
+ @@ -123,6 +122,7 @@ class Node_Base:
113
+
114
+ # -------------------- Node_Base interface, overriden by subclasses --------------------
115
+
116
+ + @abstractmethod
117
+ def fill_html_table(self, html_table, slices, id_to_slices):
118
+ """
119
+ Fill the HTML_Table object with each child of the node.
120
+ @@ -133,4 +133,4 @@ class Node_Base:
121
+ """
122
+ Return a label for the node to be shown in the graph next to the HTML table.
123
+ """
124
+ - return self.get_type_name()
125
+
126
+ + return self.get_type_name()
127
+ diff --git a/memory_graph/node_key_value.py b/memory_graph/node_key_value.py
128
+ index 762857e..0c2cd86 100644
129
+ --- a/memory_graph/node_key_value.py
130
+ +++ b/memory_graph/node_key_value.py
131
+ @@ -54,6 +54,8 @@ class Node_Key_Value(Node_Base):
132
+ """
133
+ Fill the html_table with the children of the Node_Base.
134
+ """
135
+ + if slices is None:
136
+ + return
137
+ vertical = self.is_vertical(nodes, slices, id_to_slices)
138
+ if vertical:
139
+ self.fill_html_table_vertical(html_table, nodes, slices, id_to_slices)
140
+ @@ -119,4 +121,4 @@ class Node_Key_Value(Node_Base):
141
+ if len(s) == 1:
142
+ if s[0][1] - s[0][0] == size:
143
+ return f'{type_name}'
144
+ - return f'{type_name} {size}'
145
+
146
+ + return f'{type_name} {size}'
147
+ diff --git a/memory_graph/node_linear.py b/memory_graph/node_linear.py
148
+ index c6926f0..38b8cf0 100644
149
+ --- a/memory_graph/node_linear.py
150
+ +++ b/memory_graph/node_linear.py
151
+ @@ -45,6 +45,8 @@ class Node_Linear(Node_Base):
152
+ """
153
+ Fill the html_table with the children of the Node_Base.
154
+ """
155
+ + if slices is None:
156
+ + return
157
+ if self.is_vertical(nodes, slices, id_to_slices):
158
+ self.fill_html_table_vertical(html_table, nodes, slices, id_to_slices)
159
+ else:
160
+ @@ -95,4 +97,4 @@ class Node_Linear(Node_Base):
161
+ if s[0][1] - s[0][0] == size:
162
+ return f'{type_name}'
163
+ return f'{type_name} {size}'
164
+ -
165
+
166
+ +
167
+ diff --git a/memory_graph/node_table.py b/memory_graph/node_table.py
168
+ index 67914a9..82279d3 100644
169
+ --- a/memory_graph/node_table.py
170
+ +++ b/memory_graph/node_table.py
171
+ @@ -35,7 +35,7 @@ class Node_Table(Node_Base):
172
+ """
173
+ Fill the html_table with the children of the Node_Base.
174
+ """
175
+ - if slices.is_empty():
176
+ + if slices is None or slices.is_empty():
177
+ return
178
+ children = self.children
179
+ children_size = children.size()
180
+ @@ -80,4 +80,4 @@ class Node_Table(Node_Base):
181
+ """
182
+ size = self.get_children().size()
183
+ return f'{self.get_type_name()} {size[0]}⨯{size[1]}'
184
+ -
185
+
186
+ +
Binary file
@@ -10,10 +10,11 @@ import memory_graph.utils as utils
10
10
 
11
11
  import inspect
12
12
  import sys
13
+ from memory_graph.call_stack import call_stack
13
14
 
14
15
  import graphviz
15
16
 
16
- __version__ = "0.3.17"
17
+ __version__ = "0.3.19"
17
18
  __author__ = 'Bas Terwijn'
18
19
  render_filename = 'memory_graph.pdf'
19
20
  last_show_filename = None
@@ -173,14 +174,24 @@ def get_locals_from_call_stack(stack_index=0):
173
174
  frameInfo = inspect.stack()[1+stack_index] # get frameInfo of calling frame
174
175
  return frameInfo.frame.f_locals
175
176
 
177
+ def get_function_name(frameInfo):
178
+ frame = frameInfo.frame
179
+ func_name = frame.f_code.co_name
180
+ if 'self' in frame.f_locals: # instance method
181
+ return f"{frame.f_locals['self'].__class__.__name__}.{func_name}"
182
+ elif 'cls' in frame.f_locals: # class method
183
+ return f"{frame.f_locals['cls'].__name__}.{func_name}"
184
+ else: # forget about static method, too complex
185
+ return func_name # just the function
186
+
176
187
  def stack_frames_to_dict(frames):
177
188
  """ Returns a dictionary representing the data on the call stack.
178
189
  Each key is the stack level and function name, each value is the locals of the frame at that level.
179
190
  """
180
191
  def to_dict(value): # fix by TerenceTux for Python 3.13
181
192
  return {k: v for k, v in value.items()}
182
- return {f"{level}: {frameInfo.function}" : to_dict(frameInfo.frame.f_locals)
183
- for level, frameInfo in enumerate(frames)}
193
+ return call_stack({f"{level}: {get_function_name(frameInfo)}" : to_dict(frameInfo.frame.f_locals)
194
+ for level, frameInfo in enumerate(frames)})
184
195
 
185
196
  def stack(up_to_function="<module>",stack_index=0):
186
197
  return get_call_stack(up_to_function, 1+stack_index)
@@ -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)
@@ -3,11 +3,12 @@
3
3
  # SPDX-License-Identifier: BSD-2-Clause
4
4
 
5
5
  """ Sets the default configuration values for the memory graph. """
6
- from memory_graph.node_base import Node_Base
6
+ from memory_graph.node_leaf import Node_Leaf
7
7
  from memory_graph.node_linear import Node_Linear
8
8
  from memory_graph.node_key_value import Node_Key_Value
9
9
  from memory_graph.node_table import Node_Table
10
10
 
11
+ from memory_graph.call_stack import call_stack
11
12
  from memory_graph.slicer import Slicer
12
13
 
13
14
  import memory_graph.config as config
@@ -36,11 +37,14 @@ config.not_node_types = {
36
37
  """ Types that will not have references pointing to their children in the graph but instead will have their children visualized in their node. """
37
38
  config.no_child_references_types = {dict, types.MappingProxyType}
38
39
 
39
- """ Conversion from type to Node_Base objects. """
40
+ """ Conversion from type to Node objects. """
40
41
  config.type_to_node = {
41
- str: lambda data: Node_Base(data), # visit as whole string, don't iterate over characters
42
- types.FunctionType: lambda data: Node_Base(data.__qualname__),
43
- types.MethodType: lambda data: Node_Base(data.__qualname__),
42
+ str: lambda data: Node_Leaf(data, data), # visit as whole string, don't iterate over characters
43
+ call_stack: lambda data: Node_Key_Value(data, data.items()),
44
+ types.FunctionType: lambda data: Node_Leaf(data, data.__qualname__),
45
+ types.MethodType: lambda data: Node_Leaf(data, data.__qualname__),
46
+ classmethod: lambda data: Node_Leaf(data, data.__qualname__),
47
+ staticmethod: lambda data: Node_Leaf(data, data.__qualname__),
44
48
  range: lambda data: Node_Key_Value(data, {'start':data.start, 'stop':data.stop, 'step':data.step}.items()),
45
49
  dict: lambda data: (
46
50
  Node_Key_Value(data, utils.filter_dict(data.items()) )
@@ -67,14 +71,15 @@ config.type_to_color = {
67
71
  bytearray : "khaki2",
68
72
  # ================= key_value
69
73
  Node_Key_Value : "seagreen1", # for classes
70
- type: "seagreen2", # where class variables are stored
74
+ call_stack : 'khaki',
75
+ type: "seagreen3", # where class variables are stored
71
76
  dict : "dodgerblue1",
72
77
  types.MappingProxyType : "dodgerblue2", # not used
73
- range : "cornsilk",
78
+ range : "cornsilk2",
74
79
  }
75
80
 
76
81
  """ Types that will be visualized in vertical orientation if 'True', or horizontal orientation
77
- if 'False'. Otherwise the Node_Base decides based on it having references."""
82
+ if 'False'. Otherwise the Node decides based on it having references."""
78
83
  config.type_to_vertical_orientation = {
79
84
  }
80
85
 
@@ -2,7 +2,7 @@
2
2
  # Copyright (c) 2023, Bas Terwijn.
3
3
  # SPDX-License-Identifier: BSD-2-Clause
4
4
 
5
- from memory_graph.node_base import Node_Base
5
+ from memory_graph.node_leaf import Node_Leaf
6
6
  from memory_graph.node_linear import Node_Linear
7
7
  from memory_graph.node_key_value import Node_Key_Value
8
8
 
@@ -21,7 +21,7 @@ def read_nodes(data):
21
21
  elif utils.is_finite_iterable(data): # for lists, tuples, sets, ...
22
22
  return Node_Linear(data, data)
23
23
  else:
24
- return Node_Base(data)
24
+ return Node_Leaf(data, data)
25
25
 
26
26
  def memory_to_nodes_recursive(nodes, data, parent, parent_index):
27
27
  data_type = type(data)
@@ -7,7 +7,9 @@ import memory_graph.config as config
7
7
  import memory_graph.config_helpers as config_helpers
8
8
  from memory_graph.sequence import Sequence1D
9
9
 
10
- class Node_Base:
10
+ from abc import ABC, abstractmethod
11
+
12
+ class Node_Base(ABC):
11
13
  """
12
14
  Node_Base represents a node in the memory graph. This base class has different subclasses for different types of nodes.
13
15
  """
@@ -99,10 +101,7 @@ class Node_Base:
99
101
  from memory_graph.html_table import HTML_Table
100
102
  import memory_graph.node_base
101
103
  html_table = HTML_Table()
102
- if type(self) is memory_graph.node_base.Node_Base:
103
- html_table.add_string(f'{self.data}')
104
- elif not slices is None:
105
- self.fill_html_table(nodes, html_table, slices, id_to_slices)
104
+ self.fill_html_table(nodes, html_table, slices, id_to_slices)
106
105
  return html_table
107
106
 
108
107
  def get_slicer(self):
@@ -123,6 +122,7 @@ class Node_Base:
123
122
 
124
123
  # -------------------- Node_Base interface, overriden by subclasses --------------------
125
124
 
125
+ @abstractmethod
126
126
  def fill_html_table(self, html_table, slices, id_to_slices):
127
127
  """
128
128
  Fill the HTML_Table object with each child of the node.
@@ -133,4 +133,4 @@ class Node_Base:
133
133
  """
134
134
  Return a label for the node to be shown in the graph next to the HTML table.
135
135
  """
136
- return self.get_type_name()
136
+ return self.get_type_name()
@@ -54,6 +54,8 @@ class Node_Key_Value(Node_Base):
54
54
  """
55
55
  Fill the html_table with the children of the Node_Base.
56
56
  """
57
+ if slices is None:
58
+ return
57
59
  vertical = self.is_vertical(nodes, slices, id_to_slices)
58
60
  if vertical:
59
61
  self.fill_html_table_vertical(html_table, nodes, slices, id_to_slices)
@@ -119,4 +121,4 @@ class Node_Key_Value(Node_Base):
119
121
  if len(s) == 1:
120
122
  if s[0][1] - s[0][0] == size:
121
123
  return f'{type_name}'
122
- return f'{type_name} {size}'
124
+ return f'{type_name} {size}'
@@ -0,0 +1,23 @@
1
+ # This file is part of memory_graph.
2
+ # Copyright (c) 2023, Bas Terwijn.
3
+ # SPDX-License-Identifier: BSD-2-Clause
4
+
5
+ from memory_graph.node_base import Node_Base
6
+
7
+ class Node_Leaf(Node_Base):
8
+ """
9
+ Node_Leaf (subclass of Node_Base) is a leaf node with no children but a value.
10
+ """
11
+
12
+ def __init__(self, data, value):
13
+ """
14
+ Create a Node_Leaf object.
15
+ """
16
+ super().__init__(data)
17
+ self.value = value
18
+
19
+ def fill_html_table(self, nodes, html_table, slices, id_to_slices):
20
+ """
21
+ Fill the html_table with the children of the Node_Base.
22
+ """
23
+ html_table.add_value(self.value)