memory-graph 0.3.76__tar.gz → 0.3.78__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.76 → memory_graph-0.3.78}/PKG-INFO +10 -6
  2. {memory_graph-0.3.76 → memory_graph-0.3.78}/README.md +9 -5
  3. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/__init__.py +2 -2
  4. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/config_default.py +11 -7
  5. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/config_helpers.py +21 -3
  6. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/html_table.py +11 -9
  7. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/memory_to_nodes.py +1 -2
  8. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/node_linear.py +3 -2
  9. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/node_table.py +6 -4
  10. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/utils.py +54 -1
  11. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph.egg-info/PKG-INFO +10 -6
  12. {memory_graph-0.3.76 → memory_graph-0.3.78}/pyproject.toml +1 -1
  13. {memory_graph-0.3.76 → memory_graph-0.3.78}/LICENSE.txt +0 -0
  14. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/call_stack.py +0 -0
  15. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/config.py +0 -0
  16. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/extension_numpy.py +0 -0
  17. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/extension_pandas.py +0 -0
  18. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/extension_torch.py +0 -0
  19. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/list_view.py +0 -0
  20. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/node_base.py +0 -0
  21. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/node_key_value.py +0 -0
  22. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/node_leaf.py +0 -0
  23. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/sequence.py +0 -0
  24. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/slicer.py +0 -0
  25. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/slices.py +0 -0
  26. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/slices_iterator.py +0 -0
  27. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/slices_table_iterator.py +0 -0
  28. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/test.py +0 -0
  29. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/test_max_graph_depth.py +0 -0
  30. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/test_memory_graph.py +0 -0
  31. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/test_memory_to_nodes.py +0 -0
  32. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/test_sequence.py +0 -0
  33. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/test_slicer.py +0 -0
  34. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/test_slices.py +0 -0
  35. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/test_slices_iterator.py +0 -0
  36. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph.egg-info/SOURCES.txt +0 -0
  37. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph.egg-info/dependency_links.txt +0 -0
  38. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph.egg-info/requires.txt +0 -0
  39. {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph.egg-info/top_level.txt +0 -0
  40. {memory_graph-0.3.76 → memory_graph-0.3.78}/setup.cfg +0 -0
  41. {memory_graph-0.3.76 → memory_graph-0.3.78}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: memory_graph
3
- Version: 0.3.76
3
+ Version: 0.3.78
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
@@ -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
@@ -275,7 +275,11 @@ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=ht
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
@@ -1245,7 +1249,7 @@ 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 '' 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
  ```
@@ -1384,7 +1388,7 @@ mg.show(locals())
1384
1388
  ```
1385
1389
  ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/extension_numpy.png)
1386
1390
 
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).
1391
+ 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&play).
1388
1392
 
1389
1393
  ## Pandas ##
1390
1394
  For pandas types `Series` and `DataFrame`, use `mg.extend_pandas()`:
@@ -1405,7 +1409,7 @@ mg.show(locals())
1405
1409
  ```
1406
1410
  ![extension_pandas.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/extension_pandas.png)
1407
1411
 
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).
1412
+ 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&play).
1409
1413
 
1410
1414
  ## PyTorch ##
1411
1415
  For torch type `tensor`, use `mg.extend_torch()`:
@@ -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
@@ -255,7 +255,11 @@ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=ht
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
@@ -1225,7 +1229,7 @@ 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 '' 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
  ```
@@ -1364,7 +1368,7 @@ mg.show(locals())
1364
1368
  ```
1365
1369
  ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/extension_numpy.png)
1366
1370
 
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).
1371
+ 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&play).
1368
1372
 
1369
1373
  ## Pandas ##
1370
1374
  For pandas types `Series` and `DataFrame`, use `mg.extend_pandas()`:
@@ -1385,7 +1389,7 @@ mg.show(locals())
1385
1389
  ```
1386
1390
  ![extension_pandas.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/extension_pandas.png)
1387
1391
 
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).
1392
+ 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&play).
1389
1393
 
1390
1394
  ## PyTorch ##
1391
1395
  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.76"
5
+ __version__ = "0.3.78"
6
6
  __author__ = 'Bas Terwijn'
7
7
 
8
8
  import memory_graph.memory_to_nodes as memory_to_nodes
@@ -31,7 +31,7 @@ from .node_leaf import Node_Leaf
31
31
  from .node_linear import Node_Linear
32
32
  from .node_key_value import Node_Key_Value
33
33
  from .node_table import Node_Table
