memory-graph 0.3.53__tar.gz → 0.3.55__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 (113) hide show
  1. {memory_graph-0.3.53/memory_graph.egg-info → memory_graph-0.3.55}/PKG-INFO +43 -27
  2. {memory_graph-0.3.53 → memory_graph-0.3.55}/README.md +42 -26
  3. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/binary.py +1 -1
  4. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/__init__.py +1 -1
  5. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/config.py +1 -0
  6. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/config_default.py +6 -4
  7. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/config_helpers.py +8 -1
  8. {memory_graph-0.3.53 → memory_graph-0.3.55/memory_graph.egg-info}/PKG-INFO +43 -27
  9. {memory_graph-0.3.53 → memory_graph-0.3.55}/pyproject.toml +1 -1
  10. {memory_graph-0.3.53 → memory_graph-0.3.55}/LICENSE.txt +0 -0
  11. {memory_graph-0.3.53 → memory_graph-0.3.55}/MANIFEST.in +0 -0
  12. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/add_one.png +0 -0
  13. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/add_one.py +0 -0
  14. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/avltree.py +0 -0
  15. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/avltree_dir.png +0 -0
  16. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/avltree_fail.png +0 -0
  17. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/avltree_key_value.png +0 -0
  18. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/avltree_leaf.png +0 -0
  19. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/avltree_linear.png +0 -0
  20. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/avltree_table.png +0 -0
  21. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/bin_search.png +0 -0
  22. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/bin_search.py +0 -0
  23. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/bin_search_linear.png +0 -0
  24. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/bin_tree.gif +0 -0
  25. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/bin_tree.png +0 -0
  26. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/bin_tree.py +0 -0
  27. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/binary.gif +0 -0
  28. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/colab_example.png +0 -0
  29. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/copy_immutable.png +0 -0
  30. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/copy_immutable.py +0 -0
  31. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/copy_method.png +0 -0
  32. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/copy_method.py +0 -0
  33. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/copy_mix.png +0 -0
  34. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/copy_mix.py +0 -0
  35. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/copy_mutable.png +0 -0
  36. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/copy_mutable.py +0 -0
  37. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/create_gif.sh +0 -0
  38. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/create_images.sh +0 -0
  39. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/debug_vscode.png +0 -0
  40. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/debugging.gif +0 -0
  41. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/debugging.py +0 -0
  42. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/embedded1.png +0 -0
  43. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/embedded2.png +0 -0
  44. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/extension_numpy.png +0 -0
  45. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/extension_numpy.py +0 -0
  46. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/extension_pandas.png +0 -0
  47. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/extension_pandas.py +0 -0
  48. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/extension_torch.png +0 -0
  49. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/extension_torch.py +0 -0
  50. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/factorial.gif +0 -0
  51. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/factorial.py +0 -0
  52. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/hash_set.gif +0 -0
  53. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/hash_set.png +0 -0
  54. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/hash_set.py +0 -0
  55. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/hidden_edges.png +0 -0
  56. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/hidden_edges.py +0 -0
  57. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/immutable.py +0 -0
  58. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/immutable1.png +0 -0
  59. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/immutable2.png +0 -0
  60. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/introspect_depth.png +0 -0
  61. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/introspect_depth.py +0 -0
  62. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/ipython.png +0 -0
  63. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/jupyter_example.png +0 -0
  64. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/linked_list.gif +0 -0
  65. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/linked_list.png +0 -0
  66. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/linked_list.py +0 -0
  67. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/many_types.png +0 -0
  68. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/many_types.py +0 -0
  69. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/marimo_example.png +0 -0
  70. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/memory_graph_web_debugger.png +0 -0
  71. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/mutable.py +0 -0
  72. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/mutable1.png +0 -0
  73. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/mutable2.png +0 -0
  74. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/name_rebinding.py +0 -0
  75. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/not_node_types.py +0 -0
  76. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/power_set.gif +0 -0
  77. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/power_set.py +0 -0
  78. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/rebinding1.png +0 -0
  79. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/rebinding2.png +0 -0
  80. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/uva.png +0 -0
  81. {memory_graph-0.3.53 → memory_graph-0.3.55}/images/vscode_copying.gif +0 -0
  82. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/call_stack.py +0 -0
  83. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/extension_numpy.py +0 -0
  84. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/extension_pandas.py +0 -0
  85. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/extension_torch.py +0 -0
  86. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/html_table.py +0 -0
  87. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/list_view.py +0 -0
  88. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/memory_to_nodes.py +0 -0
  89. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/node_base.py +0 -0
  90. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/node_key_value.py +0 -0
  91. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/node_leaf.py +0 -0
  92. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/node_linear.py +0 -0
  93. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/node_table.py +0 -0
  94. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/sequence.py +0 -0
  95. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/slicer.py +0 -0
  96. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/slices.py +0 -0
  97. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/slices_iterator.py +0 -0
  98. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/slices_table_iterator.py +0 -0
  99. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/test.py +0 -0
  100. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/test_max_graph_depth.py +0 -0
  101. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/test_memory_graph.py +0 -0
  102. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/test_memory_to_nodes.py +0 -0
  103. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/test_sequence.py +0 -0
  104. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/test_slicer.py +0 -0
  105. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/test_slices.py +0 -0
  106. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/test_slices_iterator.py +0 -0
  107. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph/utils.py +0 -0
  108. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph.egg-info/SOURCES.txt +0 -0
  109. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph.egg-info/dependency_links.txt +0 -0
  110. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph.egg-info/requires.txt +0 -0
  111. {memory_graph-0.3.53 → memory_graph-0.3.55}/memory_graph.egg-info/top_level.txt +0 -0
  112. {memory_graph-0.3.53 → memory_graph-0.3.55}/setup.cfg +0 -0
  113. {memory_graph-0.3.53 → memory_graph-0.3.55}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: memory_graph
