memory-graph 0.3.77__tar.gz → 0.3.79__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 (41) hide show
  1. {memory_graph-0.3.77 → memory_graph-0.3.79}/PKG-INFO +85 -22
  2. {memory_graph-0.3.77 → memory_graph-0.3.79}/README.md +84 -21
  3. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/__init__.py +2 -1
  4. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/config.py +5 -0
  5. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/config_default.py +92 -29
  6. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/html_table.py +10 -8
  7. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/memory_to_nodes.py +5 -5
  8. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/utils.py +5 -1
  9. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph.egg-info/PKG-INFO +85 -22
  10. {memory_graph-0.3.77 → memory_graph-0.3.79}/pyproject.toml +1 -1
  11. {memory_graph-0.3.77 → memory_graph-0.3.79}/LICENSE.txt +0 -0
  12. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/call_stack.py +0 -0
  13. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/config_helpers.py +0 -0
  14. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/extension_numpy.py +0 -0
  15. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/extension_pandas.py +0 -0
  16. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/extension_torch.py +0 -0
  17. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/list_view.py +0 -0
  18. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/node_base.py +0 -0
  19. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/node_key_value.py +0 -0
  20. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/node_leaf.py +0 -0
  21. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/node_linear.py +0 -0
  22. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/node_table.py +0 -0
  23. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/sequence.py +0 -0
  24. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/slicer.py +0 -0
  25. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/slices.py +0 -0
  26. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/slices_iterator.py +0 -0
  27. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/slices_table_iterator.py +0 -0
  28. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/test.py +0 -0
  29. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/test_max_graph_depth.py +0 -0
  30. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/test_memory_graph.py +0 -0
  31. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/test_memory_to_nodes.py +0 -0
  32. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/test_sequence.py +0 -0
  33. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/test_slicer.py +0 -0
  34. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/test_slices.py +0 -0
  35. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph/test_slices_iterator.py +0 -0
  36. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph.egg-info/SOURCES.txt +0 -0
  37. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph.egg-info/dependency_links.txt +0 -0
  38. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph.egg-info/requires.txt +0 -0
  39. {memory_graph-0.3.77 → memory_graph-0.3.79}/memory_graph.egg-info/top_level.txt +0 -0
  40. {memory_graph-0.3.77 → memory_graph-0.3.79}/setup.cfg +0 -0
  41. {memory_graph-0.3.77 → memory_graph-0.3.79}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: memory_graph
3
- Version: 0.3.77
3
+ Version: 0.3.79
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-Expression: BSD-2-Clause
@@ -27,7 +27,7 @@ Additionally [Graphviz](https://graphviz.org/download/) needs to be installed.
27
27
 
28
28
  # Highlights #
29
29
  ![vscode_copying.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/vscode_copying.gif)
30
- 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!
30
+ Run a live demo in the 👉 [**Memory Graph Web Debugger**](https://memory-graph.com/#breakpoints=8&continues=1&play) 👈 now, no installation required!
31
31
 
32
32
  - learn the right **mental model** to think about Python data (references, mutability, shallow vs deep copy)
33
33
  - **visualize the structure of your data** to more easily understand and debug any data structure
@@ -35,7 +35,7 @@ Run a live demo in the 👉 [**Memory Graph Web Debugger**](https://memory-graph
35
35
 
36
36
  An example Binary Tree data structure:
37
37
  ![bin_tree_vs.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/bin_tree_vs.gif)
38
- 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).
38
+ Or see it in the [Memory Graph 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).
39
39
 
40
40
  # Videos #
41
41
  | [![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) |
@@ -102,7 +102,7 @@ a graph showing `a` and `b` share the list
102
102
 
103
103
  </td></tr></table>
104
104
 
105
- The fact that `a` and `b` share the list can not be verified by printing the lists. It can be verified by comparing the identity of both variables using the `id()` function or by using the `is` comparison operator as shown in the program output below, but this quickly becomes impractical for larger programs.
105
+ The fact that `a` and `b` share the list can **not** be verified by printing the lists. It can be verified by comparing the identity of both variables using the `id()` function or by using the `is` comparison operator as shown in the program output below, but this quickly becomes impractical for larger programs.
106
106
  ```{verbatim}
107
107
  a: 4, 3, 2, 1
108
108
  b: 4, 3, 2, 1
@@ -163,7 +163,7 @@ Bas Terwijn
163
163
  ## Inspiration ##
164
164
  Inspired by [Python Tutor](https://pythontutor.com/).
165
165
 
166
- The main differences are that by running memory_graph locally we support Python Tutor’s [unsupported features](https://github.com/pythontutor-dev/pythontutor/blob/master/unsupported-features.md#unsupported-features) so that it scales to full programs in many environments and IDEs instead of just code snippets in a webbrowser, and by mirroring the data’s hierarchy we improve graph readability for larger graphs.
166
+ The main differences are that by running memory_graph locally we support Python Tutor’s [unsupported features](https://github.com/pythontutor-dev/pythontutor/blob/master/unsupported-features.md#unsupported-features) so that it scales to full multi-file programs in many environments and IDEs instead of just code snippets in a webbrowser, and by mirroring the data’s hierarchy we improve graph readability for larger graphs.
167
167
 
168
168
  ## Social Media #
169
169
  * [LinkedIn](https://www.linkedin.com/groups/13244150/)
@@ -242,7 +242,7 @@ mg.show(locals())
242
242
 
243
243
  ![copy_mutbale.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/copy_mutable.png)
244
244
 
245
- 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/copies.py&play).
245
+ Or see it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/copies.py&play).
246
246
 
247
247
  ## Custom Copy ##
248
248
  We can write our own custom copy function or method in case the three standard "copy" options don't do what we want. For example, in the code below the `custom_copy()` method of My_Class copies the `digits` but shares the `letters` between two objects.
@@ -270,12 +270,16 @@ mg.show(locals())
270
270
  ```
271
271
  ![copy_method.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/copy_method.png)
272
272
 
273
- 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).
273
+ Or see it in the [Memory Graph 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).
274
274
 
275
275
  ## Name Rebinding ##
276
276
  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 affecting any other variable.
277
277
 
278
- Also note the difference between statement `b += [1]` that changes `b` and `a`, and statement `c = c + [300]` that first creates the new value `c + [300]` and assigns this value to `c` without effecting `b`. This shows that `x += y` is not the same as `x = x + y` for values of mutable type.
278
+ In the example below, also note the difference between expressions:
279
+ - `b += [300]`: that changes both `b` and `a`
280
+ - `c = c + [600]`: that first creates a new value `c + [600]` and then assigns this new value to `c` without affecting `b`
281
+
282
+ This shows that `x += y` is not the same as `x = x + y` for a value `x` of mutable type.
279
283
 
280
284
  ```python
281
285
  import memory_graph as mg
@@ -296,7 +300,7 @@ mg.render(locals(), 'rebinding3.png')
296
300
  |:--------------:|:--------------:|:--------------:|
297
301
  | rebinding1.png | rebinding2.png | rebinding3.png |
298
302
 
299
- 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/rebind.py&play).
303
+ Or see it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/rebind.py&play).
300
304
 
301
305
  ## Copying Values of Immutable Type ##
302
306
  Because a value of immutable type will be copied automatically when it is changed, there is no need to copy it beforehand. Therefore, a shallow or deep copy of a value of immutable type will result in just an assignment to save on the time needed to make the copy and the space (=memory) needed to store the values.
@@ -354,7 +358,7 @@ print(f"a:{a} b:{b} c:{c}")
354
358
  ```
355
359
  ![add_one.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/add_one.png)
356
360
 
357
- 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).
361
+ Or see it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/function_call.py&play).
358
362
 
