memory-graph 0.3.10__tar.gz → 0.3.12__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 (90) hide show
  1. {memory_graph-0.3.10/memory_graph.egg-info → memory_graph-0.3.12}/PKG-INFO +13 -11
  2. {memory_graph-0.3.10 → memory_graph-0.3.12}/README.md +12 -10
  3. memory_graph-0.3.12/images/debug_vscode.png +0 -0
  4. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/factorial.gif +0 -0
  5. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph/__init__.py +4 -2
  6. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph/config.py +2 -1
  7. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph/config_default.py +2 -2
  8. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph/html_table.py +1 -1
  9. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph/memory_to_nodes.py +7 -7
  10. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph/test.py +1 -1
  11. memory_graph-0.3.12/memory_graph/test_max_graph_depth.py +27 -0
  12. {memory_graph-0.3.10 → memory_graph-0.3.12/memory_graph.egg-info}/PKG-INFO +13 -11
  13. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph.egg-info/SOURCES.txt +2 -0
  14. {memory_graph-0.3.10 → memory_graph-0.3.12}/setup.py +1 -1
  15. {memory_graph-0.3.10 → memory_graph-0.3.12}/src/auto_memory_graph.py +5 -2
  16. {memory_graph-0.3.10 → memory_graph-0.3.12}/src/pyodide.html +6 -3
  17. {memory_graph-0.3.10 → memory_graph-0.3.12}/LICENSE.txt +0 -0
  18. {memory_graph-0.3.10 → memory_graph-0.3.12}/MANIFEST.in +0 -0
  19. {memory_graph-0.3.10 → memory_graph-0.3.12}/TODO.txt +0 -0
  20. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/add_one.png +0 -0
  21. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/add_one.py +0 -0
  22. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/avltree.py +0 -0
  23. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/avltree_base.png +0 -0
  24. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/avltree_dir.png +0 -0
  25. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/avltree_fail.png +0 -0
  26. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/avltree_key_value.png +0 -0
  27. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/avltree_linear.png +0 -0
  28. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/avltree_table.png +0 -0
  29. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/bin_tree.png +0 -0
  30. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/bin_tree.py +0 -0
  31. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/copies.png +0 -0
  32. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/copies.py +0 -0
  33. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/copy_method.png +0 -0
  34. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/copy_method.py +0 -0
  35. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/create_gif.sh +0 -0
  36. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/create_images.sh +0 -0
  37. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/debugging.gif +0 -0
  38. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/debugging.py +0 -0
  39. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/extension_numpy.png +0 -0
  40. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/extension_numpy.py +0 -0
  41. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/extension_pandas.png +0 -0
  42. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/extension_pandas.py +0 -0
  43. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/factorial.py +0 -0
  44. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/hash_set.png +0 -0
  45. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/hash_set.py +0 -0
  46. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/highlight.png +0 -0
  47. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/highlight.py +0 -0
  48. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/immutable.py +0 -0
  49. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/immutable1.png +0 -0
  50. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/immutable2.png +0 -0
  51. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/ipython.png +0 -0
  52. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/jupyter_example.ipynb +0 -0
  53. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/jupyter_example.png +0 -0
  54. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/linked_list.png +0 -0
  55. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/linked_list.py +0 -0
  56. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/many_types.png +0 -0
  57. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/many_types.py +0 -0
  58. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/mutable.py +0 -0
  59. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/mutable1.png +0 -0
  60. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/mutable2.png +0 -0
  61. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/power_set.gif +0 -0
  62. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/power_set.py +0 -0
  63. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/pyodide.png +0 -0
  64. {memory_graph-0.3.10 → memory_graph-0.3.12}/images/uva.png +0 -0
  65. {memory_graph-0.3.10 → memory_graph-0.3.12}/install.txt +0 -0
  66. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph/config_helpers.py +0 -0
  67. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph/extension_numpy.py +0 -0
  68. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph/extension_pandas.py +0 -0
  69. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph/list_view.py +0 -0
  70. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph/node_base.py +0 -0
  71. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph/node_key_value.py +0 -0
  72. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph/node_linear.py +0 -0
  73. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph/node_table.py +0 -0
  74. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph/sequence.py +0 -0
  75. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph/slicer.py +0 -0
  76. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph/slices.py +0 -0
  77. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph/slices_iterator.py +0 -0
  78. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph/slices_table_iterator.py +0 -0
  79. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph/test_memory_graph.py +0 -0
  80. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph/test_memory_to_nodes.py +0 -0
  81. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph/test_sequence.py +0 -0
  82. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph/test_slicer.py +0 -0
  83. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph/test_slices.py +0 -0
  84. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph/test_slices_iterator.py +0 -0
  85. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph/utils.py +0 -0
  86. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph.egg-info/dependency_links.txt +0 -0
  87. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph.egg-info/requires.txt +0 -0
  88. {memory_graph-0.3.10 → memory_graph-0.3.12}/memory_graph.egg-info/top_level.txt +0 -0
  89. {memory_graph-0.3.10 → memory_graph-0.3.12}/setup.cfg +0 -0
  90. {memory_graph-0.3.10 → memory_graph-0.3.12}/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.10
