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.
- {memory_graph-0.3.16/memory_graph.egg-info → memory_graph-0.3.18}/PKG-INFO +24 -32
- {memory_graph-0.3.16 → memory_graph-0.3.18}/README.md +23 -31
- memory_graph-0.3.18/images/add_one.png +0 -0
- memory_graph-0.3.18/images/bin_tree.png +0 -0
- memory_graph-0.3.18/images/bin_tree.py +38 -0
- memory_graph-0.3.18/images/bin_tree2.py +31 -0
- memory_graph-0.3.18/images/bin_tree2.py~ +31 -0
- memory_graph-0.3.18/images/copy_method.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/copy_method.py +3 -2
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/debugging01.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/debugging02.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/debugging03.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/debugging04.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/debugging05.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/debugging06.png +0 -0
- memory_graph-0.3.18/images/factorial.gif +0 -0
- memory_graph-0.3.18/images/factorial01.png +0 -0
- memory_graph-0.3.18/images/factorial02.png +0 -0
- memory_graph-0.3.18/images/factorial03.png +0 -0
- memory_graph-0.3.18/images/factorial04.png +0 -0
- memory_graph-0.3.18/images/factorial05.png +0 -0
- memory_graph-0.3.18/images/factorial06.png +0 -0
- memory_graph-0.3.18/images/factorial07.png +0 -0
- memory_graph-0.3.18/images/highlight.png +0 -0
- memory_graph-0.3.18/images/linked_list.png +0 -0
- memory_graph-0.3.18/images/many_types.png +0 -0
- memory_graph-0.3.18/images/memory_graph.pdf +0 -0
- memory_graph-0.3.18/images/power_set.gif +0 -0
- memory_graph-0.3.18/images/power_set1.png +0 -0
- memory_graph-0.3.18/images/power_set10.png +0 -0
- memory_graph-0.3.18/images/power_set11.png +0 -0
- memory_graph-0.3.18/images/power_set12.png +0 -0
- memory_graph-0.3.18/images/power_set13.png +0 -0
- memory_graph-0.3.18/images/power_set14.png +0 -0
- memory_graph-0.3.18/images/power_set15.png +0 -0
- memory_graph-0.3.18/images/power_set16.png +0 -0
- memory_graph-0.3.18/images/power_set17.png +0 -0
- memory_graph-0.3.18/images/power_set18.png +0 -0
- memory_graph-0.3.18/images/power_set19.png +0 -0
- memory_graph-0.3.18/images/power_set2.png +0 -0
- memory_graph-0.3.18/images/power_set20.png +0 -0
- memory_graph-0.3.18/images/power_set21.png +0 -0
- memory_graph-0.3.18/images/power_set22.png +0 -0
- memory_graph-0.3.18/images/power_set3.png +0 -0
- memory_graph-0.3.18/images/power_set4.png +0 -0
- memory_graph-0.3.18/images/power_set5.png +0 -0
- memory_graph-0.3.18/images/power_set6.png +0 -0
- memory_graph-0.3.18/images/power_set7.png +0 -0
- memory_graph-0.3.18/images/power_set8.png +0 -0
- memory_graph-0.3.18/images/power_set9.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/__init__.py +14 -3
- memory_graph-0.3.18/memory_graph/call_stack.py +9 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/config_default.py +7 -2
- {memory_graph-0.3.16 → memory_graph-0.3.18/memory_graph.egg-info}/PKG-INFO +24 -32
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph.egg-info/SOURCES.txt +4 -1
- {memory_graph-0.3.16 → memory_graph-0.3.18}/setup.py +1 -1
- memory_graph-0.3.16/images/add_one.png +0 -0
- memory_graph-0.3.16/images/bin_tree.png +0 -0
- memory_graph-0.3.16/images/bin_tree.py +0 -47
- memory_graph-0.3.16/images/copy_method.png +0 -0
- memory_graph-0.3.16/images/factorial.gif +0 -0
- memory_graph-0.3.16/images/factorial01.png +0 -0
- memory_graph-0.3.16/images/factorial02.png +0 -0
- memory_graph-0.3.16/images/factorial03.png +0 -0
- memory_graph-0.3.16/images/factorial04.png +0 -0
- memory_graph-0.3.16/images/factorial05.png +0 -0
- memory_graph-0.3.16/images/factorial06.png +0 -0
- memory_graph-0.3.16/images/factorial07.png +0 -0
- memory_graph-0.3.16/images/highlight.png +0 -0
- memory_graph-0.3.16/images/linked_list.png +0 -0
- memory_graph-0.3.16/images/many_types.png +0 -0
- memory_graph-0.3.16/images/memory_graph.gv +0 -20
- memory_graph-0.3.16/images/power_set.gif +0 -0
- memory_graph-0.3.16/images/power_set1.png +0 -0
- memory_graph-0.3.16/images/power_set10.png +0 -0
- memory_graph-0.3.16/images/power_set11.png +0 -0
- memory_graph-0.3.16/images/power_set12.png +0 -0
- memory_graph-0.3.16/images/power_set13.png +0 -0
- memory_graph-0.3.16/images/power_set14.png +0 -0
- memory_graph-0.3.16/images/power_set15.png +0 -0
- memory_graph-0.3.16/images/power_set16.png +0 -0
- memory_graph-0.3.16/images/power_set17.png +0 -0
- memory_graph-0.3.16/images/power_set18.png +0 -0
- memory_graph-0.3.16/images/power_set19.png +0 -0
- memory_graph-0.3.16/images/power_set2.png +0 -0
- memory_graph-0.3.16/images/power_set20.png +0 -0
- memory_graph-0.3.16/images/power_set21.png +0 -0
- memory_graph-0.3.16/images/power_set22.png +0 -0
- memory_graph-0.3.16/images/power_set3.png +0 -0
- memory_graph-0.3.16/images/power_set4.png +0 -0
- memory_graph-0.3.16/images/power_set5.png +0 -0
- memory_graph-0.3.16/images/power_set6.png +0 -0
- memory_graph-0.3.16/images/power_set7.png +0 -0
- memory_graph-0.3.16/images/power_set8.png +0 -0
- memory_graph-0.3.16/images/power_set9.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/LICENSE.txt +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/MANIFEST.in +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/TODO.txt +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/.ipynb_checkpoints/jupyter_example-checkpoint.ipynb +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/add_one.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/avltree.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/avltree.py~ +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/avltree_base.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/avltree_dir.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/avltree_fail.gv +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/avltree_fail.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/avltree_key_value.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/avltree_linear.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/avltree_table.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/copies.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/copies.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/create_gif.sh +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/create_images.sh +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/debug_vscode.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/debugging.gif +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/debugging.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/extension_numpy.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/extension_numpy.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/extension_pandas.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/extension_pandas.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/factorial.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/hash_set.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/hash_set.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/highlight.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/immutable.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/immutable1.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/immutable2.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/ipython.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/jupyter_example.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/linked_list.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/many_types.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/memory_graph.gv.pdf +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/mutable.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/mutable1.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/mutable2.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/my_graph.gv +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/my_graph.pdf +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/name_rebinding.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/not_node_types.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/not_node_types.py~ +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/not_node_types1.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/not_node_types2.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/power_set.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/pyodide.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/rebinding1.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/rebinding2.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/images/uva.png +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/install.txt +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/config.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/config_helpers.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/extension_numpy.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/extension_pandas.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/html_table.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/list_view.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/memory_to_nodes.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/node_base.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/node_key_value.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/node_linear.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/node_table.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/sequence.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/slicer.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/slices.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/slices_iterator.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/slices_table_iterator.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/test.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/test_max_graph_depth.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/test_memory_graph.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/test_memory_to_nodes.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/test_sequence.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/test_slicer.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/test_slices.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/test_slices_iterator.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph/utils.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph.egg-info/dependency_links.txt +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph.egg-info/requires.txt +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/memory_graph.egg-info/top_level.txt +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/setup.cfg +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/src/auto_memory_graph.py +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/src/jupyter_example.ipynb +0 -0
- {memory_graph-0.3.16 → memory_graph-0.3.18}/src/pyodide.html +0 -0
- {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.
|
|
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
|
|
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.
|
|
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
|
|
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.
|
|
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
|
|
462
|
-
if
|
|
463
|
-
|
|
464
|
-
|
|
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.
|
|
464
|
+
self.smaller.add(value)
|
|
467
465
|
else:
|
|
468
|
-
if
|
|
469
|
-
|
|
466
|
+
if self.larger is None:
|
|
467
|
+
self.larger = BinTree(value)
|
|
470
468
|
else:
|
|
471
|
-
self.
|
|
472
|
-
mg.block(mg.show,
|
|
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
|
-
|
|
484
|
-
tree.add(
|
|
475
|
+
value = random.randrange(n)
|
|
476
|
+
tree.add(value)
|
|
485
477
|
```
|
|
486
478
|

|
|
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
|
|
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 ([
|
|
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
|
|
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.
|
|
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
|
|
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.
|
|
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
|
|
443
|
-
if
|
|
444
|
-
|
|
445
|
-
|
|
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.
|
|
445
|
+
self.smaller.add(value)
|
|
448
446
|
else:
|
|
449
|
-
if
|
|
450
|
-
|
|
447
|
+
if self.larger is None:
|
|
448
|
+
self.larger = BinTree(value)
|
|
451
449
|
else:
|
|
452
|
-
self.
|
|
453
|
-
mg.block(mg.show,
|
|
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
|
-
|
|
465
|
-
tree.add(
|
|
456
|
+
value = random.randrange(n)
|
|
457
|
+
tree.add(value)
|
|
466
458
|
```
|
|
467
459
|

|
|
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
|
|
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 ([
|
|
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)
|
|
Binary file
|
|
@@ -11,12 +11,13 @@ class My_Class:
|
|
|
11
11
|
self.digits = [1, 2]
|
|
12
12
|
self.letters = ['x', 'y']
|
|
13
13
|
|
|
14
|
-
def
|
|
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.
|
|
21
|
+
b = a.custom_copy()
|
|
21
22
|
|
|
22
23
|
mg.render(locals(), 'copy_method.png')
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
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.
|
|
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
|
|
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
|
-
|
|
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 : "
|
|
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.
|
|
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
|
|
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.
|
|
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
|
|
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.
|
|
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
|
|
462
|
-
if
|
|
463
|
-
|
|
464
|
-
|
|
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.
|
|
464
|
+
self.smaller.add(value)
|
|
467
465
|
else:
|
|
468
|
-
if
|
|
469
|
-
|
|
466
|
+
if self.larger is None:
|
|
467
|
+
self.larger = BinTree(value)
|
|
470
468
|
else:
|
|
471
|
-
self.
|
|
472
|
-
mg.block(mg.show,
|
|
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
|
-
|
|
484
|
-
tree.add(
|
|
475
|
+
value = random.randrange(n)
|
|
476
|
+
tree.add(value)
|
|
485
477
|
```
|
|
486
478
|

|
|
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
|
|
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 ([
|
|
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
|
|