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.
- {memory_graph-0.3.76 → memory_graph-0.3.78}/PKG-INFO +10 -6
- {memory_graph-0.3.76 → memory_graph-0.3.78}/README.md +9 -5
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/__init__.py +2 -2
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/config_default.py +11 -7
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/config_helpers.py +21 -3
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/html_table.py +11 -9
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/memory_to_nodes.py +1 -2
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/node_linear.py +3 -2
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/node_table.py +6 -4
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/utils.py +54 -1
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph.egg-info/PKG-INFO +10 -6
- {memory_graph-0.3.76 → memory_graph-0.3.78}/pyproject.toml +1 -1
- {memory_graph-0.3.76 → memory_graph-0.3.78}/LICENSE.txt +0 -0
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/call_stack.py +0 -0
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/config.py +0 -0
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/extension_numpy.py +0 -0
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/extension_pandas.py +0 -0
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/extension_torch.py +0 -0
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/list_view.py +0 -0
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/node_base.py +0 -0
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/node_key_value.py +0 -0
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/node_leaf.py +0 -0
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/sequence.py +0 -0
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/slicer.py +0 -0
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/slices.py +0 -0
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/slices_iterator.py +0 -0
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/slices_table_iterator.py +0 -0
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/test.py +0 -0
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/test_max_graph_depth.py +0 -0
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/test_memory_graph.py +0 -0
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/test_memory_to_nodes.py +0 -0
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/test_sequence.py +0 -0
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/test_slicer.py +0 -0
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/test_slices.py +0 -0
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph/test_slices_iterator.py +0 -0
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph.egg-info/SOURCES.txt +0 -0
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph.egg-info/dependency_links.txt +0 -0
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph.egg-info/requires.txt +0 -0
- {memory_graph-0.3.76 → memory_graph-0.3.78}/memory_graph.egg-info/top_level.txt +0 -0
- {memory_graph-0.3.76 → memory_graph-0.3.78}/setup.cfg +0 -0
- {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.
|
|
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
|
-
|
|
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
|

|
|
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&
|
|
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
|

|
|
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&
|
|
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
|
-
|
|
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
|

|
|
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&
|
|
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
|

|
|
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&
|
|
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.
|
|
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.
|
|
64
|
-
types.MethodType: lambda data: utils.
|
|
65
|
-
classmethod: lambda data: utils.
|
|
66
|
-
staticmethod: lambda data: utils.
|
|
67
|
-
type(len): lambda data: utils.
|
|
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
|
|
51
|
+
return
|
|
36
52
|
except Exception as e:
|
|
37
|
-
|
|
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
|
|
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
|
|
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 =
|
|
20
|
-
|
|
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}>
|
|
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
|
-
|
|
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
|
|
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
|
-
"""
|
|
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.
|
|
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
|
-
|
|
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
|

|
|
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&
|
|
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
|

|
|
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&
|
|
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.
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|