3
+ Version: 0.3.12
4
4
  Summary: Draws a graph of your data to analyze its structure.
5
5
  Home-page: https://github.com/bterwijn/memory_graph
6
6
  Author: Bas Terwijn
@@ -156,7 +156,7 @@ mg.render(locals(), 'immutable2.png')
156
156
 
157
157
 
158
158
  ### Mutable Type ###
159
- With mutable types the result is different. In the code below variable `a` and `b` both reference the same `list` value [4, 3, 2]. A `list` is a mutable type and therefore when we change variable `a` its value **can** be mutated in place and thus `a` and `b` both reference the same new value afterwards. Thus changing `a` also changes `b` and vice versa. Sometimes we want this but other times we don't and then we will have to make a copy so that `a` and `b` are independent.
159
+ With mutable types the result is different. In the code below variable `a` and `b` both reference the same `list` value [4, 3, 2]. A `list` is a mutable type and therefore when we change variable `a` its value **can** be mutated in place and thus `a` and `b` both reference the same new value afterwards. Thus changing `a` also changes `b` and vice versa. Sometimes we want this but other times we don't and then we will have to make a copy ourselfs so that `a` and `b` are independent.
160
160
 
161
161
  ```python
162
162
  import memory_graph as mg
@@ -171,7 +171,7 @@ mg.render(locals(), 'mutable2.png')
171
171
  |:-----------------------------------------------------------:|:-------------------------------------------------------------:|
172
172
  | mutable1.png | mutable2.png |
173
173
 
174
- One practical reason why Python makes the distinction between mutable and immutable types is that a value of a mutable type can be large, making it inefficient to copy each time we change it. Immutable values generally don't need to change as much, or are small which makes copying less of a concern.
174
+ One practical reason why Python makes the distinction between mutable and immutable types is that a value of a mutable type can be large, making it inefficient to copy each time we change it. Immutable values generally don't need to change as much, or are small making copying less of a concern.
175
175
 
176
176
  ### Copying ###
177
177
  Python offers three different "copy" options that we will demonstrate using a nested list:
@@ -264,7 +264,7 @@ This function:
264
264
  * then blocks execution until the <Enter> key is pressed
265
265
  * finally returns the value of the `fun()` call
266
266
 
267
- to change it's behavior:
267
+ to change its behavior:
268
268
  * Set `mg.block_prints_location = False` to skip printing the source location.
269
269
  * Set `mg.press_enter_message = None` to skip printing "Press <Enter> to continue...".
270
270
 
@@ -326,7 +326,7 @@ For the best debugging experience with memory_graph set for example expression:
326
326
  ```
327
327
  mg.render(locals(), "my_graph.pdf")
328
328
  ```
329
- as a *watch* in a debugger tool such as the integrated debugger in Visual Studio Code. Then open the "my_graph.pdf" output file to continuously see all the local variables while debugging. This avoids having to add any memory_graph `show()`, `render()` calls to your code.
329
+ as a *watch* in a debugger tool such as the integrated debugger in Visual Studio Code. Then open the "my_graph.pdf" output file to continuously see all the local variables while debugging. This avoids having to add any memory_graph `show()` or `render()` calls to your code.
330
330
 
331
331
  ### Call Stack in Watch Context ###
332
332
  The ```mg.get_call_stack()``` doesn't work well in *watch* context in most debuggers because debuggers introduce additional stack frames that cause problems. Use these alternative functions for various debuggers to filter out these problematic stack frames:
@@ -337,6 +337,8 @@ The ```mg.get_call_stack()``` doesn't work well in *watch* context in most debug
337
337
  | **Visual Studio Code** | `mg.get_call_stack_vscode()` |
338
338
  | **Pycharm** | `mg.get_call_stack_pycharm()` |
339
339
 
340
+ ![debug_vscode.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/debug_vscode.png)
341
+
340
342
  #### Other Debuggers ####
341
343
  For other debuggers, invoke this function within the *watch* context. Then, in the "call_stack.txt" file, identify the slice of functions you wish to include in the call stack.
342
344
  ```
@@ -508,8 +510,8 @@ for i in range(n):
508
510
  ## Configuration ##
509
511
  Different aspects of memory_graph can be configured. The default configuration is reset by importing 'memory_graph.config_default'.
510
512
 