359
363
  In the printed output we see that only `a` is changed as a result of the function call:
360
364
  ```
@@ -383,7 +387,7 @@ print(f"a:{a} b:{b[0]}")
383
387
  ```
384
388
  a:10 b:11
385
389
  ```
386
- 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/wrap.py&breakpoints=5&continues=1&play)
390
+ Or see it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/wrap.py&breakpoints=5&continues=1&play)
387
391
 
388
392
  The effect of calling `add_one()` is that `b[0]` increases by 1, while `a` is unaffected.
389
393
 
@@ -424,7 +428,7 @@ print( factorial(4) )
424
428
 
425
429
  and the result is: 1 x 2 x 3 x 4 = 24
426
430
 
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/factorial.py&timestep=1.0&play).
431
+ Or see it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/factorial.py&timestep=1.0&play).
428
432
 
429
433
  ## Binary Conversion ##
430
434
  A more interesting recursive example is function `binary()` that converts a integer from decimal to binary representation.
@@ -448,7 +452,7 @@ print( binary(100) )
448
452
  [1, 1, 0, 0, 1, 0, 0]
449
453
  ```
450
454
 
451
- 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).
455
+ Or see it in the [Memory Graph 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).
452
456
 
453
457
  ## Power Set ##
454
458
  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.
@@ -480,7 +484,7 @@ print( power_set(['a', 'b', 'c']) )
480
484
  [['a', 'b', 'c'], ['a', 'b'], ['a', 'c'], ['a'], ['b', 'c'], ['b'], ['c'], []]
481
485
  ```
482
486
 
483
- 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).
487
+ Or see it in the [Memory Graph 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).
484
488
 
485
489
  ## Invocation Tree ##
486
490
  The memory_graph package visualizes data at the currect time, but to better understand recursion it can also be helpful to visualize different function calls over time. This is what the [invocation_tree](https://github.com/bterwijn/invocation_tree?tab=readme-ov-file#installation) package does.
@@ -644,7 +648,7 @@ for i in range(n):
644
648
  Here we show values being added to a Linked List in Cursor AI. When adding the last value '5' we "Step Into" the code to show more of the details.
645
649
  ![linked_list.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/linked_list.gif)
646
650
 
647
- 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/linked_list.py&timestep=0.2&play).
651
+ Or see it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/linked_list.py&timestep=0.2&play).
648
652
 
649
653
  ## Binary Tree ##
650
654
  ```python
@@ -686,7 +690,7 @@ for i in range(n):
686
690
  Here we show values being inserted in a Binary Tree in Visual Studio Code. When inserting the last value '29' we "Step Into" the code to show the recursive implementation.
687
691
  ![images/bin_tree.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/bin_tree.gif)
688
692
 
689
- 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) or see the more advanced [Multiway Tree](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/multiway_tree.py&breakpoints=19,33&continues=1&timestep=0.2&play) with more than two children per node, making the tree less deep and more efficient.
693
+ See it in the [Memory Graph 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) or see the more advanced [Multiway Tree](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/multiway_tree.py&breakpoints=19,33&continues=1&timestep=0.2&play) with more than two children per node, making the tree less deep and more efficient.
690
694
 
691
695
  ## Hash Set ##
692
696
  ```python
@@ -730,7 +734,7 @@ for i in range(n):
730
734
  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.
731
735
  ![images/hash_set.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/hash_set.gif)
732
736
 
733
- 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).
737
+ Or see it in the [Memory Graph 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).
734
738
 
735
739
 
736
740
  # Sorting Algorithms #
@@ -757,7 +761,7 @@ In this configuration example we show the decimal, binary and [two's complement
757
761
 
758
762
  A sliding puzzle solver as a challenging example showing how memory_graph deals with large amounts of data. Click "Continue" to step through the breadth-first search generations until a solution path is found:
759
763
 
760
- - [sliding puzzle solver](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/sliding_puzzle.py&breakpoints=16,26,28,39&continues=1)
764
+ - [sliding puzzle solver](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/sliding_puzzle.py&breakpoints=16,26,28,39,136&continues=1)
761
765
 
762
766
  ![sliding_puzzle.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/sliding_puzzle.png)
763
767
 
@@ -1245,13 +1249,72 @@ Arguably the visualization is then more clear when we show a List_View object as
1245
1249
 
1246
1250
  ```python
1247
1251
  mg.config.type_to_node[List_View] = (lambda l: mg.Node_Linear(l,
1248
- [v if l.begin <= i < l.end else mg.unquoted('') for i, v in enumerate(l.lst)]
1252
+ [v if l.begin <= i < l.end else mg.unquoted_str('') for i, v in enumerate(l.lst)]
1249
1253
  if hasattr(l, 'end') else [])
1250
1254
  )
1251
1255
  ```
1252
1256
  ![bin_search_linear.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/bin_search_linear.png)
1253
1257
 
1254
- 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_search.py&breakpoints=32&continues=1&timestep=0.5&play)
1258
+ Or see it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/bin_search.py&breakpoints=38&continues=1&timestep=0.5&play)
1259
+
1260
+ ## String Types ##
1261
+
1262
+ For special string formatting different `str` types are available:
1263
+
1264
+ | string type | format |
1265
+ |:--------------------------:|:--------------------:|
1266
+ | `str` | normal Python `str` type is limited by `config.max_string_length` |
1267
+ | `mg.full_str('text')` | not limited |
1268
+ | `mg.unquoted_str('text')` | not limited and not quoted |
1269
+ | `mg.html_str('text')` | for [Grahviz html-like formatting](https://graphviz.org/doc/info/shapes.html#html) |
1270
+
1271
+ The [Grahviz html-like formatting](https://graphviz.org/doc/info/shapes.html#html) supports a subset of html tags that allow for things like:
1272
+ ```python
1273
+ import memory_graph as mg
1274
+
1275
+ elements = ['<B>bold</B>',
1276
+ '<I>italic</I>',
1277
+ '<S>strikethrough</S>',
1278
+ '<U>under</U><O>over</O>',
1279
+ '<SUB>sub</SUB><SUP>sup</SUP>',
1280
+ '<FONT FACE="Courier">monospaced</FONT>',
1281
+ '<FONT COLOR="red">red</FONT><FONT COLOR="green">green</FONT>',
1282
+ '<FONT POINT-SIZE="20">Large</FONT><FONT POINT-SIZE="10">small</FONT>',
1283
+ '<TABLE BORDER="1"><TR><TD>c1</TD><TD>c2</TD></TR></TABLE>',
1284
+ 'line1<BR/>line2<BR/>line3<BR/>']
1285
+
1286
+ normal_str = '<TABLE BORDER="0">\n'
1287
+ for element in elements:
1288
+ normal_str += '<TR><TD> ' + mg.utils.html_escape(element) + ' </TD><TD> ' + element+ ' </TD></TR>element\n'
1289
+ normal_str += '</TABLE>\n'
1290
+
1291
+ html_example = mg.html_str(normal_str)
1292
+ del elements, element, normal_str
1293
+ mg.show(locals())
1294
+ ```
1295
+ ![html_str_example.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/html_str_example.png)
1296
+
1297
+ Including the `<IMG>` tag that allows for showing local image files only, but that currently doesn't work in the Memory Graph Web Debugger, that uses 'Viz.js' for graph rendering, unfortunately.
1298
+
1299
+ ```python
1300
+ import memory_graph as mg
1301
+ import matplotlib.pyplot as plt
1302
+ import random
1303
+ random.seed(0)
1304
+
1305
+ N = 100
1306
+ value = 0
1307
+ data = [value]
1308
+ for i in range(N):
1309
+ value += random.uniform(-1, 1)
1310
+ data.append(value)
1311
+
1312
+ plt.plot(data)
1313
+ plt.savefig('plot.png')
1314
+ image = {mg.html_str('<IMG SRC="plot.png"/>')}
1315
+ mg.show(locals())
1316
+ ```
1317
+ ![html_str_image.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/html_str_image.png)
1255
1318
 
1256
1319
  ## Collapse Type ##
1257
1320
 
@@ -1384,7 +1447,7 @@ mg.show(locals())
1384
1447
  ```