3
- Version: 0.3.53
3
+ Version: 0.3.55
4
4
  Summary: Teaching tool and debugging aid in context of references, mutable data types, and shallow and deep copy.
5
5
  Author-email: Bas Terwijn <bterwijn@gmail.com>
6
6
  License: BSD 2-Clause License
@@ -52,12 +52,16 @@ Additionally [Graphviz](https://graphviz.org/download/) needs to be installed.
52
52
 
53
53
  # Highlights #
54
54
  ![vscode_copying.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/vscode_copying.gif)
55
- Run a live demo in the 👉 [**Memory Graph Web Debugger**](https://memory-graph.com/#play) 👈 now, no installation required!
55
+ Run a live demo in the 👉 [**Memory Graph Web Debugger**](https://memory-graph.com/#breakpoints=8&continues=1&timestep=1.0&play) 👈 now, no installation required!
56
56
 
57
57
  - learn the right **mental model** to think about Python data (references, mutability, shallow vs deep copy)
58
58
  - **visualize the structure of your data** to easily understand and debug any data structure
59
59
  - understand function calls, variable scope, and the **complete program state** through call stack visualization
60
60
 
61
+ An example Binary Tree data structure:
62
+ ![images/bin_tree.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/bin_tree.gif)
63
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/bin_tree.py&timestep=0.2&play).
64
+
61
65
  # Videos #
62
66
  | [![Quick Intro](https://img.youtube.com/vi/23_bHcr7hqo/0.jpg)](https://www.youtube.com/watch?v=23_bHcr7hqo) | [![Mutability](https://img.youtube.com/vi/pvIJgHCaXhU/0.jpg)](https://www.youtube.com/watch?v=pvIJgHCaXhU) |
63
67
  |:--:|:--:|
@@ -132,7 +136,7 @@ identical?: True
132
136
  ```
133
137
  A better way to understand what values are shared is to draw a graph using [memory_graph](https://pypi.org/project/memory-graph/).
134
138
 
135
- # Chapters #
139
+ # Topics #
136
140
 
137
141
  [Python Data Model](#python-data-model)
138
142
 
@@ -164,8 +168,6 @@ A better way to understand what values are shared is to draw a graph using [memo
164
168
 
165
169
  [Troubleshooting](#troubleshooting)
166
170
 
167
- [Social Media](#social-media)
168
-
169
171
  [Other Packages](#other-packages)
170
172
 
171
173
  ## Author ##
@@ -174,6 +176,10 @@ Bas Terwijn
174
176
  ## Inspiration ##
175
177
  Inspired by [Python Tutor](https://pythontutor.com/).
176
178
 
179
+ ## Social Media #
180
+ * [LinkedIn](https://www.linkedin.com/groups/13244150/)
181
+ * [Reddit](https://www.reddit.com/r/Python_memory_graph/)
182
+
177
183
  ## Supported by ##
178
184
  <img src="https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/uva.png" alt="University of Amsterdam" width="600">
179
185
 
@@ -274,6 +280,8 @@ mg.show(locals())
274
280
  ```
275
281
  ![copy_method.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/copy_method.png)
276
282
 
283
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/custom_copy.py&breakpoints=15&continues=1&play).
284
+
277
285
  ## Name Rebinding ##
278
286
  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 another value without effecting any other variables.
279
287
 
@@ -348,6 +356,8 @@ print(f"a:{a} b:{b} c:{c}")
348
356
  ```
349
357
  ![add_one.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/add_one.png)
350
358
 
359
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/function_call.py&play).
360
+
351
361
  In the printed output only `a` is changed as a result of the function call:
352
362
  ```
353
363
  a:[4, 3, 2, 1] b:(4, 3, 2) c:[4, 3, 2]
@@ -355,6 +365,8 @@ a:[4, 3, 2, 1] b:(4, 3, 2) c:[4, 3, 2]
355
365
 
356
366
  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.
357
367
 
368
+ Now is a good time to practice the Python Data Model. Here are [some exercises](https://github.com/bterwijn/memory_graph_videos/blob/main/exercises/exercises.md) on references, mutability, copies, and function calls.
369
+
358
370
  ## Block ##
359
371
  It is often helpful to temporarily block program execution to inspect the graph. For this we can use the `mg.block()` function:
360
372
 
@@ -384,16 +396,17 @@ def factorial(n):
384
396
 
385
397
  print( factorial(4) )
386
398
  ```
387
-
388
399
  ![factorial.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/factorial.gif)
389
400
 
390
401
  and the result is: 1 x 2 x 3 x 4 = 24
391
402
 
392
- ## Binary ##
393
- A more interesting recursive example is function `binary()` that converts a decimal integer to binary representation.
403
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/factorial.py&timestep=1.0&play).
404
+
405
+ ## Binary Conversion ##
406
+ A more interesting recursive example is function `binary()` that converts a integer from decimal to binary representation.
394
407
  ```python
395
408
  import memory_graph as mg
396
- mg.config.type_to_vertical[list] = False # horizontal lists
409
+ mg.config.type_to_horizontal[list] = True # horizontal lists
397
410
 
398
411
  def binary(value: int) -> list[int]:
399
412
  mg.block(mg.show(), mg.stack())
@@ -408,9 +421,11 @@ print( binary(100) )
408
421
  ```
409
422
  ![factorial.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/binary.gif)
410
423
  ```
411
- 1100100
424
+ [1, 1, 0, 0, 1, 0, 0]
412
425
  ```
413
426
 
427
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/binary_convert.py&timestep=1.0&play).
428
+
414
429
  ## Power Set ##
415
430
  A more complex recursive example is function `power_set()` where lists are shared by different function calls. A power set is the set of all subsets of a collection of values.
416
431
 
@@ -441,6 +456,8 @@ print( power_set(['a', 'b', 'c']) )
441
456
  [['a', 'b', 'c'], ['a', 'b'], ['a', 'c'], ['a'], ['b', 'c'], ['b'], ['c'], []]
442
457
  ```
443
458
 
459
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/power_set.py&timestep=1.0&play).
460
+
444
461
  # Debugging #
445
462
 
446
463
  For the best debugging experience with memory_graph set for example expression:
@@ -639,10 +656,10 @@ for i in range(n):
639
656
  Here we show values being inserted in a HashSet in PyCharm. When inserting the last value '44' we "Step Into" the code to show more of the details.
640
657
  ![images/hash_set.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/hash_set.gif)
641
658
 
642
- Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/hash_set.py&timestep=0.2&play).
659
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/hash_set.py&breakpoints=32&continues=1&timestep=0.5&play).
643
660
 
644
661
  # Configuration #
645
- Different aspects of memory_graph can be configured. The default configuration can be reset by calling 'mg.config_default.reset()'.
662
+ Different aspects of memory_graph can be configured. The default configuration can be reset by calling 'mg.config_default.reset()'. The Memory Graph Web Debugger gives examples of the [most important configurations](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/config.py&play).
646
663
 
647
664
  - ***mg.config.reopen_viewer*** : bool
648
665
  - If True the viewer is reopened each time show() is called, this might change window focus, default True.
@@ -677,8 +694,8 @@ Different aspects of memory_graph can be configured. The default configuration c
677
694
  - ***mg.config.type_to_color*** : dict[type, color]
678
695
  - Maps a type to the [graphviz color](https://graphviz.org/doc/info/colors.html) it gets in the graph.
679
696
 
680
- - ***mg.config.type_to_vertical*** : dict[type, bool]
681
- - 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.
697
+ - ***mg.config.type_to_horizontal*** : dict[type, bool]
698
+ - Maps a type to its orientation for Node_Linear and Node_Key_Value. Use 'True' for horizontal and 'False' for vertical. If not specified these nodes vertical unless they have references to children.
682
699
 
683
700
  - ***mg.config.type_to_slicer*** : dict[type, int]
684
701
  - 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.
@@ -735,7 +752,6 @@ mg.show(locals())
735
752
  ```
736
753
  ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_fail.png)
737
754
 
738
-
739
755
  ## All attributes using dir() ##
740
756
  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.
741
757
 
@@ -757,7 +773,7 @@ mg.config.type_to_slicer[bintrees.avltree.Node] = mg.Slicer()
757
773
 
758
774
  mg.show(locals())
759
775
  ```
760
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_dir.png)
776
+ ![avltree_dir.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_dir.png)
761
777
 
762
778
  Next figure out what the attributes are you want to graph and choose a Node type, there are four options:
763
779
 
@@ -780,7 +796,7 @@ mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.Node_Leaf(data,
780
796
 
781
797
  mg.show(locals())
782
798
  ```
783
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_leaf.png)
799
+ ![avltree_leaf.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_leaf.png)
784
800
 
785
801
  ## 2) Node_Linear ##
786
802
  Node_Linear shows multiple values in a line like a list.
@@ -804,7 +820,7 @@ mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.Node_Linear(data
804
820
 
805
821
  mg.show(locals())
806
822
  ```
807
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_linear.png)
823
+ ![avltree_linear.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_linear.png)
808
824
 
809
825
  ## 3) Node_Key_Value ##
810
826
  Node_Key_Value shows key-value pairs like a dictionary. Note the required `items()` call at the end.
@@ -828,7 +844,7 @@ mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.Node_Key_Value(d
828
844
 
829
845
  mg.show(locals())
830
846
  ```
831
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_key_value.png)
847
+ ![avltree_key_value.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_key_value.png)
832
848
 
833
849
  ## 4) Node_Table ##
834
850
  Node_Table shows all the values as a table.
@@ -850,7 +866,7 @@ mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.Node_Table(data,
850
866
 
851
867
  mg.show(locals())
852
868
  ```
853
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_table.png)
869
+ ![avltree_table.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_table.png)
854
870
 
855
871
  ## Binary Search ##
856
872
  For binary search we can use a List_View class to represent a particular sublist without making a list copy.
@@ -955,7 +971,7 @@ mg.config.type_to_depth[B] = 3
955
971
  mg.config.type_to_depth[id(c)] = 2
956
972
  mg.show(locals())
957
973
  ```
958
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/introspect_depth.png)
974
+ ![introspect_depth.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/introspect_depth.png)
959
975
 
960
976
  ## Hidden Edges ##
961
977
 
@@ -971,7 +987,7 @@ for i in range(20):
971
987
 
972
988
  mg.show(locals())
973
989
  ```
974
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/hidden_edges.png)
990
+ ![hidden_edges.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/hidden_edges.png)
975
991
 