511
- - ***mg.config.max_tree_depth*** : int
512
- - The maxium depth of the graph. A `★` symbol indictes where the graph is cut short.
513
+ - ***mg.config.max_graph_depth*** : int
514
+ - The maxium depth of the graph with default value 12. A `✂` (scissor) symbol indicates where the graph is cut short. Dashed references indicate that there are more references to a node than are shown.
513
515
 
514
516
  - ***mg.config.max_string_length*** : int
515
517
  - The maximum length of strings shown in the graph. Longer strings will be truncated.
@@ -533,7 +535,7 @@ Different aspects of memory_graph can be configured. The default configuration i
533
535
  - Maps each type to a Slicer. A slicer determines how many elements of a data type are shown in the graph to prevent the graph from getting too big. 'Slicer()' does no slicing, 'Slicer(1,2,3)' shows just 1 element at the beginning, 2 in the middle, and 3 at the end.
534
536
 
535
537
  ### Temporary Configuration ###
536
- In addition to the global configuration, a temporary configuration can be set for a single `show()`, `render()`, `d()`, `ds()` call to change the colors, orientation, and slicer. This example highlights a particular list element in red, gives it a horizontal orientation, and overwrites the default slicer for lists:
538
+ In addition to the global configuration, a temporary configuration can be set for a single `show()` or `render()` call to change the colors, orientation, and slicer. This example highlights a particular list element in red, gives it a horizontal orientation, and overwrites the default slicer for lists:
537
539
 
538
540
  ```python
539
541
  import memory_graph as mg
@@ -554,7 +556,7 @@ mg.show( locals(),
554
556
  Different extensions are available for types from other Python packages.
555
557
 
556
558
  ### Numpy ###
557
- Numpy types `arrray` and `matrix` and `ndarray` can be graphed with "memory_graph.extension_numpy":
559
+ Numpy types `array` and `matrix` and `ndarray` can be graphed with "memory_graph.extension_numpy":
558
560
 
559
561
  ```python
560
562
  import memory_graph as mg