1385
1448
  ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/extension_numpy.png)
1386
1449
 
1387
- 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).
1450
+ Or see it in the [Memory Graph Web Debugger](https://memory-graph.com/#micropip=numpy&codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/mg_numpy.py&play).
1388
1451
 
1389
1452
  ## Pandas ##
1390
1453
  For pandas types `Series` and `DataFrame`, use `mg.extend_pandas()`:
@@ -1405,7 +1468,7 @@ mg.show(locals())
1405
1468
  ```
1406
1469
  ![extension_pandas.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/extension_pandas.png)
1407
1470
 
1408
- 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).
1471
+ Or see it in the [Memory Graph Web Debugger](https://memory-graph.com/#micropip=pandas&codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/mg_pandas.py&play).
1409
1472
 
1410
1473
  ## PyTorch ##
1411
1474
  For torch type `tensor`, use `mg.extend_torch()`:
@@ -7,7 +7,7 @@ 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/#breakpoints=8&continues=1&timestep=1.0&play) 👈 now, no installation required!
10
+ Run a live demo in the 👉 [**Memory Graph Web Debugger**](https://memory-graph.com/#breakpoints=8&continues=1&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 more easily understand and debug any data structure
@@ -15,7 +15,7 @@ Run a live demo in the 👉 [**Memory Graph Web Debugger**](https://memory-graph
15
15
 
16
16
  An example Binary Tree data structure:
17
17
  ![bin_tree_vs.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/bin_tree_vs.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).
18
+ Or see it in the [Memory Graph 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
19
 
20
20
  # Videos #
21
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) |
@@ -82,7 +82,7 @@ a graph showing `a` and `b` share the list
82
82
 
83
83
  </td></tr></table>
84
84
 
85
- The fact that `a` and `b` share the list can not be verified by printing the lists. It can be verified by comparing the identity of both variables using the `id()` function or by using the `is` comparison operator as shown in the program output below, but this quickly becomes impractical for larger programs.
85
+ The fact that `a` and `b` share the list can **not** be verified by printing the lists. It can be verified by comparing the identity of both variables using the `id()` function or by using the `is` comparison operator as shown in the program output below, but this quickly becomes impractical for larger programs.
86
86
  ```{verbatim}
87
87
  a: 4, 3, 2, 1
88
88
  b: 4, 3, 2, 1
@@ -143,7 +143,7 @@ Bas Terwijn
143
143
  ## Inspiration ##
144
144
  Inspired by [Python Tutor](https://pythontutor.com/).
145
145
 
146
- The main differences are that by running memory_graph locally we support Python Tutor’s [unsupported features](https://github.com/pythontutor-dev/pythontutor/blob/master/unsupported-features.md#unsupported-features) so that it scales to full programs in many environments and IDEs instead of just code snippets in a webbrowser, and by mirroring the data’s hierarchy we improve graph readability for larger graphs.
146
+ The main differences are that by running memory_graph locally we support Python Tutor’s [unsupported features](https://github.com/pythontutor-dev/pythontutor/blob/master/unsupported-features.md#unsupported-features) so that it scales to full multi-file programs in many environments and IDEs instead of just code snippets in a webbrowser, and by mirroring the data’s hierarchy we improve graph readability for larger graphs.
147
147
 
148
148
  ## Social Media #
149
149
  * [LinkedIn](https://www.linkedin.com/groups/13244150/)
@@ -222,7 +222,7 @@ mg.show(locals())
222
222
 
223
223
  ![copy_mutbale.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/copy_mutable.png)
224
224
 
225
- 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/copies.py&play).
225
+ Or see it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/copies.py&play).
226
226
 
227
227
  ## Custom Copy ##
228
228
  We can write our own custom copy function or method in case the three standard "copy" options don't do what we want. For example, in the code below the `custom_copy()` method of My_Class copies the `digits` but shares the `letters` between two objects.
@@ -250,12 +250,16 @@ mg.show(locals())
250
250
  ```
251
251
  ![copy_method.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/copy_method.png)
252
252
 
253
- 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).
253
+ Or see it in the [Memory Graph 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).
254
254
 
255
255
  ## Name Rebinding ##
256
256
  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 affecting any other variable.
257
257
 
258
- Also note the difference between statement `b += [1]` that changes `b` and `a`, and statement `c = c + [300]` that first creates the new value `c + [300]` and assigns this value to `c` without effecting `b`. This shows that `x += y` is not the same as `x = x + y` for values of mutable type.
258
+ In the example below, also note the difference between expressions:
259
+ - `b += [300]`: that changes both `b` and `a`
260
+ - `c = c + [600]`: that first creates a new value `c + [600]` and then assigns this new value to `c` without affecting `b`
261
+
262
+ This shows that `x += y` is not the same as `x = x + y` for a value `x` of mutable type.
259
263
 
260
264
  ```python
261
265
  import memory_graph as mg
@@ -276,7 +280,7 @@ mg.render(locals(), 'rebinding3.png')
276
280
  |:--------------:|:--------------:|:--------------:|
277
281
  | rebinding1.png | rebinding2.png | rebinding3.png |
278
282
 
279
- 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/rebind.py&play).
283
+ Or see it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/rebind.py&play).
280
284
 
281
285
  ## Copying Values of Immutable Type ##
282
286
  Because a value of immutable type will be copied automatically when it is changed, there is no need to copy it beforehand. Therefore, a shallow or deep copy of a value of immutable type will result in just an assignment to save on the time needed to make the copy and the space (=memory) needed to store the values.
@@ -334,7 +338,7 @@ print(f"a:{a} b:{b} c:{c}")
334
338
  ```
335
339
  ![add_one.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/add_one.png)
336
340
 
337
- 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).
341
+ Or see it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/function_call.py&play).
338
342
 
339
343
  In the printed output we see that only `a` is changed as a result of the function call:
340
344
  ```
@@ -363,7 +367,7 @@ print(f"a:{a} b:{b[0]}")
363
367
  ```
364
368
  a:10 b:11
365
369
  ```
366
- 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/wrap.py&breakpoints=5&continues=1&play)
370
+ Or see it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/wrap.py&breakpoints=5&continues=1&play)
367
371
 