976
992
  # Extensions #
977
993
  Different extensions are available for types from other Python packages.
@@ -994,6 +1010,8 @@ mg.show(locals())
994
1010
  ```
995
1011
  ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/extension_numpy.png)
996
1012
 
1013
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#micropip=numpy&codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/mg_numpy.py&continues=1).
1014
+
997
1015
  ## Pandas ##
998
1016
  Pandas types `Series` and `DataFrame` can be graphed with "memory_graph.extension_pandas":
999
1017
 
@@ -1013,6 +1031,8 @@ mg.show(locals())
1013
1031
  ```
1014
1032
  ![extension_pandas.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/extension_pandas.png)
1015
1033
 
1034
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#micropip=pandas&codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/mg_pandas.py&continues=1).
1035
+
1016
1036
  ## PyTorch ##
1017
1037
  Torch type `tensor` can be graphed with "memory_graph.extension_torch":
1018
1038
 
@@ -1087,13 +1107,9 @@ $ bash create_gif.sh animated
1087
1107
  ```
1088
1108
 
1089
1109
  # Troubleshooting #
1090
- - 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.
1110
+ - 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 'memory_graph.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 your default PDF reader. Another solution is to `render()` the graph to a different output format.
1091
1111
 
1092
1112
  - 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.
1093
1113
 
1094
- # Social Media #
1095
- * LinkedIn: https://www.linkedin.com/groups/13244150/
1096
- * Reddit: https://www.reddit.com/r/Python_memory_graph/
1097
-
1098
1114
  # Other Packages #
1099
1115
  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.
@@ -7,12 +7,16 @@ Additionally [Graphviz](https://graphviz.org/download/) needs to be installed.
7
7
 
8
8
  # Highlights #
9
9
  ![vscode_copying.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/vscode_copying.gif)
10
- Run a live demo in the 👉 [**Memory Graph Web Debugger**](https://memory-graph.com/#play) 👈 now, no installation required!
10
+ Run a live demo in the 👉 [**Memory Graph Web Debugger**](https://memory-graph.com/#breakpoints=8&continues=1&timestep=1.0&play) 👈 now, no installation required!
11
11
 
12
12
  - learn the right **mental model** to think about Python data (references, mutability, shallow vs deep copy)
13
13
  - **visualize the structure of your data** to easily understand and debug any data structure
14
14
  - understand function calls, variable scope, and the **complete program state** through call stack visualization
15
15
 
16
+ An example Binary Tree data structure:
17
+ ![images/bin_tree.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/bin_tree.gif)
18
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/bin_tree.py&timestep=0.2&play).
19
+
16
20
  # Videos #
17
21
  | [![Quick Intro](https://img.youtube.com/vi/23_bHcr7hqo/0.jpg)](https://www.youtube.com/watch?v=23_bHcr7hqo) | [![Mutability](https://img.youtube.com/vi/pvIJgHCaXhU/0.jpg)](https://www.youtube.com/watch?v=pvIJgHCaXhU) |
18
22
  |:--:|:--:|
@@ -87,7 +91,7 @@ identical?: True
87
91
  ```
