memory-graph 0.3.16__tar.gz → 0.3.18__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 (181) hide show
  1. {memory_graph-0.3.16/memory_graph.egg-info → memory_graph-0.3.18}/PKG-INFO +24 -32
  2. {memory_graph-0.3.16 → memory_graph-0.3.18}/README.md +23 -31
  3. memory_graph-0.3.18/images/add_one.png +0 -0
  4. memory_graph-0.3.18/images/bin_tree.png +0 -0
  5. memory_graph-0.3.18/images/bin_tree.py +38 -0
  6. memory_graph-0.3.18/images/bin_tree2.py +31 -0
  7. memory_graph-0.3.18/images/bin_tree2.py~ +31 -0
  8. memory_graph-0.3.18/images/copy_method.png +0 -0
  9. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/copy_method.py +3 -2
  10. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/debugging01.png +0 -0
  11. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/debugging02.png +0 -0
  12. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/debugging03.png +0 -0
  13. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/debugging04.png +0 -0
  14. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/debugging05.png +0 -0
  15. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/debugging06.png +0 -0
  16. memory_graph-0.3.18/images/factorial.gif +0 -0
  17. memory_graph-0.3.18/images/factorial01.png +0 -0
  18. memory_graph-0.3.18/images/factorial02.png +0 -0
  19. memory_graph-0.3.18/images/factorial03.png +0 -0
  20. memory_graph-0.3.18/images/factorial04.png +0 -0
  21. memory_graph-0.3.18/images/factorial05.png +0 -0
  22. memory_graph-0.3.18/images/factorial06.png +0 -0
  23. memory_graph-0.3.18/images/factorial07.png +0 -0
  24. memory_graph-0.3.18/images/highlight.png +0 -0
  25. memory_graph-0.3.18/images/linked_list.png +0 -0
  26. memory_graph-0.3.18/images/many_types.png +0 -0
  27. memory_graph-0.3.18/images/memory_graph.pdf +0 -0
  28. memory_graph-0.3.18/images/power_set.gif +0 -0
  29. memory_graph-0.3.18/images/power_set1.png +0 -0
  30. memory_graph-0.3.18/images/power_set10.png +0 -0
  31. memory_graph-0.3.18/images/power_set11.png +0 -0
  32. memory_graph-0.3.18/images/power_set12.png +0 -0
  33. memory_graph-0.3.18/images/power_set13.png +0 -0
  34. memory_graph-0.3.18/images/power_set14.png +0 -0
  35. memory_graph-0.3.18/images/power_set15.png +0 -0
  36. memory_graph-0.3.18/images/power_set16.png +0 -0
  37. memory_graph-0.3.18/images/power_set17.png +0 -0
  38. memory_graph-0.3.18/images/power_set18.png +0 -0
  39. memory_graph-0.3.18/images/power_set19.png +0 -0
  40. memory_graph-0.3.18/images/power_set2.png +0 -0
  41. memory_graph-0.3.18/images/power_set20.png +0 -0
  42. memory_graph-0.3.18/images/power_set21.png +0 -0
  43. memory_graph-0.3.18/images/power_set22.png +0 -0
  44. memory_graph-0.3.18/images/power_set3.png +0 -0
  45. memory_graph-0.3.18/images/power_set4.png +0 -0
  46. memory_graph-0.3.18/images/power_set5.png +0 -0
  47. memory_graph-0.3.18/images/power_set6.png +0 -0
  48. memory_graph-0.3.18/images/power_set7.png +0 -0
  49. memory_graph-0.3.18/images/power_set8.png +0 -0
  50. memory_graph-0.3.18/images/power_set9.png +0 -0
  51. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/__init__.py +14 -3
  52. memory_graph-0.3.18/memory_graph/call_stack.py +9 -0
  53. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/config_default.py +7 -2
  54. {memory_graph-0.3.16 → memory_graph-0.3.18/memory_graph.egg-info}/PKG-INFO +24 -32
  55. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph.egg-info/SOURCES.txt +4 -1
  56. {memory_graph-0.3.16 → memory_graph-0.3.18}/setup.py +1 -1
  57. memory_graph-0.3.16/images/add_one.png +0 -0
  58. memory_graph-0.3.16/images/bin_tree.png +0 -0
  59. memory_graph-0.3.16/images/bin_tree.py +0 -47
  60. memory_graph-0.3.16/images/copy_method.png +0 -0
  61. memory_graph-0.3.16/images/factorial.gif +0 -0
  62. memory_graph-0.3.16/images/factorial01.png +0 -0
  63. memory_graph-0.3.16/images/factorial02.png +0 -0
  64. memory_graph-0.3.16/images/factorial03.png +0 -0
  65. memory_graph-0.3.16/images/factorial04.png +0 -0
  66. memory_graph-0.3.16/images/factorial05.png +0 -0
  67. memory_graph-0.3.16/images/factorial06.png +0 -0
  68. memory_graph-0.3.16/images/factorial07.png +0 -0
  69. memory_graph-0.3.16/images/highlight.png +0 -0
  70. memory_graph-0.3.16/images/linked_list.png +0 -0
  71. memory_graph-0.3.16/images/many_types.png +0 -0
  72. memory_graph-0.3.16/images/memory_graph.gv +0 -20
  73. memory_graph-0.3.16/images/power_set.gif +0 -0
  74. memory_graph-0.3.16/images/power_set1.png +0 -0
  75. memory_graph-0.3.16/images/power_set10.png +0 -0
  76. memory_graph-0.3.16/images/power_set11.png +0 -0
  77. memory_graph-0.3.16/images/power_set12.png +0 -0
  78. memory_graph-0.3.16/images/power_set13.png +0 -0
  79. memory_graph-0.3.16/images/power_set14.png +0 -0
  80. memory_graph-0.3.16/images/power_set15.png +0 -0
  81. memory_graph-0.3.16/images/power_set16.png +0 -0
  82. memory_graph-0.3.16/images/power_set17.png +0 -0
  83. memory_graph-0.3.16/images/power_set18.png +0 -0
  84. memory_graph-0.3.16/images/power_set19.png +0 -0
  85. memory_graph-0.3.16/images/power_set2.png +0 -0
  86. memory_graph-0.3.16/images/power_set20.png +0 -0
  87. memory_graph-0.3.16/images/power_set21.png +0 -0
  88. memory_graph-0.3.16/images/power_set22.png +0 -0
  89. memory_graph-0.3.16/images/power_set3.png +0 -0
  90. memory_graph-0.3.16/images/power_set4.png +0 -0
  91. memory_graph-0.3.16/images/power_set5.png +0 -0
  92. memory_graph-0.3.16/images/power_set6.png +0 -0
  93. memory_graph-0.3.16/images/power_set7.png +0 -0
  94. memory_graph-0.3.16/images/power_set8.png +0 -0
  95. memory_graph-0.3.16/images/power_set9.png +0 -0
  96. {memory_graph-0.3.16 → memory_graph-0.3.18}/LICENSE.txt +0 -0
  97. {memory_graph-0.3.16 → memory_graph-0.3.18}/MANIFEST.in +0 -0
  98. {memory_graph-0.3.16 → memory_graph-0.3.18}/TODO.txt +0 -0
  99. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/.ipynb_checkpoints/jupyter_example-checkpoint.ipynb +0 -0
  100. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/add_one.py +0 -0
  101. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/avltree.py +0 -0
  102. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/avltree.py~ +0 -0
  103. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/avltree_base.png +0 -0
  104. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/avltree_dir.png +0 -0
  105. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/avltree_fail.gv +0 -0
  106. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/avltree_fail.png +0 -0
  107. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/avltree_key_value.png +0 -0
  108. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/avltree_linear.png +0 -0
  109. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/avltree_table.png +0 -0
  110. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/copies.png +0 -0
  111. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/copies.py +0 -0
  112. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/create_gif.sh +0 -0
  113. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/create_images.sh +0 -0
  114. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/debug_vscode.png +0 -0
  115. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/debugging.gif +0 -0
  116. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/debugging.py +0 -0
  117. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/extension_numpy.png +0 -0
  118. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/extension_numpy.py +0 -0
  119. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/extension_pandas.png +0 -0
  120. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/extension_pandas.py +0 -0
  121. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/factorial.py +0 -0
  122. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/hash_set.png +0 -0
  123. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/hash_set.py +0 -0
  124. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/highlight.py +0 -0
  125. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/immutable.py +0 -0
  126. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/immutable1.png +0 -0
  127. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/immutable2.png +0 -0
  128. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/ipython.png +0 -0
  129. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/jupyter_example.png +0 -0
  130. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/linked_list.py +0 -0
  131. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/many_types.py +0 -0
  132. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/memory_graph.gv.pdf +0 -0
  133. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/mutable.py +0 -0
  134. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/mutable1.png +0 -0
  135. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/mutable2.png +0 -0
  136. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/my_graph.gv +0 -0
  137. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/my_graph.pdf +0 -0
  138. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/name_rebinding.py +0 -0
  139. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/not_node_types.py +0 -0
  140. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/not_node_types.py~ +0 -0
  141. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/not_node_types1.png +0 -0
  142. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/not_node_types2.png +0 -0
  143. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/power_set.py +0 -0
  144. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/pyodide.png +0 -0
  145. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/rebinding1.png +0 -0
  146. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/rebinding2.png +0 -0
  147. {memory_graph-0.3.16 → memory_graph-0.3.18}/images/uva.png +0 -0
  148. {memory_graph-0.3.16 → memory_graph-0.3.18}/install.txt +0 -0
  149. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/config.py +0 -0
  150. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/config_helpers.py +0 -0
  151. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/extension_numpy.py +0 -0
  152. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/extension_pandas.py +0 -0
  153. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/html_table.py +0 -0
  154. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/list_view.py +0 -0
  155. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/memory_to_nodes.py +0 -0
  156. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/node_base.py +0 -0
  157. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/node_key_value.py +0 -0
  158. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/node_linear.py +0 -0
  159. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/node_table.py +0 -0
  160. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/sequence.py +0 -0
  161. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/slicer.py +0 -0
  162. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/slices.py +0 -0
  163. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/slices_iterator.py +0 -0
  164. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/slices_table_iterator.py +0 -0
  165. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/test.py +0 -0
  166. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/test_max_graph_depth.py +0 -0
  167. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/test_memory_graph.py +0 -0
  168. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/test_memory_to_nodes.py +0 -0
  169. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/test_sequence.py +0 -0
  170. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/test_slicer.py +0 -0
  171. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/test_slices.py +0 -0
  172. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/test_slices_iterator.py +0 -0
  173. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/utils.py +0 -0
  174. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph.egg-info/dependency_links.txt +0 -0
  175. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph.egg-info/requires.txt +0 -0
  176. {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph.egg-info/top_level.txt +0 -0
  177. {memory_graph-0.3.16 → memory_graph-0.3.18}/setup.cfg +0 -0
  178. {memory_graph-0.3.16 → memory_graph-0.3.18}/src/auto_memory_graph.py +0 -0
  179. {memory_graph-0.3.16 → memory_graph-0.3.18}/src/jupyter_example.ipynb +0 -0
  180. {memory_graph-0.3.16 → memory_graph-0.3.18}/src/pyodide.html +0 -0
  181. {memory_graph-0.3.16 → memory_graph-0.3.18}/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.16
3
+ Version: 0.3.18
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
  ```
@@ -430,7 +431,7 @@ class LinkedList:
430
431
  new_node.next = self.head
431
432
  self.head.prev = new_node
432
433
  self.head = new_node
433
- mg.block(mg.show, locals()) # <--- draw graph
434
+ mg.block(mg.show, locals()) # <--- draw locals
434
435
 
435
436
  linked_list = LinkedList()
436
437
  n = 100
@@ -446,42 +447,33 @@ import memory_graph as mg
446
447
  import random
447
448
  random.seed(0) # use same random numbers each run
448
449
 
449
- class Node:
450
-
451
- def __init__(self, value):
452
- self.smaller = None
453
- self.value = value
454
- self.larger = None
455
-
456
450
  class BinTree:
457
451
 
458
- def __init__(self):
459
- self.root = None
452
+ def __init__(self, value=None, smaller=None, larger=None):
453
+ self.smaller = smaller
454
+ self.value = value
455
+ self.larger = larger
460
456
 
461
- def add_recursive(self, new_value, node):
462
- if new_value < node.value:
463
- if node.smaller is None:
464
- node.smaller = Node(new_value)
457
+ def add(self, value):
458
+ if self.value is None:
459
+ self.value = value
460
+ elif value < self.value:
461
+ if self.smaller is None:
462
+ self.smaller = BinTree(value)
465
463
  else:
466
- self.add_recursive(new_value, node.smaller)
464
+ self.smaller.add(value)
467
465
  else:
468
- if node.larger is None:
469
- node.larger = Node(new_value)
466
+ if self.larger is None:
467
+ self.larger = BinTree(value)
470
468
  else:
471
- self.add_recursive(new_value, node.larger)
472
- mg.block(mg.show, locals()) # <--- draw graph
473
-
474
- def add(self, value):
475
- if self.root is None:
476
- self.root = Node(value)
477
- else:
478
- self.add_recursive(value, self.root)
469
+ self.larger.add(value)
470
+ mg.block(mg.show, mg.stack()) # <--- draw stack
479
471
 
480
472
  tree = BinTree()
481
473
  n = 100
482
474
  for i in range(n):
483
- new_value = random.randrange(n)
484
- tree.add(new_value)
475
+ value = random.randrange(n)
476
+ tree.add(value)
485
477
  ```
486
478
  ![bin_tree.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/bin_tree.png)
487
479
 
@@ -502,7 +494,7 @@ class HashSet:
502
494
  self.buckets[index] = []
503
495
  bucket = self.buckets[index]
504
496
  bucket.append(value)
505
- mg.block(mg.show, locals()) # <--- draw graph
497
+ mg.block(mg.show, locals()) # <--- draw locals
506
498
 
507
499
  def contains(self, value):
508
500
  index = hash(value) % len(self.buckets)
@@ -793,7 +785,7 @@ We can also run memory_graph in the browser: <a href="https://bterwijn.github.io
793
785
 
794
786
  ## Troubleshooting ##
795
787
 
796
- - 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.
788
+ - 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.
797
789
 
798
790
  - 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
791
 
@@ -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
  ```
@@ -411,7 +412,7 @@ class LinkedList:
411
412
  new_node.next = self.head
412
413
  self.head.prev = new_node
413
414
  self.head = new_node
414
- mg.block(mg.show, locals()) # <--- draw graph
415
+ mg.block(mg.show, locals()) # <--- draw locals
415
416
 
416
417
  linked_list = LinkedList()
417
418
  n = 100
@@ -427,42 +428,33 @@ import memory_graph as mg
427
428
  import random
428
429
  random.seed(0) # use same random numbers each run
429
430
 
430
- class Node:
431
-
432
- def __init__(self, value):
433
- self.smaller = None
434
- self.value = value
435
- self.larger = None
436
-
437
431
  class BinTree:
438
432
 
439
- def __init__(self):
440
- self.root = None
433
+ def __init__(self, value=None, smaller=None, larger=None):
434
+ self.smaller = smaller
435
+ self.value = value
436
+ self.larger = larger
441
437
 
442
- def add_recursive(self, new_value, node):
443
- if new_value < node.value:
444
- if node.smaller is None:
445
- node.smaller = Node(new_value)
438
+ def add(self, value):
439
+ if self.value is None:
440
+ self.value = value
441
+ elif value < self.value:
442
+ if self.smaller is None:
443
+ self.smaller = BinTree(value)
446
444
  else:
447
- self.add_recursive(new_value, node.smaller)
445
+ self.smaller.add(value)
448
446
  else:
449
- if node.larger is None:
450
- node.larger = Node(new_value)
447
+ if self.larger is None:
448
+ self.larger = BinTree(value)
451
449
  else:
452
- self.add_recursive(new_value, node.larger)
453
- mg.block(mg.show, locals()) # <--- draw graph
454
-
455
- def add(self, value):
456
- if self.root is None:
457
- self.root = Node(value)
458
- else:
459
- self.add_recursive(value, self.root)
450
+ self.larger.add(value)
451
+ mg.block(mg.show, mg.stack()) # <--- draw stack
460
452
 
461
453
  tree = BinTree()
462
454
  n = 100
463
455
  for i in range(n):
464
- new_value = random.randrange(n)
465
- tree.add(new_value)
456
+ value = random.randrange(n)
457
+ tree.add(value)
466
458
  ```
467
459
  ![bin_tree.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/bin_tree.png)
468
460
 
@@ -483,7 +475,7 @@ class HashSet:
483
475
  self.buckets[index] = []
484
476
  bucket = self.buckets[index]
485
477
  bucket.append(value)
486
- mg.block(mg.show, locals()) # <--- draw graph
478
+ mg.block(mg.show, locals()) # <--- draw locals
487
479
 
488
480
  def contains(self, value):
489
481
  index = hash(value) % len(self.buckets)
@@ -774,7 +766,7 @@ We can also run memory_graph in the browser: <a href="https://bterwijn.github.io
774
766
 
775
767
  ## Troubleshooting ##
776
768
 
777
- - 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.
769
+ - 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.
778
770
 
779
771
  - 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.
780
772
 
Binary file
Binary file
@@ -0,0 +1,38 @@
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 as mg
6
+ import random
7
+ random.seed(0) # use same random numbers each run
8
+
9
+ class BinTree:
10
+
11
+ def __init__(self, value=None, smaller=None, larger=None):
12
+ self.smaller = smaller
13
+ self.value = value
14
+ self.larger = larger
15
+
16
+ def add(self, value):
17
+ if self.value is None:
18
+ self.value = value
19
+ elif value < self.value:
20
+ if self.smaller is None:
21
+ self.smaller = BinTree(value)
22
+ else:
23
+ self.smaller.add(value)
24
+ else:
25
+ if self.larger is None:
26
+ self.larger = BinTree(value)
27
+ else:
28
+ self.larger.add(value)
29
+ if value == 51:
30
+ mg.render(mg.stack(), f"bin_tree.png")
31
+ exit(0)
32
+
33
+ tree = BinTree()
34
+ n = 100
35
+ for i in range(n):
36
+ value = random.randrange(n)
37
+ tree.add(value)
38
+
@@ -0,0 +1,31 @@
1
+ import memory_graph as mg
2
+ import random
3
+ random.seed(0) # use same random numbers each run
4
+
5
+ class BinTree:
6
+
7
+ def __init__(self, value=None, smaller=None, larger=None):
8
+ self.smaller = smaller
9
+ self.value = value
10
+ self.larger = larger
11
+
12
+ def add(self, value):
13
+ if self.value is None:
14
+ self.value = value
15
+ elif value < self.value:
16
+ if self.smaller is None:
17
+ self.smaller = BinTree(value)
18
+ else:
19
+ self.smaller.add(value)
20
+ else:
21
+ if self.larger is None:
22
+ self.larger = BinTree(value)
23
+ else:
24
+ self.larger.add(value)
25
+ mg.block(mg.show, mg.stack())
26
+
27
+ tree = BinTree()
28
+ n = 100
29
+ for i in range(n):
30
+ value = random.randrange(n)
31
+ tree.add(value)
@@ -0,0 +1,31 @@
1
+ import memory_graph as mg
2
+ import random
3
+ random.seed(0) # use same random numbers each run
4
+
5
+ class BinTree:
6
+
7
+ def __init__(self, value=None, smaller=None, larger=None):
8
+ self.smaller = smaller
9
+ self.value = value
10
+ self.larger = larger
11
+
12
+ def add(self, value):
13
+ if self.value is None:
14
+ self.value = value
15
+ elif value < self.value:
16
+ if self.smaller is None:
17
+ self.smaller = BinTree(value)
18
+ else:
19
+ self.smaller.add(value)
20
+ else:
21
+ if self.larger is None:
22
+ self.larger = BinTree(value)
23
+ else:
24
+ self.larger.add(value)
25
+ mg.block(mg.render, mg.stack(), f"bin_tree.png")
26
+
27
+ tree = BinTree()
28
+ n = 100
29
+ for i in range(n):
30
+ value = random.randrange(n)
31
+ tree.add(value)
@@ -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
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.16"
17
+ __version__ = "0.3.18"
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)
@@ -8,6 +8,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
@@ -39,8 +40,11 @@ config.no_child_references_types = {dict, types.MappingProxyType}
39
40
  """ Conversion from type to Node_Base objects. """