368
372
  The effect of calling `add_one()` is that `b[0]` increases by 1, while `a` is unaffected.
369
373
 
@@ -404,7 +408,7 @@ print( factorial(4) )
404
408
 
405
409
  and the result is: 1 x 2 x 3 x 4 = 24
406
410
 
407
- 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).
411
+ Or see it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/factorial.py&timestep=1.0&play).
408
412
 
409
413
  ## Binary Conversion ##
410
414
  A more interesting recursive example is function `binary()` that converts a integer from decimal to binary representation.
@@ -428,7 +432,7 @@ print( binary(100) )
428
432
  [1, 1, 0, 0, 1, 0, 0]
429
433
  ```
430
434
 
431
- 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).
435
+ Or see it in the [Memory Graph 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).
432
436
 
433
437
  ## Power Set ##
434
438
  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.
@@ -460,7 +464,7 @@ print( power_set(['a', 'b', 'c']) )
460
464
  [['a', 'b', 'c'], ['a', 'b'], ['a', 'c'], ['a'], ['b', 'c'], ['b'], ['c'], []]
461
465
  ```
462
466
 
463
- 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).
467
+ Or see it in the [Memory Graph 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).
464
468
 
465
469
  ## Invocation Tree ##
466
470
  The memory_graph package visualizes data at the currect time, but to better understand recursion it can also be helpful to visualize different function calls over time. This is what the [invocation_tree](https://github.com/bterwijn/invocation_tree?tab=readme-ov-file#installation) package does.
@@ -624,7 +628,7 @@ for i in range(n):
624
628
  Here we show values being added to a Linked List in Cursor AI. When adding the last value '5' we "Step Into" the code to show more of the details.
625
629
  ![linked_list.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/linked_list.gif)
626
630
 
627
- 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/linked_list.py&timestep=0.2&play).
631
+ Or see it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/linked_list.py&timestep=0.2&play).
628
632
 
629
633
  ## Binary Tree ##
630
634
  ```python
@@ -666,7 +670,7 @@ for i in range(n):
666
670
  Here we show values being inserted in a Binary Tree in Visual Studio Code. When inserting the last value '29' we "Step Into" the code to show the recursive implementation.
667
671
  ![images/bin_tree.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/bin_tree.gif)
668
672
 
669
- 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) or see the more advanced [Multiway Tree](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/multiway_tree.py&breakpoints=19,33&continues=1&timestep=0.2&play) with more than two children per node, making the tree less deep and more efficient.
673
+ See it in the [Memory Graph 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) or see the more advanced [Multiway Tree](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/multiway_tree.py&breakpoints=19,33&continues=1&timestep=0.2&play) with more than two children per node, making the tree less deep and more efficient.
670
674
 
671
675
  ## Hash Set ##
672
676
  ```python
@@ -710,7 +714,7 @@ for i in range(n):
710
714
  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.
711
715
  ![images/hash_set.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/hash_set.gif)
712
716
 
713
- 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).
717
+ Or see it in the [Memory Graph 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).
714
718
 
715
719
 
716
720
  # Sorting Algorithms #