34
-
34
+ from .utils import unquoted_str, full_str, html_str
35
35
 
36
36
  last_show_filename = None
37
37
  render_filename_count = 0
@@ -3,6 +3,7 @@
3
3
  # SPDX-License-Identifier: BSD-2-Clause
4
4
 
5
5
  """ Sets the default configuration values for the memory graph. """
6
+ from memory_graph.utils import unquoted_str, full_str, html_str
6
7
  from memory_graph.node_leaf import Node_Leaf
7
8
  from memory_graph.node_linear import Node_Linear
8
9
  from memory_graph.node_key_value import Node_Key_Value
@@ -41,7 +42,7 @@ def reset():
41
42
 
42
43
  """ Types that by default will be embedded in the node of their parent. """
43
44
  config.embedded_types = {
44
- type(None), bool, int, float, complex, str,
45
+ type(None), bool, int, float, complex, str, unquoted_str, html_str,
45
46
  types.FunctionType,
46
47
  types.MethodType,
47
48
  classmethod,
@@ -60,12 +61,15 @@ def reset():
60
61
 
61
62
  """ Types that need a special conversion """
62
63
  config.type_to_string = {
63
- types.FunctionType: lambda data: utils.limit_string(data.__qualname__),
64
- types.MethodType: lambda data: utils.limit_string(data.__qualname__),
65
- classmethod: lambda data: utils.limit_string(data.__qualname__),
66
- staticmethod: lambda data: utils.limit_string(data.__qualname__),
67
- type(len): lambda data: utils.limit_string(data.__qualname__),
68
- BaseException: lambda data: utils.exception_to_string(data),
64
+ types.FunctionType: lambda data: utils.prep_str(data.__qualname__),
65
+ types.MethodType: lambda data: utils.prep_str(data.__qualname__),
66
+ classmethod: lambda data: utils.prep_str(data.__qualname__),
67
+ staticmethod: lambda data: utils.prep_str(data.__qualname__),
68
+ type(len): lambda data: utils.prep_str(data.__qualname__),
69
+ BaseException: lambda data: utils.prep_exception_str(utils.exception_to_string(data)),
70
+ unquoted_str: lambda data: utils.newlines_to_br(utils.html_escape(str(data))),
71
+ full_str: lambda data: utils.newlines_to_br(utils.html_escape(str(data))),
72
+ html_str: lambda data: str(data),
69
73
  }
70
74
 
71
75
  """ Conversion from type to Node objects. """
@@ -25,6 +25,22 @@ def get_data_to_node(data, default=None):
25
25
  config.type_to_node,
26
26
  default )
27
27
 
28
+ def is_property(data_id, data_types, node_type, types_set):
29
+ if data_id in types_set:
30
+ return True
31
+ for data_type in data_types:
32
+ if data_type in types_set:
33
+ return True
34
+ if node_type in types_set:
35
+ return True
36
+ return False
37
+
38
+ def is_embedded_type(data):
39
+ return is_property(id(data),
40
+ utils.get_all_types(data),
41
+ None,
42
+ config.embedded_types )
43
+
28
44
  def default_to_string(data):
29
45
  """ Convert data to string. """
30
46
  try:
@@ -32,11 +48,13 @@ def default_to_string(data):
32
48
  s = data
33
49
  else:
34
50
  s = str(data)
35
- return utils.limit_string(s)
51
+ return
36
52
  except Exception as e:
37
- return f'no stringification, {type(e).__name__}: {e}'
53
+ s = 'no stringification, '+ type(e).__name__ +': '+ str(e)
54
+ finally:
55
+ return utils.prep_str(s)
38
56
 
39
- def get_to_string(data, default=lambda s: default_to_string(s)):
57
+ def get_to_string(data, default=lambda d: default_to_string(d)):
40
58
  return get_property(id(data),
41
59
  utils.get_all_types(data),
42
60
  None,
@@ -2,22 +2,24 @@
2
2
  # Copyright (c) 2023, Bas Terwijn.
3
3
  # SPDX-License-Identifier: BSD-2-Clause
4
4
 
5
- from memory_graph.node_base import Node_Base
6
- import memory_graph.node_base
7
5
  import memory_graph.config as config
8
6
  import memory_graph.config_helpers as config_helpers
9
- import html
7
+ import memory_graph.utils as utils
10
8
 
11
9
  def html_table_frame(s, border, color, spacing=5):
12
10
  """ Helper function to add the HTML table frame to the string s setting the 'border' and 'color'. """
13
11
  return (f'<\n<TABLE BORDER="{border}" CELLBORDER="1" CELLSPACING="{spacing}" CELLPADDING="0" BGCOLOR="{color}" PORT="table">\n <TR>' +
14
12
  s + '</TR>\n</TABLE>\n>')
15
13
 
16
- def format_string(value):
14
+ def format_string(value, quote_str):
17
15
  """ Helper function to format 'value' to be shown in the graph. We escape html characters and convert newlines to <BR/> tags. """
18
16
  to_string = config_helpers.get_to_string(value)
19
- s = html.escape(to_string(value))
20
- return s.replace('\n', ' <BR/> ')
17
+ s = to_string(value)
18
+ if quote_str and isinstance(value, (str, utils.full_str)):
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)
22
+ return s
21
23
 