40
41
  config.type_to_node = {
41
42
  str: lambda data: Node_Base(data), # visit as whole string, don't iterate over characters
43
+ call_stack: lambda data: Node_Key_Value(data, data.items()),
42
44
  types.FunctionType: lambda data: Node_Base(data.__qualname__),
43
45
  types.MethodType: lambda data: Node_Base(data.__qualname__),
46
+ classmethod: lambda data: Node_Base(data.__qualname__),
47
+ staticmethod: lambda data: Node_Base(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,10 +71,11 @@ 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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: memory_graph
3
- Version: 0.3.16
3
+ Version: 0.3.18
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
  ```
@@ -430,7 +431,7 @@ class LinkedList:
430
431
  new_node.next = self.head
431
432
  self.head.prev = new_node
432
433
  self.head = new_node
433
- mg.block(mg.show, locals()) # <--- draw graph
434
+ mg.block(mg.show, locals()) # <--- draw locals
434
435
 
435
436
  linked_list = LinkedList()
436
437
  n = 100
@@ -446,42 +447,33 @@ import memory_graph as mg
446
447
  import random
447
448
  random.seed(0) # use same random numbers each run
448
449
 
449
- class Node:
450
-
451
- def __init__(self, value):
452
- self.smaller = None
453
- self.value = value
454
- self.larger = None
455
-
456
450
  class BinTree:
457
451
 
458
- def __init__(self):
459
- self.root = None
452
+ def __init__(self, value=None, smaller=None, larger=None):
453
+ self.smaller = smaller
454
+ self.value = value
455
+ self.larger = larger
460
456
 
461
- def add_recursive(self, new_value, node):
462
- if new_value < node.value:
463
- if node.smaller is None:
464
- node.smaller = Node(new_value)
457
+ def add(self, value):
458
+ if self.value is None:
459
+ self.value = value
460
+ elif value < self.value:
461
+ if self.smaller is None:
462
+ self.smaller = BinTree(value)
465
463
  else:
466
- self.add_recursive(new_value, node.smaller)
464
+ self.smaller.add(value)
467
465
  else:
468
- if node.larger is None:
469
- node.larger = Node(new_value)
466
+ if self.larger is None:
467
+ self.larger = BinTree(value)
470
468
  else:
471
- self.add_recursive(new_value, node.larger)
472
- mg.block(mg.show, locals()) # <--- draw graph
473
-
474
- def add(self, value):
475
- if self.root is None:
476
- self.root = Node(value)
477
- else:
478
- self.add_recursive(value, self.root)
469
+ self.larger.add(value)
470
+ mg.block(mg.show, mg.stack()) # <--- draw stack
479
471
 
480
472
  tree = BinTree()
481
473
  n = 100
482
474
  for i in range(n):
483
- new_value = random.randrange(n)
484
- tree.add(new_value)
475
+ value = random.randrange(n)
476
+ tree.add(value)
485
477
  ```
486
478
  ![bin_tree.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/bin_tree.png)
487
479
 
@@ -502,7 +494,7 @@ class HashSet:
502
494
  self.buckets[index] = []
503
495
  bucket = self.buckets[index]
504
496
  bucket.append(value)
505
- mg.block(mg.show, locals()) # <--- draw graph
497
+ mg.block(mg.show, locals()) # <--- draw locals
506
498
 
507
499
  def contains(self, value):
508
500
  index = hash(value) % len(self.buckets)
@@ -793,7 +785,7 @@ We can also run memory_graph in the browser: <a href="https://bterwijn.github.io
793
785
 
794
786
  ## Troubleshooting ##
795
787
 
796
- - 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.
788
+ - 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.
797
789
 
798
790
  - 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
791