@@ -737,7 +741,7 @@ In this configuration example we show the decimal, binary and [two's complement
737
741
 
738
742
  A sliding puzzle solver as a challenging example showing how memory_graph deals with large amounts of data. Click "Continue" to step through the breadth-first search generations until a solution path is found:
739
743
 
740
- - [sliding puzzle solver](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/sliding_puzzle.py&breakpoints=16,26,28,39&continues=1)
744
+ - [sliding puzzle solver](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/sliding_puzzle.py&breakpoints=16,26,28,39,136&continues=1)
741
745
 
742
746
  ![sliding_puzzle.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/sliding_puzzle.png)
743
747
 
@@ -1225,13 +1229,72 @@ Arguably the visualization is then more clear when we show a List_View object as
1225
1229
 
1226
1230
  ```python
1227
1231
  mg.config.type_to_node[List_View] = (lambda l: mg.Node_Linear(l,
1228
- [v if l.begin <= i < l.end else mg.unquoted('') for i, v in enumerate(l.lst)]
1232
+ [v if l.begin <= i < l.end else mg.unquoted_str('') for i, v in enumerate(l.lst)]
1229
1233
  if hasattr(l, 'end') else [])
1230
1234
  )
1231
1235
  ```
1232
1236
  ![bin_search_linear.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/bin_search_linear.png)
1233
1237
 
1234
- 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_search.py&breakpoints=32&continues=1&timestep=0.5&play)
1238
+ Or see it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/bin_search.py&breakpoints=38&continues=1&timestep=0.5&play)
1239
+
1240
+ ## String Types ##
1241
+
1242
+ For special string formatting different `str` types are available:
1243
+
1244
+ | string type | format |
1245
+ |:--------------------------:|:--------------------:|
1246
+ | `str` | normal Python `str` type is limited by `config.max_string_length` |
1247
+ | `mg.full_str('text')` | not limited |
1248
+ | `mg.unquoted_str('text')` | not limited and not quoted |
1249
+ | `mg.html_str('text')` | for [Grahviz html-like formatting](https://graphviz.org/doc/info/shapes.html#html) |
1250
+
1251
+ The [Grahviz html-like formatting](https://graphviz.org/doc/info/shapes.html#html) supports a subset of html tags that allow for things like:
1252
+ ```python
1253
+ import memory_graph as mg
1254
+
1255
+ elements = ['<B>bold</B>',
1256
+ '<I>italic</I>',
1257
+ '<S>strikethrough</S>',
1258
+ '<U>under</U><O>over</O>',
1259
+ '<SUB>sub</SUB><SUP>sup</SUP>',
1260
+ '<FONT FACE="Courier">monospaced</FONT>',
1261
+ '<FONT COLOR="red">red</FONT><FONT COLOR="green">green</FONT>',
1262
+ '<FONT POINT-SIZE="20">Large</FONT><FONT POINT-SIZE="10">small</FONT>',
1263
+ '<TABLE BORDER="1"><TR><TD>c1</TD><TD>c2</TD></TR></TABLE>',
1264
+ 'line1<BR/>line2<BR/>line3<BR/>']
1265
+
1266
+ normal_str = '<TABLE BORDER="0">\n'
1267
+ for element in elements:
1268
+ normal_str += '<TR><TD> ' + mg.utils.html_escape(element) + ' </TD><TD> ' + element+ ' </TD></TR>element\n'
1269
+ normal_str += '</TABLE>\n'
1270
+
1271
+ html_example = mg.html_str(normal_str)
1272
+ del elements, element, normal_str
1273
+ mg.show(locals())
1274
+ ```
1275
+ ![html_str_example.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/html_str_example.png)
1276
+
1277
+ Including the `<IMG>` tag that allows for showing local image files only, but that currently doesn't work in the Memory Graph Web Debugger, that uses 'Viz.js' for graph rendering, unfortunately.
1278
+
1279
+ ```python
1280
+ import memory_graph as mg
1281
+ import matplotlib.pyplot as plt
1282
+ import random
1283
+ random.seed(0)
1284
+
1285
+ N = 100
1286
+ value = 0
1287
+ data = [value]
1288
+ for i in range(N):
1289
+ value += random.uniform(-1, 1)
1290
+ data.append(value)
1291
+
1292
+ plt.plot(data)
1293
+ plt.savefig('plot.png')
1294
+ image = {mg.html_str('<IMG SRC="plot.png"/>')}
1295
+ mg.show(locals())
1296
+ ```
1297
+ ![html_str_image.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/html_str_image.png)
1235
1298
 
1236
1299
  ## Collapse Type ##
1237
1300
 
@@ -1364,7 +1427,7 @@ mg.show(locals())
1364
1427
  ```
1365
1428
  ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/extension_numpy.png)
1366
1429
 
1367
- 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).
1430
+ Or see it in the [Memory Graph Web Debugger](https://memory-graph.com/#micropip=numpy&codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/mg_numpy.py&play).
1368
1431
 
1369
1432
  ## Pandas ##
1370
1433
  For pandas types `Series` and `DataFrame`, use `mg.extend_pandas()`:
@@ -1385,7 +1448,7 @@ mg.show(locals())
1385
1448
  ```
1386
1449
  ![extension_pandas.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/extension_pandas.png)
1387
1450
 
1388
- 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).
1451
+ Or see it in the [Memory Graph Web Debugger](https://memory-graph.com/#micropip=pandas&codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/mg_pandas.py&play).
1389
1452
 
1390
1453
  ## PyTorch ##
1391
1454
  For torch type `tensor`, use `mg.extend_torch()`:
@@ -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.77"
5
+ __version__ = "0.3.79"
6
6
  __author__ = 'Bas Terwijn'
7
7
 
8
8
  import memory_graph.memory_to_nodes as memory_to_nodes
@@ -26,6 +26,7 @@ if not hasattr(builtins, "mg"):
26
26
  builtins.mg = mg
27
27
 
28
28
  # re-exports for shorter names
29
+ from .config_default import dark_mode, transparent_background
29
30
  from .slicer import Slicer
30
31
  from .node_leaf import Node_Leaf
31
32
  from .node_linear import Node_Linear
@@ -29,6 +29,11 @@ type_to_string = { }
29
29
 
30
30
  type_to_node = { }
31
31
 
32
+ color_mode_dark = False
33
+ transparent_background = False
34
+ foreground_color = None
35
+ index_color = None
36
+ background_color = None
32
37
  type_to_color = { }
33
38
 
34
39
  type_to_horizontal = { }
@@ -17,8 +17,98 @@ import memory_graph.utils as utils
17
17
 
18
18
  import types
19
19
 
20
+ """ Colors of the graph. """
21
+ foreground_color_light = 'black'
22
+ index_color_light = '#505050'
23
+ background_color_light = 'white'
24
+ """ Colors of different types in the graph. """
25
+ type_to_color_light = {
26
+ # ================= singular
27
+ type(None) : "gray",
28
+ bool : "pink",
29
+ int : "darkolivegreen1",
30
+ float : "plum",
31
+ complex : "yellow",
32
+ str : "cyan",
33
+ # ================= linear
34
+ tuple : "orange",
35
+ list : "lightcoral",
36
+ set : "orchid1",
37
+ frozenset : "orchid2",
38
+ bytes : "khaki1",
39
+ bytearray : "khaki2",
40
+ # ================= key_value
41
+ Node_Key_Value : "seagreen1", # for classes
42
+ call_stack : 'khaki',
43
+ type: "seagreen3", # where class variables are stored
44
+ dict : "#60a5ff",
45
+ types.MappingProxyType : "dodgerblue2", # not used
46
+ range : "cornsilk2",
47
+ # ================= exception
48
+ BaseException : "#ff6666",
49
+ }
50
+
51
+ background_color_dark = "#1d1d1d"
52
+ foreground_color_dark = "#cccccc"
53
+ index_color_dark = "#999999"
54
+ type_to_color_dark = {
55
+ # ================= singular
56
+ type(None) : "#646464",
57
+ bool : "#8d646d",
58
+ int : "#507835",
59
+ float : "#7e4974",
60
+ complex : "#707500",
61
+ str : "#006f6f",
62
+ # ================= linear
63
+ tuple : "#956200",
64
+ list : "#783438",
65
+ set : "#811b7d",
66
+ frozenset : "#6a1666",
67
+ bytes : "#73753f",
68
+ bytearray : "#6a6c3b",
69
+ # ================= key_value
70
+ Node_Key_Value : "#00905d",
71
+ call_stack : '#7e8148',
72
+ type: "#00784e",
73
+ dict : "#355393",
74
+ types.MappingProxyType : "#304a84",
75
+ range : "#7e7d6c",
76
+ # ================= exception
77
+ BaseException : "#a52e37",
78
+ }
79
+
80
+ def set_colors(dark, transparent):
81
+ if dark:
82
+ config.foreground_color = foreground_color_dark
83
+ config.index_color = index_color_dark
84
+ config.background_color = background_color_dark
85
+ config.type_to_color = type_to_color_dark
86
+ else:
87
+ config.foreground_color = foreground_color_light
88
+ config.index_color = index_color_light
89
+ config.background_color = background_color_light
90
+ config.type_to_color = type_to_color_light
91
+ if transparent:
92
+ config.background_color = "transparent"
93
+
94
+ def transparent_background(transparent = None):
95
+ if transparent is None:
96
+ config.transparent_background = not config.transparent_background
97
+ else:
98
+ config.transparent_background = transparent
99
+ set_colors(config.color_mode_dark, config.transparent_background)
100
+
101
+ def dark_mode(dark = None):
102
+ if dark is None:
103
+ config.color_mode_dark = not config.color_mode_dark
104
+ else:
105
+ config.color_mode_dark = dark
106
+ set_colors(config.color_mode_dark, config.transparent_background)
107
+
20
108
  def reset():
21
109
 
110
+ set_colors(config.color_mode_dark, config.transparent_background)
111
+
22
112
  """ Reopen viewer each time show() is called, this might change window focus. """
23
113
  config.reopen_viewer = True
24
114
 
@@ -42,7 +132,8 @@ def reset():
42
132
 
43
133
  """ Types that by default will be embedded in the node of their parent. """
44
134
  config.embedded_types = {
45
- type(None), bool, int, float, complex, str, unquoted_str, html_str,
135
+ type(None), bool, int, float, complex,
136
+ str, full_str, unquoted_str, html_str,
46
137
  types.FunctionType,
47
138
  types.MethodType,
48
139
  classmethod,
@@ -85,34 +176,6 @@ def reset():
85
176
  ),
86
177
  BaseException: lambda data: Node_Leaf(data, data),
87
178
  }
88
-
89
- """ Colors of different types in the graph. """
90
- config.type_to_color = {
91
- # ================= singular
92
- type(None) : "gray",
93
- bool : "pink",
94
- int : "darkolivegreen1",
95
- float : "plum",
96
- complex : "yellow",
97
- str : "cyan",
98
- # ================= linear
99
- tuple : "orange",
100
- list : "lightcoral",
101
- set : "orchid1",
102
- frozenset : "orchid2",
103
- bytes : "khaki1",
104
- bytearray : "khaki2",
105
- # ================= key_value
106
- Node_Key_Value : "seagreen1", # for classes
107
- call_stack : 'khaki',
108
- type: "seagreen3", # where class variables are stored
109
- dict : "#60a5ff",
110
- types.MappingProxyType : "dodgerblue2", # not used
111
- range : "cornsilk2",
112
- # ================= exception
113
- BaseException : "#ff5555",
114
- }
115
-
116
179
 
117
180
  """ Types that will be visualized in horizontal or vertical orientation based on a True/False value.
118
181
  The 'type_to_horizontal' takes precedence over 'type_to_vertical'.
@@ -6,17 +6,19 @@ import memory_graph.config as config
6
6
  import memory_graph.config_helpers as config_helpers
7
7
  import memory_graph.utils as utils
8
8
 
9
- def html_table_frame(s, border, color, spacing=5):
9
+ def html_table_frame(s, border, color, line_color='black', spacing=5):
10
10
  """ Helper function to add the HTML table frame to the string s setting the 'border' and 'color'. """
11
- return (f'<\n<TABLE BORDER="{border}" CELLBORDER="1" CELLSPACING="{spacing}" CELLPADDING="0" BGCOLOR="{color}" PORT="table">\n <TR>' +
11
+ return (f'<\n<TABLE BORDER="{border}" CELLBORDER="1" CELLSPACING="{spacing}" CELLPADDING="0" BGCOLOR="{color}" COLOR="{line_color}" PORT="table">\n <TR>' +
12
12
  s + '</TR>\n</TABLE>\n>')
13
13
 
14
14
  def format_string(value, quote_str):
15
15
  """ Helper function to format 'value' to be shown in the graph. We escape html characters and convert newlines to <BR/> tags. """
16
16
  to_string = config_helpers.get_to_string(value)
17
17
  s = to_string(value)
18
- if quote_str and isinstance(value, str) or isinstance(value, utils.full_str):
18
+ if quote_str and isinstance(value, (str, utils.full_str)):
19
19
  s = utils.quote_string(s)
20
+ if not isinstance(value, utils.html_str): # <IMG> can't have padding in Graphviz
21
+ s = utils.pad_string(s)
20
22
  return s
21
23
 
22
24
  class HTML_Table:
@@ -58,7 +60,7 @@ class HTML_Table:
58
60
  def add_index(self, s):
59
61
  """ Add an index s to the table. """
60
62
  self.check_add_new_line()
61
- self.html += f'<TD BORDER="0"><font color="#505050">{str(s)}</font></TD>'
63
+ self.html += f'<TD BORDER="0"><font color="{config.index_color}">{str(s)}</font></TD>'
62
64
  self.col_count += 1
63
65
 
64
66
  def add_entry(self, node, nodes, child, id_to_slices, rounded=False, border=1, dashed=False, embed=False):
@@ -77,7 +79,7 @@ class HTML_Table:
77
79
  """ Helper function to add 'value' to the table. """
78
80
  self.check_add_new_line()
79
81
  r = ' STYLE="ROUNDED"' if rounded else ''
80
- self.html += f'<TD BORDER="{border}"{r}> {format_string(value, not rounded)} </TD>'
82
+ self.html += f'<TD BORDER="{border}"{r}>{format_string(value, not rounded)}</TD>'
81
83
  self.is_empty = False
82
84
  self.col_count += 1
83
85
 
@@ -98,13 +100,13 @@ class HTML_Table:
98
100
  self.html += f'<TD BORDER="{border}" {r}>...</TD>'
99
101
  self.col_count += 1
100
102
 
101
- def to_string(self, border=1, color='white'):
103
+ def to_string(self, border=1, color='white', line_color='black'):
102
104
  """ Construct the HTML table string with the 'border' and 'color' settings. """
103
105
  if self.col_count == 0 and self.row_count == 0:
104
106
  if self.is_empty:
105
107
  self.add_value(utils.unquoted_str(''), border=0)
106
- return html_table_frame(self.html, border, color, spacing=0)
107
- return html_table_frame(self.html, border, color)
108
+ return html_table_frame(self.html, border, color, line_color, spacing=0)
109
+ return html_table_frame(self.html, border, color, line_color)
108
110
 
109
111
  def get_column(self):
110
112
  """ Get the number of columns in the table. """
@@ -218,11 +218,11 @@ def build_graph(graphviz_graph, nodes, root_id, id_to_slices):
218
218
  border = 3 if node.is_root() else 1
219
219
  if config.type_labels:
220
220
  graphviz_graph.node(node.get_name(),
221
- html_table.to_string(border, color),
221
+ html_table.to_string(border, color, config.foreground_color),
222
222
  xlabel=node.get_label(slices))
223
223
  else:
224
224
  graphviz_graph.node(node.get_name(),
225
- html_table.to_string(border, color))
225
+ html_table.to_string(border, color, config.foreground_color))
226
226
  # ------------ edges
227
227
  for parent,child,dashed in edges:
228
228
  graphviz_graph.edge(parent, child+':table', style='dashed' if dashed else 'solid')
@@ -261,9 +261,9 @@ def memory_to_nodes(data):
261
261
  id_to_slices = add_missing_edges(nodes, id_to_slices, config.max_missing_edges)
262
262
  #print('id_to_slices:',id_to_slices)
263
263
  embed_keys_in_key_value_nodes(nodes, nodes_key_value, id_to_slices)
264
- graphviz_graph_attr = {'fontname': config.fontname, 'fontsize': config.fontsize}
265
- graphviz_node_attr = {'fontname': config.fontname, 'fontsize': config.fontsize, 'shape': 'plaintext'}
266
- graphviz_edge_attr = {'fontname': config.fontname, 'fontsize': config.fontsize}
264
+ graphviz_graph_attr = {'fontname': config.fontname, 'fontsize': config.fontsize, 'fontcolor': config.foreground_color, 'bgcolor': config.background_color}
265
+ graphviz_node_attr = {'fontname': config.fontname, 'fontsize': config.fontsize, 'shape': 'plaintext', 'fontcolor': config.foreground_color}
266
+ graphviz_edge_attr = {'fontname': config.fontname, 'fontsize': config.fontsize, 'fontcolor': config.foreground_color, 'color': config.foreground_color}
267
267
  graphviz_graph=graphviz.Digraph('memory_graph',
268
268
  graph_attr=graphviz_graph_attr,
269
269
  node_attr=graphviz_node_attr,
@@ -45,9 +45,13 @@ def prep_str(s):
45
45
  return newlines_to_br(html_escape(limit_string(s)))
46
46
 
47
47
  def quote_string(s):
48
- """ Quote 's' if it is a string. """
48
+ """ Quote string 's'. """
49
49
  return "'" + s + "'"
50
50
 
51
+ def pad_string(s):
52
+ """ Pad string 's'. """
53
+ return " " + s + " "
54
+
51
55
  def exception_to_string(e):
52
56
  """ Helper function to convert the traceback of an exception to a string. """
53
57
  return ''.join(traceback.format_exception(type(e), e, e.__traceback__)).strip()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: memory_graph
3
- Version: 0.3.77
3
+ Version: 0.3.79
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-Expression: BSD-2-Clause
@@ -27,7 +27,7 @@ Additionally [Graphviz](https://graphviz.org/download/) needs to be installed.
27
27
 
28
28
  # Highlights #
29
29
  ![vscode_copying.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/vscode_copying.gif)
30
- 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!
30
+ Run a live demo in the 👉 [**Memory Graph Web Debugger**](https://memory-graph.com/#breakpoints=8&continues=1&play) 👈 now, no installation required!
31
31
 
32
32
  - learn the right **mental model** to think about Python data (references, mutability, shallow vs deep copy)
33
33
  - **visualize the structure of your data** to more easily understand and debug any data structure
@@ -35,7 +35,7 @@ Run a live demo in the 👉 [**Memory Graph Web Debugger**](https://memory-graph
35
35
 
36
36
  An example Binary Tree data structure:
37
37
  ![bin_tree_vs.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/bin_tree_vs.gif)
38
- 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).
38
+ Or see it in the [Memory Graph 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).
39
39
 
40
40
  # Videos #
41
41
  | [![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) |
@@ -102,7 +102,7 @@ a graph showing `a` and `b` share the list
102
102
 
103
103
  </td></tr></table>
104
104
 
105
- The fact that `a` and `b` share the list can not be verified by printing the lists. It can be verified by comparing the identity of both variables using the `id()` function or by using the `is` comparison operator as shown in the program output below, but this quickly becomes impractical for larger programs.
105
+ The fact that `a` and `b` share the list can **not** be verified by printing the lists. It can be verified by comparing the identity of both variables using the `id()` function or by using the `is` comparison operator as shown in the program output below, but this quickly becomes impractical for larger programs.
106
106
  ```{verbatim}
107
107
  a: 4, 3, 2, 1
108
108
  b: 4, 3, 2, 1
@@ -163,7 +163,7 @@ Bas Terwijn
163
163
  ## Inspiration ##
164
164
  Inspired by [Python Tutor](https://pythontutor.com/).
165
165
 
166
- The main differences are that by running memory_graph locally we support Python Tutor’s [unsupported features](https://github.com/pythontutor-dev/pythontutor/blob/master/unsupported-features.md#unsupported-features) so that it scales to full programs in many environments and IDEs instead of just code snippets in a webbrowser, and by mirroring the data’s hierarchy we improve graph readability for larger graphs.
166
+ The main differences are that by running memory_graph locally we support Python Tutor’s [unsupported features](https://github.com/pythontutor-dev/pythontutor/blob/master/unsupported-features.md#unsupported-features) so that it scales to full multi-file programs in many environments and IDEs instead of just code snippets in a webbrowser, and by mirroring the data’s hierarchy we improve graph readability for larger graphs.
167
167
 
168
168
  ## Social Media #
169
169
  * [LinkedIn](https://www.linkedin.com/groups/13244150/)
@@ -242,7 +242,7 @@ mg.show(locals())
242
242
 
243
243
  ![copy_mutbale.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/copy_mutable.png)
244
244
 
245
- 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/copies.py&play).
245
+ Or see it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/copies.py&play).
246
246
 
247
247
  ## Custom Copy ##
248
248
  We can write our own custom copy function or method in case the three standard "copy" options don't do what we want. For example, in the code below the `custom_copy()` method of My_Class copies the `digits` but shares the `letters` between two objects.
@@ -270,12 +270,16 @@ mg.show(locals())
270
270
  ```
271
271
  ![copy_method.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/copy_method.png)
272
272
 
273
- 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).
273
+ Or see it in the [Memory Graph 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).
274
274
 
275
275
  ## Name Rebinding ##
276
276
  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 affecting any other variable.
277
277
 
278
- Also note the difference between statement `b += [1]` that changes `b` and `a`, and statement `c = c + [300]` that first creates the new value `c + [300]` and assigns this value to `c` without effecting `b`. This shows that `x += y` is not the same as `x = x + y` for values of mutable type.
278
+ In the example below, also note the difference between expressions:
279
+ - `b += [300]`: that changes both `b` and `a`
280
+ - `c = c + [600]`: that first creates a new value `c + [600]` and then assigns this new value to `c` without affecting `b`
281
+
282
+ This shows that `x += y` is not the same as `x = x + y` for a value `x` of mutable type.
279
283
 
280
284
  ```python
281
285
  import memory_graph as mg
@@ -296,7 +300,7 @@ mg.render(locals(), 'rebinding3.png')
296
300
  |:--------------:|:--------------:|:--------------:|
297
301
  | rebinding1.png | rebinding2.png | rebinding3.png |
298
302
 
299
- 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/rebind.py&play).
303
+ Or see it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/rebind.py&play).
300
304
 
301
305
  ## Copying Values of Immutable Type ##
302
306
  Because a value of immutable type will be copied automatically when it is changed, there is no need to copy it beforehand. Therefore, a shallow or deep copy of a value of immutable type will result in just an assignment to save on the time needed to make the copy and the space (=memory) needed to store the values.
@@ -354,7 +358,7 @@ print(f"a:{a} b:{b} c:{c}")
354
358
  ```
355
359
  ![add_one.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/add_one.png)
356
360
 
357
- 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).
361
+ Or see it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/function_call.py&play).
358
362
 
359
363
  In the printed output we see that only `a` is changed as a result of the function call:
360
364
  ```
@@ -383,7 +387,7 @@ print(f"a:{a} b:{b[0]}")
383
387
  ```
384
388
  a:10 b:11
385
389
  ```
386
- 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/wrap.py&breakpoints=5&continues=1&play)
390
+ Or see it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/wrap.py&breakpoints=5&continues=1&play)
387
391
 
388
392
  The effect of calling `add_one()` is that `b[0]` increases by 1, while `a` is unaffected.
389
393
 
@@ -424,7 +428,7 @@ print( factorial(4) )
424
428
 
425
429
  and the result is: 1 x 2 x 3 x 4 = 24
426
430
 
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/factorial.py&timestep=1.0&play).
431
+ Or see it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/factorial.py&timestep=1.0&play).
428
432
 
429
433
  ## Binary Conversion ##
430
434
  A more interesting recursive example is function `binary()` that converts a integer from decimal to binary representation.
@@ -448,7 +452,7 @@ print( binary(100) )
448
452
  [1, 1, 0, 0, 1, 0, 0]
449
453
  ```
450
454
 
451
- 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).
455
+ Or see it in the [Memory Graph 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).
452
456
 
453
457
  ## Power Set ##
454
458
  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.
@@ -480,7 +484,7 @@ print( power_set(['a', 'b', 'c']) )
480
484
  [['a', 'b', 'c'], ['a', 'b'], ['a', 'c'], ['a'], ['b', 'c'], ['b'], ['c'], []]
481
485
  ```
482
486
 
483
- 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).
487
+ Or see it in the [Memory Graph 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).
484
488
 
485
489
  ## Invocation Tree ##
486
490
  The memory_graph package visualizes data at the currect time, but to better understand recursion it can also be helpful to visualize different function calls over time. This is what the [invocation_tree](https://github.com/bterwijn/invocation_tree?tab=readme-ov-file#installation) package does.
@@ -644,7 +648,7 @@ for i in range(n):
644
648
  Here we show values being added to a Linked List in Cursor AI. When adding the last value '5' we "Step Into" the code to show more of the details.
645
649
  ![linked_list.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/linked_list.gif)
646
650
 
647
- 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/linked_list.py&timestep=0.2&play).
651
+ Or see it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/linked_list.py&timestep=0.2&play).
648
652
 
649
653
  ## Binary Tree ##
650
654
  ```python
@@ -686,7 +690,7 @@ for i in range(n):
686
690
  Here we show values being inserted in a Binary Tree in Visual Studio Code. When inserting the last value '29' we "Step Into" the code to show the recursive implementation.
687
691
  ![images/bin_tree.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/bin_tree.gif)
688
692
 
689
- 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) or see the more advanced [Multiway Tree](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/multiway_tree.py&breakpoints=19,33&continues=1&timestep=0.2&play) with more than two children per node, making the tree less deep and more efficient.
693
+ See it in the [Memory Graph 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) or see the more advanced [Multiway Tree](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/multiway_tree.py&breakpoints=19,33&continues=1&timestep=0.2&play) with more than two children per node, making the tree less deep and more efficient.
690
694
 
691
695
  ## Hash Set ##
692
696
  ```python
@@ -730,7 +734,7 @@ for i in range(n):
730
734
  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.
731
735
  ![images/hash_set.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/hash_set.gif)
732
736
 
733
- 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).
737
+ Or see it in the [Memory Graph 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).
734
738
 
735
739
 
736
740
  # Sorting Algorithms #
@@ -757,7 +761,7 @@ In this configuration example we show the decimal, binary and [two's complement
757
761
 
758
762
  A sliding puzzle solver as a challenging example showing how memory_graph deals with large amounts of data. Click "Continue" to step through the breadth-first search generations until a solution path is found:
759
763
 
760
- - [sliding puzzle solver](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/sliding_puzzle.py&breakpoints=16,26,28,39&continues=1)
764
+ - [sliding puzzle solver](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/sliding_puzzle.py&breakpoints=16,26,28,39,136&continues=1)
761
765
 
762
766
  ![sliding_puzzle.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/sliding_puzzle.png)
763
767
 
@@ -1245,13 +1249,72 @@ Arguably the visualization is then more clear when we show a List_View object as
1245
1249
 
1246
1250
  ```python
1247
1251
  mg.config.type_to_node[List_View] = (lambda l: mg.Node_Linear(l,
1248
- [v if l.begin <= i < l.end else mg.unquoted('') for i, v in enumerate(l.lst)]
1252
+ [v if l.begin <= i < l.end else mg.unquoted_str('') for i, v in enumerate(l.lst)]
1249
1253
  if hasattr(l, 'end') else [])
1250
1254
  )
1251
1255
  ```
1252
1256
  ![bin_search_linear.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/bin_search_linear.png)
1253
1257
 
1254
- 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_search.py&breakpoints=32&continues=1&timestep=0.5&play)
1258
+ Or see it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/bin_search.py&breakpoints=38&continues=1&timestep=0.5&play)
1259
+
1260
+ ## String Types ##
1261
+
1262
+ For special string formatting different `str` types are available:
1263
+
1264
+ | string type | format |
1265
+ |:--------------------------:|:--------------------:|
1266
+ | `str` | normal Python `str` type is limited by `config.max_string_length` |
1267
+ | `mg.full_str('text')` | not limited |
1268
+ | `mg.unquoted_str('text')` | not limited and not quoted |
1269
+ | `mg.html_str('text')` | for [Grahviz html-like formatting](https://graphviz.org/doc/info/shapes.html#html) |
1270
+
1271
+ The [Grahviz html-like formatting](https://graphviz.org/doc/info/shapes.html#html) supports a subset of html tags that allow for things like:
1272
+ ```python
1273
+ import memory_graph as mg
1274
+
1275
+ elements = ['<B>bold</B>',
1276
+ '<I>italic</I>',
1277
+ '<S>strikethrough</S>',
1278
+ '<U>under</U><O>over</O>',
1279
+ '<SUB>sub</SUB><SUP>sup</SUP>',
1280
+ '<FONT FACE="Courier">monospaced</FONT>',
1281
+ '<FONT COLOR="red">red</FONT><FONT COLOR="green">green</FONT>',
1282
+ '<FONT POINT-SIZE="20">Large</FONT><FONT POINT-SIZE="10">small</FONT>',
1283
+ '<TABLE BORDER="1"><TR><TD>c1</TD><TD>c2</TD></TR></TABLE>',
1284
+ 'line1<BR/>line2<BR/>line3<BR/>']
1285
+
1286
+ normal_str = '<TABLE BORDER="0">\n'
1287
+ for element in elements:
1288
+ normal_str += '<TR><TD> ' + mg.utils.html_escape(element) + ' </TD><TD> ' + element+ ' </TD></TR>element\n'
1289
+ normal_str += '</TABLE>\n'
1290
+
1291
+ html_example = mg.html_str(normal_str)
1292
+ del elements, element, normal_str
1293
+ mg.show(locals())
1294
+ ```
1295
+ ![html_str_example.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/html_str_example.png)
1296
+
1297
+ Including the `<IMG>` tag that allows for showing local image files only, but that currently doesn't work in the Memory Graph Web Debugger, that uses 'Viz.js' for graph rendering, unfortunately.
1298
+
1299
+ ```python
1300
+ import memory_graph as mg
1301
+ import matplotlib.pyplot as plt
1302
+ import random
1303
+ random.seed(0)
1304
+
1305
+ N = 100
1306
+ value = 0
1307
+ data = [value]
1308
+ for i in range(N):
1309
+ value += random.uniform(-1, 1)
1310
+ data.append(value)
1311
+
1312
+ plt.plot(data)
1313
+ plt.savefig('plot.png')
1314
+ image = {mg.html_str('<IMG SRC="plot.png"/>')}
1315
+ mg.show(locals())
1316
+ ```
1317
+ ![html_str_image.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/html_str_image.png)
1255
1318
 
1256
1319
  ## Collapse Type ##
1257
1320
 
@@ -1384,7 +1447,7 @@ mg.show(locals())
1384
1447
  ```
1385
1448
  ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/extension_numpy.png)
1386
1449
 
1387
- 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).
1450
+ Or see it in the [Memory Graph Web Debugger](https://memory-graph.com/#micropip=numpy&codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/mg_numpy.py&play).
1388
1451
 
1389
1452
  ## Pandas ##
1390
1453
  For pandas types `Series` and `DataFrame`, use `mg.extend_pandas()`:
@@ -1405,7 +1468,7 @@ mg.show(locals())
1405
1468
  ```
1406
1469
  ![extension_pandas.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/extension_pandas.png)
1407
1470
 
1408
- 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).
1471
+ Or see it in the [Memory Graph Web Debugger](https://memory-graph.com/#micropip=pandas&codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/mg_pandas.py&play).
1409
1472
 
1410
1473
  ## PyTorch ##
1411
1474
  For torch type `tensor`, use `mg.extend_torch()`:
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "memory_graph"
7
- version = "0.3.77"
7
+ version = "0.3.79"
8
8
  description = "Teaching tool and debugging aid in context of references, mutable data types, and shallow and deep copy."
9
9
  authors = [
10
10
  {name = "Bas Terwijn", email = "bterwijn@gmail.com"}
File without changes
File without changes
File without changes