22
24
  class HTML_Table:
23
25
  """
@@ -69,7 +71,7 @@ class HTML_Table:
69
71
  if child_id in id_to_slices:
70
72
  self.add_reference(node, child, rounded, border, dashed)
71
73
  else:
72
- self.add_value(config.graph_cut_symbol, rounded, border)
74
+ self.add_value(utils.unquoted_str(config.graph_cut_symbol), rounded, border)
73
75
  else:
74
76
  self.add_value(child, rounded, border)
75
77
 
@@ -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)} </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
 
@@ -102,7 +104,7 @@ class HTML_Table:
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
- self.add_value('', border=0)
107
+ self.add_value(utils.unquoted_str(''), border=0)
106
108
  return html_table_frame(self.html, border, color, spacing=0)
107
109
  return html_table_frame(self.html, border, color)
108
110
 
@@ -36,8 +36,7 @@ def read_nodes(data):
36
36
  """ Recursively reads through each reference found in 'data', creates a node for
37
37
  it and adds, and adds it to 'nodes'.
38
38
  """
39
- data_type = type(data)
40
- if not data_type in config.embedded_types or parent is None:
39
+ if not config_helpers.is_embedded_type(data) or parent is None:
41
40
  data_id = id(data)
42
41
  if data_id in nodes:
43
42
  node = nodes[data_id]
@@ -7,6 +7,7 @@ from memory_graph.sequence import Sequence1D
7
7
 
8
8
  import memory_graph.config_helpers as config_helpers
9
9
  import memory_graph.config as config
10
+ import memory_graph.utils as utils
10
11
 
11
12
  class Node_Linear(Node_Base):
12
13
  """
@@ -66,7 +67,7 @@ class Node_Linear(Node_Base):
66
67
  html_table.add_entry(self, nodes, child, id_to_slices, dashed=slices.is_dashed(index))
67
68
  html_table.add_new_line()
68
69
  else:
69
- html_table.add_value('', border=0)
70
+ html_table.add_value(utils.unquoted_str(''), border=0)
70
71
  html_table.add_dots()
71
72
  html_table.add_new_line()
72
73
 
@@ -80,7 +81,7 @@ class Node_Linear(Node_Base):
80
81
  if index>=0:
81
82
  html_table.add_index(index)
82
83
  else:
83
- html_table.add_value('', border=0)
84
+ html_table.add_value(utils.unquoted_str(''), border=0)
84
85
  html_table.add_new_line()
85
86
  for index in slices.table_iter(self.children.size()):
86
87
  if index>=0:
@@ -3,9 +3,11 @@
3
3
  # SPDX-License-Identifier: BSD-2-Clause
4
4
 
5
5
  from memory_graph.node_base import Node_Base
6
- from memory_graph.sequence import Sequence2D
6
+ from memory_graph.sequence import Sequence2D
7
7
  from memory_graph.list_view import List_View
8
8
 
9
+ import memory_graph.utils as utils
10
+
9
11
  class Node_Table(Node_Base):