@@ -740,7 +742,7 @@ See for example [jupyter_example.ipynb](https://raw.githubusercontent.com/bterwi
740
742
  ## ipython ##
741
743
  In ipython `locals()` has additional variables that cause problems in the graph, use `mg.locals_ipython()` to get the local variables with these problematic variables filtered out. Use `mg.get_call_stack_ipython()` to get the whole call stack with these variables filtered out.
742
744
 
743
- Additionally install file [auto_memory_graph.py](https://raw.githubusercontent.com/bterwijn/memory_graph/main/sc/auto_memory_graph.py) in the ipython startup directory:
745
+ Additionally install file [auto_memory_graph.py](https://raw.githubusercontent.com/bterwijn/memory_graph/main/src/auto_memory_graph.py) in the ipython startup directory:
744
746
  * Linux/Mac: ~/.ipython/profile_default/startup/
745
747
  * Windows: %USERPROFILE%\.ipython\profile_default\startup\
746
748
 
@@ -748,7 +750,7 @@ Then after starting 'ipython' call function `mg_switch()` to turn on/off the aut
748
750
  ![ipyton.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/ipython.png)
749
751
 
750
752
  ## In the Browser ##
751
- We can run memory_graph in the browser: <a href="https://bterwijn.github.io/memory_graph/src/pyodide.html" target="_blank">Pyodide Example</a>
753
+ We can also run memory_graph in the browser: <a href="https://bterwijn.github.io/memory_graph/src/pyodide.html" target="_blank">Pyodide Example</a>
752
754
  ![pyodide.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/pyodide.png)
753
755
 
754
756
  ## Troubleshooting ##
@@ -137,7 +137,7 @@ mg.render(locals(), 'immutable2.png')
137
137
 
138
138
 
139
139
  ### Mutable Type ###
140
- With mutable types the result is different. In the code below variable `a` and `b` both reference the same `list` value [4, 3, 2]. A `list` is a mutable type and therefore when we change variable `a` its value **can** be mutated in place and thus `a` and `b` both reference the same new value afterwards. Thus changing `a` also changes `b` and vice versa. Sometimes we want this but other times we don't and then we will have to make a copy so that `a` and `b` are independent.
140
+ With mutable types the result is different. In the code below variable `a` and `b` both reference the same `list` value [4, 3, 2]. A `list` is a mutable type and therefore when we change variable `a` its value **can** be mutated in place and thus `a` and `b` both reference the same new value afterwards. Thus changing `a` also changes `b` and vice versa. Sometimes we want this but other times we don't and then we will have to make a copy ourselfs so that `a` and `b` are independent.
141
141
 
142
142
  ```python
143
143
  import memory_graph as mg
@@ -152,7 +152,7 @@ mg.render(locals(), 'mutable2.png')
152
152
  |:-----------------------------------------------------------:|:-------------------------------------------------------------:|
153
153
  | mutable1.png | mutable2.png |
154
154
 
155
- One practical reason why Python makes the distinction between mutable and immutable types is that a value of a mutable type can be large, making it inefficient to copy each time we change it. Immutable values generally don't need to change as much, or are small which makes copying less of a concern.
155
+ One practical reason why Python makes the distinction between mutable and immutable types is that a value of a mutable type can be large, making it inefficient to copy each time we change it. Immutable values generally don't need to change as much, or are small making copying less of a concern.
156
156
 
157
157
  ### Copying ###
158
158
  Python offers three different "copy" options that we will demonstrate using a nested list:
@@ -245,7 +245,7 @@ This function:
245
245
  * then blocks execution until the &lt;Enter&gt; key is pressed
246
246
  * finally returns the value of the `fun()` call
247
247
 
248
- to change it's behavior:
248
+ to change its behavior:
249
249
  * Set `mg.block_prints_location = False` to skip printing the source location.
250
250
  * Set `mg.press_enter_message = None` to skip printing "Press &lt;Enter&gt; to continue...".
251
251
 
@@ -307,7 +307,7 @@ For the best debugging experience with memory_graph set for example expression:
307
307
  ```
308
308
  mg.render(locals(), "my_graph.pdf")
309
309
  ```
310
- as a *watch* in a debugger tool such as the integrated debugger in Visual Studio Code. Then open the "my_graph.pdf" output file to continuously see all the local variables while debugging. This avoids having to add any memory_graph `show()`, `render()` calls to your code.
310
+ as a *watch* in a debugger tool such as the integrated debugger in Visual Studio Code. Then open the "my_graph.pdf" output file to continuously see all the local variables while debugging. This avoids having to add any memory_graph `show()` or `render()` calls to your code.
311
311
 
312
312
  ### Call Stack in Watch Context ###
313
313
  The ```mg.get_call_stack()``` doesn't work well in *watch* context in most debuggers because debuggers introduce additional stack frames that cause problems. Use these alternative functions for various debuggers to filter out these problematic stack frames:
@@ -318,6 +318,8 @@ The ```mg.get_call_stack()``` doesn't work well in *watch* context in most debug
318
318
  | **Visual Studio Code** | `mg.get_call_stack_vscode()` |
319
319
  | **Pycharm** | `mg.get_call_stack_pycharm()` |
320
320
 
321
+ ![debug_vscode.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/debug_vscode.png)
322
+
321
323
  #### Other Debuggers ####
322
324
  For other debuggers, invoke this function within the *watch* context. Then, in the "call_stack.txt" file, identify the slice of functions you wish to include in the call stack.
323
325
  ```
@@ -489,8 +491,8 @@ for i in range(n):
489
491
  ## Configuration ##
490
492
  Different aspects of memory_graph can be configured. The default configuration is reset by importing 'memory_graph.config_default'.
491
493
 
492
- - ***mg.config.max_tree_depth*** : int
493
- - The maxium depth of the graph. A `★` symbol indictes where the graph is cut short.
494
+ - ***mg.config.max_graph_depth*** : int
495
+ - The maxium depth of the graph with default value 12. A `✂` (scissor) symbol indicates where the graph is cut short. Dashed references indicate that there are more references to a node than are shown.
494
496
 
495
497
  - ***mg.config.max_string_length*** : int
496
498
  - The maximum length of strings shown in the graph. Longer strings will be truncated.
@@ -514,7 +516,7 @@ Different aspects of memory_graph can be configured. The default configuration i
514
516
  - Maps each type to a Slicer. A slicer determines how many elements of a data type are shown in the graph to prevent the graph from getting too big. 'Slicer()' does no slicing, 'Slicer(1,2,3)' shows just 1 element at the beginning, 2 in the middle, and 3 at the end.
515
517
 
516
518
  ### Temporary Configuration ###
517
- In addition to the global configuration, a temporary configuration can be set for a single `show()`, `render()`, `d()`, `ds()` call to change the colors, orientation, and slicer. This example highlights a particular list element in red, gives it a horizontal orientation, and overwrites the default slicer for lists:
519
+ In addition to the global configuration, a temporary configuration can be set for a single `show()` or `render()` call to change the colors, orientation, and slicer. This example highlights a particular list element in red, gives it a horizontal orientation, and overwrites the default slicer for lists:
518
520
 
519
521
  ```python
520
522
  import memory_graph as mg
@@ -535,7 +537,7 @@ mg.show( locals(),
535
537
  Different extensions are available for types from other Python packages.
536
538
 
537
539
  ### Numpy ###
538
- Numpy types `arrray` and `matrix` and `ndarray` can be graphed with "memory_graph.extension_numpy":
540
+ Numpy types `array` and `matrix` and `ndarray` can be graphed with "memory_graph.extension_numpy":
539
541
 
540
542
  ```python
541
543
  import memory_graph as mg
@@ -721,7 +723,7 @@ See for example [jupyter_example.ipynb](https://raw.githubusercontent.com/bterwi
721
723
  ## ipython ##
722
724
  In ipython `locals()` has additional variables that cause problems in the graph, use `mg.locals_ipython()` to get the local variables with these problematic variables filtered out. Use `mg.get_call_stack_ipython()` to get the whole call stack with these variables filtered out.
723
725
 
724
- Additionally install file [auto_memory_graph.py](https://raw.githubusercontent.com/bterwijn/memory_graph/main/sc/auto_memory_graph.py) in the ipython startup directory:
726
+ Additionally install file [auto_memory_graph.py](https://raw.githubusercontent.com/bterwijn/memory_graph/main/src/auto_memory_graph.py) in the ipython startup directory:
725
727
  * Linux/Mac: ~/.ipython/profile_default/startup/
726
728
  * Windows: %USERPROFILE%\.ipython\profile_default\startup\
727
729
 
@@ -729,7 +731,7 @@ Then after starting 'ipython' call function `mg_switch()` to turn on/off the aut
729
731
  ![ipyton.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/ipython.png)
730
732
 
731
733
  ## In the Browser ##
732
- We can run memory_graph in the browser: <a href="https://bterwijn.github.io/memory_graph/src/pyodide.html" target="_blank">Pyodide Example</a>
734
+ We can also run memory_graph in the browser: <a href="https://bterwijn.github.io/memory_graph/src/pyodide.html" target="_blank">Pyodide Example</a>
733
735
  ![pyodide.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/pyodide.png)
734
736
 
735
737
  ## Troubleshooting ##
@@ -13,7 +13,7 @@ import sys
13
13
 
14
14
  import graphviz
15
15
 
16
- __version__ = "0.3.10"
16
+ __version__ = "0.3.12"
17
17
  __author__ = 'Bas Terwijn'
18
18
  render_filename = 'memory_graph.pdf'
19
19
  block_prints_location = True
@@ -167,7 +167,9 @@ def stack_frames_to_dict(frames):
167
167
  """ Returns a dictionary representing the data on the call stack.
168
168
  Each key is the stack level and function name, each value is the locals of the frame at that level.
169
169
  """
170
- return {f"{level}: {frameInfo.function}" : frameInfo.frame.f_locals
170
+ def to_dict(value): # fix by TerenceTux for Python 3.13
171
+ return {k: v for k, v in value.items()}
172
+ return {f"{level}: {frameInfo.function}" : to_dict(frameInfo.frame.f_locals)
171
173
  for level, frameInfo in enumerate(frames)}
172
174
 
173
175
  def get_call_stack(up_to_function="<module>",stack_index=0):
@@ -4,7 +4,8 @@
4
4
 
5
5
  """ Configuration file for the graph visualizer. The configuration values are set later by the 'config_default.py' file. """
6
6
 
7
- max_tree_depth = None
7
+ max_graph_depth = None
8
+ graph_cut_symbol = None
8
9
  max_missing_edges = None
9
10
  max_string_length = None
10
11
  graph_stability = None
@@ -16,8 +16,8 @@ import memory_graph.utils as utils
16
16
  import types
17
17
 
18
18
  """ The maximum depth of nodes in the graph. When the graph gets too big set this to a small positive number. A `✂` symbol indictes where the graph is cut short. """
19
- config.max_tree_depth = -1
20
-
19
+ config.max_graph_depth = 12
20
+ config.graph_cut_symbol = '✂'
21
21
  config.max_missing_edges = 3
22
22
 
23
23
  """ The maximum length of strings shown in the graph. Longer strings will be truncated. """
@@ -80,7 +80,7 @@ class HTML_Table:
80
80
  if child_id in id_to_slices:
81
81
  self.add_reference(node, child, rounded, border, dashed)
82
82
  else:
83
- self.add_value("✂", rounded, border)
83
+ self.add_value(config.graph_cut_symbol, rounded, border)
84
84
  else:
85
85
  self.add_value(child, rounded, border)
86
86
 
@@ -45,10 +45,10 @@ def read_nodes(data):
45
45
 
46
46
  # --------------------------------------------------------------------------------------------
47
47
 
48
- def slice_nodes(nodes, root_id, max_tree_depth):
48
+ def slice_nodes(nodes, root_id, max_graph_depth):
49
49
 
50
- def slice_nodes_recursive(nodes, node_id, id_to_slices, max_tree_depth):
51
- if max_tree_depth == 0 or node_id in id_to_slices:
50
+ def slice_nodes_recursive(nodes, node_id, id_to_slices, max_graph_depth):
51
+ if max_graph_depth == 0 or node_id in id_to_slices:
52
52
  return
53
53
  if node_id in nodes:
54
54
  node = nodes[node_id]
@@ -60,11 +60,11 @@ def slice_nodes(nodes, root_id, max_tree_depth):
60
60
  slices = children.slice(slicer)
61
61
  id_to_slices[node_id] = slices
62
62
  if not node.is_hidden_node():
63
- max_tree_depth -= 1
63
+ max_graph_depth -= 1
64
64
  for index in slices:
65
- slice_nodes_recursive(nodes, id(children[index]), id_to_slices, max_tree_depth)
65
+ slice_nodes_recursive(nodes, id(children[index]), id_to_slices, max_graph_depth)
66
66
  id_to_slices = {}
67
- slice_nodes_recursive(nodes, root_id, id_to_slices, max_tree_depth)
67
+ slice_nodes_recursive(nodes, root_id, id_to_slices, max_graph_depth)
68
68
  return id_to_slices
69
69
 
70
70
  # --------------------------------------------------------------------------------------------
@@ -175,7 +175,7 @@ def build_graph(graphviz_graph, nodes, root_id, id_to_slices):
175
175
  def memory_to_nodes(data):
176
176
  nodes, root_id = read_nodes(data)
177
177
  #print('nodes:',nodes,'root_id:',root_id)
178
- id_to_slices = slice_nodes(nodes, root_id, config.max_tree_depth)
178
+ id_to_slices = slice_nodes(nodes, root_id, config.max_graph_depth)
179
179
  #print('id_to_slices:',id_to_slices)
180
180
  id_to_slices = add_missing_edges(nodes, id_to_slices, config.max_missing_edges)
181
181
  #print('id_to_slices:',id_to_slices)
@@ -214,7 +214,7 @@ class BinTree:
214
214
 
215
215
  def test_missing_edges(fun):
216
216
  random.seed(0)
217
- config.max_tree_depth = 7
217
+ config.max_graph_depth = 7
218
218
  config.max_missing_edges = 5
219
219
  tree = BinTree()
220
220
  last_node = None
@@ -0,0 +1,27 @@
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
+
7
+ def build_nested_list(depth = 15):
8
+ first = [1,2]
9
+ last = first
10
+ if depth>0:
11
+ first2, last = build_nested_list(depth-1)
12
+ first.append(first2)
13
+ return first, last
14
+
15
+ first,last = build_nested_list(15)
16
+ for i in range(20):
17
+ last.append('X')
18
+
19
+ child = ('who', 'are', 'my', 'parents?')
20
+ last[4] = child
21
+ last[5] = child
22
+ last[6] = child
23
+ last[7] = child
24
+ last[8] = child
25
+
26
+ mg.show([first,child])
27
+ #mg.show([first])
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: memory_graph
3
- Version: 0.3.10
3
+ Version: 0.3.12
4
4
  Summary: Draws a graph of your data to analyze its structure.
5
5
  Home-page: https://github.com/bterwijn/memory_graph
6
6
  Author: Bas Terwijn
@@ -156,7 +156,7 @@ mg.render(locals(), 'immutable2.png')
156
156
 
157
157
 
158
158
  ### Mutable Type ###
159
- With mutable types the result is different. In the code below variable `a` and `b` both reference the same `list` value [4, 3, 2]. A `list` is a mutable type and therefore when we change variable `a` its value **can** be mutated in place and thus `a` and `b` both reference the same new value afterwards. Thus changing `a` also changes `b` and vice versa. Sometimes we want this but other times we don't and then we will have to make a copy so that `a` and `b` are independent.
159
+ With mutable types the result is different. In the code below variable `a` and `b` both reference the same `list` value [4, 3, 2]. A `list` is a mutable type and therefore when we change variable `a` its value **can** be mutated in place and thus `a` and `b` both reference the same new value afterwards. Thus changing `a` also changes `b` and vice versa. Sometimes we want this but other times we don't and then we will have to make a copy ourselfs so that `a` and `b` are independent.
160
160
 
161
161
  ```python
162
162
  import memory_graph as mg
@@ -171,7 +171,7 @@ mg.render(locals(), 'mutable2.png')
171
171
  |:-----------------------------------------------------------:|:-------------------------------------------------------------:|
172
172
  | mutable1.png | mutable2.png |
173
173
 
174
- One practical reason why Python makes the distinction between mutable and immutable types is that a value of a mutable type can be large, making it inefficient to copy each time we change it. Immutable values generally don't need to change as much, or are small which makes copying less of a concern.
174
+ One practical reason why Python makes the distinction between mutable and immutable types is that a value of a mutable type can be large, making it inefficient to copy each time we change it. Immutable values generally don't need to change as much, or are small making copying less of a concern.
175
175
 
176
176
  ### Copying ###
177
177
  Python offers three different "copy" options that we will demonstrate using a nested list:
@@ -264,7 +264,7 @@ This function:
264
264
  * then blocks execution until the &lt;Enter&gt; key is pressed
265
265
  * finally returns the value of the `fun()` call
266
266
 
267
- to change it's behavior:
267
+ to change its behavior:
268
268
  * Set `mg.block_prints_location = False` to skip printing the source location.
269
269
  * Set `mg.press_enter_message = None` to skip printing "Press &lt;Enter&gt; to continue...".
270
270
 
@@ -326,7 +326,7 @@ For the best debugging experience with memory_graph set for example expression:
326
326
  ```
327
327
  mg.render(locals(), "my_graph.pdf")
328
328
  ```
329
- as a *watch* in a debugger tool such as the integrated debugger in Visual Studio Code. Then open the "my_graph.pdf" output file to continuously see all the local variables while debugging. This avoids having to add any memory_graph `show()`, `render()` calls to your code.
329
+ as a *watch* in a debugger tool such as the integrated debugger in Visual Studio Code. Then open the "my_graph.pdf" output file to continuously see all the local variables while debugging. This avoids having to add any memory_graph `show()` or `render()` calls to your code.
330
330
 
331
331
  ### Call Stack in Watch Context ###
332
332
  The ```mg.get_call_stack()``` doesn't work well in *watch* context in most debuggers because debuggers introduce additional stack frames that cause problems. Use these alternative functions for various debuggers to filter out these problematic stack frames:
@@ -337,6 +337,8 @@ The ```mg.get_call_stack()``` doesn't work well in *watch* context in most debug
337
337
  | **Visual Studio Code** | `mg.get_call_stack_vscode()` |
338
338
  | **Pycharm** | `mg.get_call_stack_pycharm()` |
339
339
 
340
+ ![debug_vscode.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/debug_vscode.png)
341
+
340
342
  #### Other Debuggers ####
341
343
  For other debuggers, invoke this function within the *watch* context. Then, in the "call_stack.txt" file, identify the slice of functions you wish to include in the call stack.
342
344
  ```
@@ -508,8 +510,8 @@ for i in range(n):
508
510
  ## Configuration ##
509
511
  Different aspects of memory_graph can be configured. The default configuration is reset by importing 'memory_graph.config_default'.
510
512
 
511
- - ***mg.config.max_tree_depth*** : int
512
- - The maxium depth of the graph. A `★` symbol indictes where the graph is cut short.
513
+ - ***mg.config.max_graph_depth*** : int
514
+ - The maxium depth of the graph with default value 12. A `✂` (scissor) symbol indicates where the graph is cut short. Dashed references indicate that there are more references to a node than are shown.
513
515
 
514
516
  - ***mg.config.max_string_length*** : int
515
517
  - The maximum length of strings shown in the graph. Longer strings will be truncated.
@@ -533,7 +535,7 @@ Different aspects of memory_graph can be configured. The default configuration i
533
535
  - Maps each type to a Slicer. A slicer determines how many elements of a data type are shown in the graph to prevent the graph from getting too big. 'Slicer()' does no slicing, 'Slicer(1,2,3)' shows just 1 element at the beginning, 2 in the middle, and 3 at the end.
534
536
 
535
537
  ### Temporary Configuration ###
536
- In addition to the global configuration, a temporary configuration can be set for a single `show()`, `render()`, `d()`, `ds()` call to change the colors, orientation, and slicer. This example highlights a particular list element in red, gives it a horizontal orientation, and overwrites the default slicer for lists:
538
+ In addition to the global configuration, a temporary configuration can be set for a single `show()` or `render()` call to change the colors, orientation, and slicer. This example highlights a particular list element in red, gives it a horizontal orientation, and overwrites the default slicer for lists:
537
539
 
538
540
  ```python
539
541
  import memory_graph as mg
@@ -554,7 +556,7 @@ mg.show( locals(),
554
556
  Different extensions are available for types from other Python packages.
555
557
 
556
558
  ### Numpy ###
557
- Numpy types `arrray` and `matrix` and `ndarray` can be graphed with "memory_graph.extension_numpy":
559
+ Numpy types `array` and `matrix` and `ndarray` can be graphed with "memory_graph.extension_numpy":
558
560
 
559
561
  ```python
560
562
  import memory_graph as mg
@@ -740,7 +742,7 @@ See for example [jupyter_example.ipynb](https://raw.githubusercontent.com/bterwi
740
742
  ## ipython ##
741
743
  In ipython `locals()` has additional variables that cause problems in the graph, use `mg.locals_ipython()` to get the local variables with these problematic variables filtered out. Use `mg.get_call_stack_ipython()` to get the whole call stack with these variables filtered out.
742
744
 
743
- Additionally install file [auto_memory_graph.py](https://raw.githubusercontent.com/bterwijn/memory_graph/main/sc/auto_memory_graph.py) in the ipython startup directory:
745
+ Additionally install file [auto_memory_graph.py](https://raw.githubusercontent.com/bterwijn/memory_graph/main/src/auto_memory_graph.py) in the ipython startup directory:
744
746
  * Linux/Mac: ~/.ipython/profile_default/startup/
745
747
  * Windows: %USERPROFILE%\.ipython\profile_default\startup\
746
748
 
@@ -748,7 +750,7 @@ Then after starting 'ipython' call function `mg_switch()` to turn on/off the aut
748
750
  ![ipyton.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/ipython.png)
749
751
 
750
752
  ## In the Browser ##
751
- We can run memory_graph in the browser: <a href="https://bterwijn.github.io/memory_graph/src/pyodide.html" target="_blank">Pyodide Example</a>
753
+ We can also run memory_graph in the browser: <a href="https://bterwijn.github.io/memory_graph/src/pyodide.html" target="_blank">Pyodide Example</a>
752
754
  ![pyodide.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/pyodide.png)
753
755
 
754
756
  ## Troubleshooting ##
@@ -21,6 +21,7 @@ images/copy_method.png
21
21
  images/copy_method.py
22
22
  images/create_gif.sh
23
23
  images/create_images.sh
24
+ images/debug_vscode.png
24
25
  images/debugging.gif
25
26
  images/debugging.py
26
27
  images/extension_numpy.png
@@ -69,6 +70,7 @@ memory_graph/slices.py
69
70
  memory_graph/slices_iterator.py
70
71
  memory_graph/slices_table_iterator.py
71
72
  memory_graph/test.py
73
+ memory_graph/test_max_graph_depth.py
72
74
  memory_graph/test_memory_graph.py
73
75
  memory_graph/test_memory_to_nodes.py
74
76
  memory_graph/test_sequence.py
@@ -11,7 +11,7 @@ long_description_from_readme = (this_directory / "README.md").read_text()
11
11
 
12
12
  setup(
13
13
  name = 'memory_graph',
14
- version = '0.3.10',
14
+ version = '0.3.12',
15
15
  description = 'Draws a graph of your data to analyze its structure.',
16
16
  long_description = long_description_from_readme,
17
17
  long_description_content_type = 'text/markdown',
@@ -8,9 +8,12 @@ def mg_visualization(execution_result):
8
8
  ipython_locals = get_ipython().user_ns
9
9
  mg.show(mg.ipython_locals_filter(ipython_locals))
10
10
 
11
- def mg_switch():
11
+ def mg_switch(status = None):
12
12
  global mg_visualization_status
13
- mg_visualization_status = not mg_visualization_status
13
+ if isinstance(status, bool):
14
+ mg_visualization_status = status
15
+ else:
16
+ mg_visualization_status = not mg_visualization_status
14
17
  if mg_visualization_status:
15
18
  get_ipython().events.register("post_run_cell", mg_visualization)
16
19
  else:
@@ -54,7 +54,9 @@
54
54
  </head>
55
55
  <body>
56
56
  <div class="container">
57
- <div class="part"><!-- ========== Top Left ========== --> <p>Log:</p>
57
+ <div class="part"><!-- ========== Top Left ========== -->
58
+ <p>See the <a href="https://pypi.org/project/memory-graph/" style="font-size: 1.5em;">memory_graph</a> python package.<br>
59
+ Log:</p>
58
60
  <textarea id="log"></textarea>
59
61
  </div>
60
62
 
@@ -67,7 +69,7 @@ def add_one(a, b, c):
67
69
  a += [1]
68
70
  b += (1,)
69
71
  c += [1]
70
- print("display the call stack")
72
+ print("display a graph of the call stack")
71
73
  js.display(mg.create_graph(mg.get_call_stack()))
72
74
 
73
75
  print("initialize test data")
@@ -76,9 +78,10 @@ b = (4, 3, 2)
76
78
  c = [4, 3, 2]
77
79
  print(f"a:{a} b:{b} c:{c}")
78
80
 
79
- print("call function add_one()")
81
+ print("call function: add_one(a, b, c.copy())")
80
82
  add_one(a, b, c.copy())
81
83
  print(f"a:{a} b:{b} c:{c}")
84
+ print("only 'a' has changed, the graph explains why")
82
85
  </textarea>
83
86
  <button id="run-button" disabled>Run</button>
84
87
  </div>
File without changes
File without changes
File without changes
File without changes
File without changes