88
92
  A better way to understand what values are shared is to draw a graph using [memory_graph](https://pypi.org/project/memory-graph/).
89
93
 
90
- # Chapters #
94
+ # Topics #
91
95
 
92
96
  [Python Data Model](#python-data-model)
93
97
 
@@ -119,8 +123,6 @@ A better way to understand what values are shared is to draw a graph using [memo
119
123
 
120
124
  [Troubleshooting](#troubleshooting)
121
125
 
122
- [Social Media](#social-media)
123
-
124
126
  [Other Packages](#other-packages)
125
127
 
126
128
  ## Author ##
@@ -129,6 +131,10 @@ Bas Terwijn
129
131
  ## Inspiration ##
130
132
  Inspired by [Python Tutor](https://pythontutor.com/).
131
133
 
134
+ ## Social Media #
135
+ * [LinkedIn](https://www.linkedin.com/groups/13244150/)
136
+ * [Reddit](https://www.reddit.com/r/Python_memory_graph/)
137
+
132
138
  ## Supported by ##
133
139
  <img src="https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/uva.png" alt="University of Amsterdam" width="600">
134
140
 
@@ -229,6 +235,8 @@ mg.show(locals())
229
235
  ```
230
236
  ![copy_method.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/copy_method.png)
231
237
 
238
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/custom_copy.py&breakpoints=15&continues=1&play).
239
+
232
240
  ## Name Rebinding ##
233
241
  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 another value without effecting any other variables.
234
242
 
@@ -303,6 +311,8 @@ print(f"a:{a} b:{b} c:{c}")
303
311
  ```
304
312
  ![add_one.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/add_one.png)
305
313
 
314
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/function_call.py&play).
315
+
306
316
  In the printed output only `a` is changed as a result of the function call:
307
317
  ```
308
318
  a:[4, 3, 2, 1] b:(4, 3, 2) c:[4, 3, 2]
@@ -310,6 +320,8 @@ a:[4, 3, 2, 1] b:(4, 3, 2) c:[4, 3, 2]
310
320
 
311
321
  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.
312
322
 
323
+ Now is a good time to practice the Python Data Model. Here are [some exercises](https://github.com/bterwijn/memory_graph_videos/blob/main/exercises/exercises.md) on references, mutability, copies, and function calls.
324
+
313
325
  ## Block ##
314
326
  It is often helpful to temporarily block program execution to inspect the graph. For this we can use the `mg.block()` function:
315
327
 
@@ -339,16 +351,17 @@ def factorial(n):
339
351
 
340
352
  print( factorial(4) )
341
353
  ```
342
-
343
354
  ![factorial.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/factorial.gif)
344
355
 
345
356
  and the result is: 1 x 2 x 3 x 4 = 24
346
357
 
347
- ## Binary ##
348
- A more interesting recursive example is function `binary()` that converts a decimal integer to binary representation.
358
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/factorial.py&timestep=1.0&play).
359
+
360
+ ## Binary Conversion ##
361
+ A more interesting recursive example is function `binary()` that converts a integer from decimal to binary representation.
349
362
  ```python
350
363
  import memory_graph as mg
351
- mg.config.type_to_vertical[list] = False # horizontal lists
364
+ mg.config.type_to_horizontal[list] = True # horizontal lists
352
365
 
353
366
  def binary(value: int) -> list[int]:
354
367
  mg.block(mg.show(), mg.stack())
@@ -363,9 +376,11 @@ print( binary(100) )
363
376
  ```
364
377
  ![factorial.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/binary.gif)
365
378
  ```
366
- 1100100
379
+ [1, 1, 0, 0, 1, 0, 0]
367
380
  ```
368
381
 
382
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/binary_convert.py&timestep=1.0&play).
383
+
369
384
  ## Power Set ##
370
385
  A more complex recursive example is function `power_set()` where lists are shared by different function calls. A power set is the set of all subsets of a collection of values.
371
386
 
@@ -396,6 +411,8 @@ print( power_set(['a', 'b', 'c']) )
396
411
  [['a', 'b', 'c'], ['a', 'b'], ['a', 'c'], ['a'], ['b', 'c'], ['b'], ['c'], []]
397
412
  ```
398
413
 
414
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/power_set.py&timestep=1.0&play).
415
+
399
416
  # Debugging #
400
417
 
401
418
  For the best debugging experience with memory_graph set for example expression:
@@ -594,10 +611,10 @@ for i in range(n):
594
611
  Here we show values being inserted in a HashSet in PyCharm. When inserting the last value '44' we "Step Into" the code to show more of the details.
595
612
  ![images/hash_set.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/hash_set.gif)
596
613
 
597
- Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/hash_set.py&timestep=0.2&play).
614
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/hash_set.py&breakpoints=32&continues=1&timestep=0.5&play).
598
615
 
599
616
  # Configuration #
600
- Different aspects of memory_graph can be configured. The default configuration can be reset by calling 'mg.config_default.reset()'.
617
+ Different aspects of memory_graph can be configured. The default configuration can be reset by calling 'mg.config_default.reset()'. The Memory Graph Web Debugger gives examples of the [most important configurations](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/config.py&play).
601
618
 
602
619
  - ***mg.config.reopen_viewer*** : bool
603
620
  - If True the viewer is reopened each time show() is called, this might change window focus, default True.
@@ -632,8 +649,8 @@ Different aspects of memory_graph can be configured. The default configuration c
632
649
  - ***mg.config.type_to_color*** : dict[type, color]
633
650
  - Maps a type to the [graphviz color](https://graphviz.org/doc/info/colors.html) it gets in the graph.
634
651
 
635
- - ***mg.config.type_to_vertical*** : dict[type, bool]
636
- - 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.
652
+ - ***mg.config.type_to_horizontal*** : dict[type, bool]
653
+ - Maps a type to its orientation for Node_Linear and Node_Key_Value. Use 'True' for horizontal and 'False' for vertical. If not specified these nodes vertical unless they have references to children.
637
654
 
638
655
  - ***mg.config.type_to_slicer*** : dict[type, int]
639
656
  - 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.
@@ -690,7 +707,6 @@ mg.show(locals())
690
707
  ```
691
708
  ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_fail.png)
692
709
 
693
-
694
710
  ## All attributes using dir() ##
695
711
  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.
696
712
 
@@ -712,7 +728,7 @@ mg.config.type_to_slicer[bintrees.avltree.Node] = mg.Slicer()
712
728
 
713
729
  mg.show(locals())
714
730
  ```
715
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_dir.png)
731
+ ![avltree_dir.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_dir.png)
716
732
 
717
733
  Next figure out what the attributes are you want to graph and choose a Node type, there are four options:
718
734
 
@@ -735,7 +751,7 @@ mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.Node_Leaf(data,
735
751
 
736
752
  mg.show(locals())
737
753
  ```
738
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_leaf.png)
754
+ ![avltree_leaf.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_leaf.png)
739
755
 
740
756
  ## 2) Node_Linear ##
741
757
  Node_Linear shows multiple values in a line like a list.
@@ -759,7 +775,7 @@ mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.Node_Linear(data
759
775
 
760
776
  mg.show(locals())
761
777
  ```
762
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_linear.png)
778
+ ![avltree_linear.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_linear.png)
763
779
 
764
780
  ## 3) Node_Key_Value ##
765
781
  Node_Key_Value shows key-value pairs like a dictionary. Note the required `items()` call at the end.
@@ -783,7 +799,7 @@ mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.Node_Key_Value(d
783
799
 
784
800
  mg.show(locals())
785
801
  ```
786
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_key_value.png)
802
+ ![avltree_key_value.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_key_value.png)
787
803
 
788
804
  ## 4) Node_Table ##
789
805
  Node_Table shows all the values as a table.
@@ -805,7 +821,7 @@ mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.Node_Table(data,
805
821
 
806
822
  mg.show(locals())
807
823
  ```
808
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_table.png)
824
+ ![avltree_table.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_table.png)
809
825
 
810
826
  ## Binary Search ##
811
827
  For binary search we can use a List_View class to represent a particular sublist without making a list copy.
@@ -910,7 +926,7 @@ mg.config.type_to_depth[B] = 3
910
926
  mg.config.type_to_depth[id(c)] = 2
911
927
  mg.show(locals())
912
928
  ```
913
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/introspect_depth.png)
929
+ ![introspect_depth.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/introspect_depth.png)
914
930
 
915
931
  ## Hidden Edges ##
916
932
 
@@ -926,7 +942,7 @@ for i in range(20):
926
942
 
927
943
  mg.show(locals())
928
944
  ```
929
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/hidden_edges.png)
945
+ ![hidden_edges.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/hidden_edges.png)
930
946
 
931
947
  # Extensions #
932
948
  Different extensions are available for types from other Python packages.
@@ -949,6 +965,8 @@ mg.show(locals())
949
965
  ```
950
966
  ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/extension_numpy.png)
951
967
 
968
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#micropip=numpy&codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/mg_numpy.py&continues=1).
969
+
952
970
  ## Pandas ##
953
971
  Pandas types `Series` and `DataFrame` can be graphed with "memory_graph.extension_pandas":
954
972
 
@@ -968,6 +986,8 @@ mg.show(locals())
968
986
  ```
969
987
  ![extension_pandas.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/extension_pandas.png)
970
988
 
989
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#micropip=pandas&codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/mg_pandas.py&continues=1).
990
+
971
991
  ## PyTorch ##
972
992
  Torch type `tensor` can be graphed with "memory_graph.extension_torch":
973
993
 
@@ -1042,13 +1062,9 @@ $ bash create_gif.sh animated
1042
1062
  ```
1043
1063
 
1044
1064
  # Troubleshooting #
1045
- - 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.
1065
+ - 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 'memory_graph.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 your default PDF reader. Another solution is to `render()` the graph to a different output format.
1046
1066
 
1047
1067
  - 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.
1048
1068
 
1049
- # Social Media #
1050
- * LinkedIn: https://www.linkedin.com/groups/13244150/
1051
- * Reddit: https://www.reddit.com/r/Python_memory_graph/
1052
-
1053
1069
  # Other Packages #
1054
1070
  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.
@@ -1,6 +1,6 @@
1
1
  import memory_graph as mg
2
2
  import typing
3
- mg.config.type_to_vertical[list] = False # horizontal lists
3
+ mg.config.type_to_horizontal[list] = True # horizontal lists
4
4
 
5
5
  def binary(value: int) -> typing.List[int]:
6
6
  mg.render(mg.stack(), 'binary.png', numbered=True)
@@ -2,7 +2,7 @@
2
2
  # Copyright (c) 2023, Bas Terwijn.
3
3
  # SPDX-License-Identifier: BSD-2-Clause
4
4
 
5
- __version__ = "0.3.53"
5
+ __version__ = "0.3.55"
6
6
  __author__ = 'Bas Terwijn'
7
7
 
8
8
  import memory_graph.memory_to_nodes as memory_to_nodes
@@ -36,6 +36,7 @@ type_to_node = { }
36
36
 
37
37
  type_to_color = { }
38
38
 
39
+ type_to_horizontal = { }
39
40
  type_to_vertical = { }
40
41
 
41
42
  type_to_slicer = { }
@@ -103,10 +103,12 @@ def reset():
103
103
  }
104
104
 
105
105
 
106
- """ Types that will be visualized in vertical orientation if 'True', or horizontal orientation
107
- if 'False'. Otherwise the Node decides based on it having references."""
108
- config.type_to_vertical_orientation = {
109
- }
106
+ """ Types that will be visualized in horizontal or vertical orientation based on a True/False value.
107
+ The 'type_to_horizontal' takes precedence over 'type_to_vertical'.
108
+ If no boolean value is present the Node decides based on it having references."""
109
+ config.type_to_horizontal = {}
110
+ config.type_to_vertical = {}
111
+
110
112
 
111
113
  """ Slicer objects for different types. """
112
114
  config.type_to_slicer = {
@@ -23,10 +23,17 @@ def get_color(node, default='white'):
23
23
  default)
24
24
 
25
25
  def get_vertical(node, default):
26
+ horizontal = get_property(node.get_id(),
27
+ node.get_type(),
28
+ type(node),
29
+ config.type_to_horizontal,
30
+ None)
31
+ if isinstance(horizontal, bool):
32
+ return not horizontal
26
33
  return get_property(node.get_id(),
27
34
  node.get_type(),
28
35
  type(node),
29
- config.type_to_vertical,
36
+ config.type_to_vertical,
30
37
  default)
31
38
 
32
39
  def get_slicer(node, data, default=Slicer(3,2,3)):