10
12
  """
11
13
  Node_Table (subclass of Node_Base) is a node that represents a 2D table of data used for
@@ -43,10 +45,10 @@ class Node_Table(Node_Base):
43
45
  col_slices = slices.get_col_slices()
44
46
 
45
47
  # use column indices for header row
46
- html_table.add_value('', border=0)
48
+ html_table.add_value(utils.unquoted_str(''), border=0)
47
49
  for coli in col_slices.table_iter(children_width):
48
50
  if coli == -1:
49
- html_table.add_value('', border=0)
51
+ html_table.add_value(utils.unquoted_str(''), border=0)
50
52
  else:
51
53
  self.add_index_or_name(html_table, coli, self.col_names)
52
54
  html_table.add_new_line()
@@ -65,7 +67,7 @@ class Node_Table(Node_Base):
65
67
  first_col = True
66
68
  elif coli == -3:
67
69
  html_table.add_new_line()
68
- html_table.add_value('', border=0)
70
+ html_table.add_value(utils.unquoted_str(''), border=0)
69
71
  for _ in range (html_table.get_max_column()-1):
70
72
  html_table.add_dots()
71
73
  html_table.add_new_line()
@@ -7,15 +7,51 @@ import types
7
7
  import functools
8
8
  import traceback
9
9
  import re
10
+ import html
10
11
 
11
12
  import memory_graph.config as config
12
13
 
14
+ class Base_Str():
15
+ def __init__(self, s):
16
+ self.s = s
17
+ def __str__(self):
18
+ return self.s
19
+
20
+ class unquoted_str(Base_Str):
21
+ pass
22
+
23
+ class full_str(Base_Str):
24
+ pass
25
+
26
+ class html_str(Base_Str):
27
+ pass
28
+
13
29
  def limit_string(s):
14
- """ Helper function to limit the length of a string s to the 'max_string_length' in the config. """
30
+ """ Limit the length of a string s to the 'max_string_length' in the config. """
15
31
  if len(s) > config.max_string_length:
16
32
  return s[:config.max_string_length] + '...'
17
33
  return s
18
34
 
35
+ def html_escape(s):
36
+ """ Escape HTML characters in 's' for safe display in the graph. """
37
+ return html.escape(s)
38
+
39
+ def newlines_to_br(s):
40
+ """ Replace newlines in 's' with <BR/> tags for HTML display. """
41
+ return s.replace('\n', ' <BR/> ')
42
+
43
+ def prep_str(s):
44
+ """ Prepare 's' by limiting length, escaping HTML, and replacing newlines. """
45
+ return newlines_to_br(html_escape(limit_string(s)))
46
+
47
+ def quote_string(s):
48
+ """ Quote string 's'. """
49
+ return "'" + s + "'"
50
+
51
+ def pad_string(s):
52
+ """ Pad string 's'. """
53
+ return " " + s + " "
54
+
19
55
  def exception_to_string(e):
20
56
  """ Helper function to convert the traceback of an exception to a string. """
21
57
  return ''.join(traceback.format_exception(type(e), e, e.__traceback__)).strip()
@@ -40,6 +76,23 @@ def exception_to_string_short(e):
40
76
  """ Helper function to convert an exception to a short string. """
41
77
  return f'{type(e).__name__}: {e}'
42
78
 
79
+ def mono_font(s):
80
+ """ Helper function to wrap in monospaced font. """
81
+ return f'<FONT FACE="Courier">{s}</FONT>'
82
+
83
+ def caret_line_length(s):
84
+ """ Adds whitespace to caret line in 's' so it is as long as the previois line. """
85
+ lines = s.split('\n')
86
+ for i in range(len(lines)-2, -1, -1):
87
+ if re.fullmatch(r'\s*~*\^+\s*', lines[i]): # match line like ' ~~~^^ '
88
+ lines[i] = lines[i].ljust(len(lines[i - 1]))
89
+ break
90
+ return '\n'.join(lines)
91
+
92
+ def prep_exception_str(s):
93
+ """ Helper function to prepare an exception string for HTML display. """
94
+ return newlines_to_br(mono_font(html_escape(caret_line_length(s))))
95
+
43
96
  def get_all_types(obj):
44
97
  cls = type(obj)
45
98
  if hasattr(cls, '__mro__'):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: memory_graph
3
- Version: 0.3.76
3
+ Version: 0.3.78
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
@@ -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
@@ -275,7 +275,11 @@ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=ht
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
@@ -1245,7 +1249,7 @@ 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 '' 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
  ```
@@ -1384,7 +1388,7 @@ mg.show(locals())
1384
1388
  ```
1385
1389
  ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/extension_numpy.png)
1386
1390
 
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).
1391
+ 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&play).
1388
1392
 
1389
1393
  ## Pandas ##
1390
1394
  For pandas types `Series` and `DataFrame`, use `mg.extend_pandas()`:
@@ -1405,7 +1409,7 @@ mg.show(locals())
1405
1409
  ```
1406
1410
  ![extension_pandas.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/extension_pandas.png)
1407
1411
 
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).
1412
+ 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&play).
1409
1413
 
1410
1414
  ## PyTorch ##
1411
1415
  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.76"
7
+ version = "0.3.78"
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