memory-graph 0.3.73__tar.gz → 0.3.74__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.73 → memory_graph-0.3.74}/PKG-INFO +116 -11
- {memory_graph-0.3.73 → memory_graph-0.3.74}/README.md +115 -10
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/__init__.py +1 -1
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/config.py +7 -4
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/utils.py +1 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph.egg-info/PKG-INFO +116 -11
- {memory_graph-0.3.73 → memory_graph-0.3.74}/pyproject.toml +1 -1
- {memory_graph-0.3.73 → memory_graph-0.3.74}/LICENSE.txt +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/call_stack.py +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/config_default.py +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/config_helpers.py +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/extension_numpy.py +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/extension_pandas.py +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/extension_torch.py +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/html_table.py +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/list_view.py +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/memory_to_nodes.py +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/node_base.py +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/node_key_value.py +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/node_leaf.py +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/node_linear.py +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/node_table.py +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/sequence.py +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/slicer.py +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/slices.py +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/slices_iterator.py +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/slices_table_iterator.py +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/test.py +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/test_max_graph_depth.py +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/test_memory_graph.py +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/test_memory_to_nodes.py +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/test_sequence.py +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/test_slicer.py +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/test_slices.py +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph/test_slices_iterator.py +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph.egg-info/SOURCES.txt +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph.egg-info/dependency_links.txt +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph.egg-info/requires.txt +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/memory_graph.egg-info/top_level.txt +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/setup.cfg +0 -0
- {memory_graph-0.3.73 → memory_graph-0.3.74}/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.74
|
|
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
|
|
@@ -772,7 +772,6 @@ This example shows the flow of control when using inheritance with:
|
|
|
772
772
|
- class variable `message_count`
|
|
773
773
|
|
|
774
774
|
```python
|
|
775
|
-
from datetime import datetime
|
|
776
775
|
|
|
777
776
|
class Notification_Service:
|
|
778
777
|
message_count = 0
|
|
@@ -810,14 +809,14 @@ class SMS_Notification(Notification_Service):
|
|
|
810
809
|
email = Email_Notification(3, 'support@company.com')
|
|
811
810
|
email.send('customer@email.com', 'Your report is ready')
|
|
812
811
|
email.send('customer@email.com', 'Update to Privacy Policy')
|
|
813
|
-
sms =
|
|
812
|
+
sms = SMS_Notification(3, '0123456789')
|
|
814
813
|
sms.send('001122334455', 'Update to Privacy Policy')
|
|
815
814
|
```
|
|
816
|
-
Run it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/inheritance.py&breakpoints=
|
|
815
|
+
Run it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/inheritance.py&breakpoints=35&continues=1&play).
|
|
817
816
|
|
|
818
817
|
## Decorator ##
|
|
819
818
|
|
|
820
|
-
This example shows the flow of control when using a decorator.
|
|
819
|
+
This example shows the flow of control when using a decorator. A decorator wraps a function and is active before and after the function is called.
|
|
821
820
|
|
|
822
821
|
```python
|
|
823
822
|
def log_call(function):
|
|
@@ -851,29 +850,135 @@ This example shows the flow of control when using exception handling.
|
|
|
851
850
|
def fun2():
|
|
852
851
|
try:
|
|
853
852
|
d = [0] * 3
|
|
854
|
-
for i in range(
|
|
853
|
+
for i in range(6):
|
|
855
854
|
try:
|
|
856
|
-
|
|
857
|
-
|
|
855
|
+
print(f'{i=}')
|
|
856
|
+
d[i] = i # raises IndexError when i>=3
|
|
857
|
+
except ZeroDivisionError as e:
|
|
858
858
|
print(type(e), e)
|
|
859
859
|
except AssertionError as e:
|
|
860
860
|
print(type(e), e)
|
|
861
|
-
|
|
861
|
+
print('fun2() returns')
|
|
862
|
+
|
|
862
863
|
def fun1():
|
|
863
864
|
try:
|
|
864
865
|
return fun2()
|
|
865
866
|
except NameError as e:
|
|
866
867
|
print(type(e), e)
|
|
867
|
-
|
|
868
|
+
print('fun1() returns')
|
|
869
|
+
|
|
868
870
|
try:
|
|
869
871
|
fun1()
|
|
870
872
|
except LookupError as e:
|
|
871
873
|
print(type(e), e)
|
|
874
|
+
print('program ended cleanly')
|
|
872
875
|
```
|
|
873
|
-
Run it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/exceptions.py&breakpoints=
|
|
876
|
+
Run it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/exceptions.py&breakpoints=22&continues=1&play). In the program an `IndexError` exception is raised which propagates up the call stack until it reaches an except clause that matches its type where it is handled. Here, it is handled by the `LookupError` except clause because `IndexError` is a subclass of `LookupError`. Exceptions that are not handled terminate the execution of a program while its traceback is shown for analyses.
|
|
874
877
|
|
|
875
878
|

|
|
876
879
|
|
|
880
|
+
## Lazy Evaluation ##
|
|
881
|
+
|
|
882
|
+
In the following Eager and Lazy ealuation examples, we use this `pr()` function to print in what order things are created and used.
|
|
883
|
+
|
|
884
|
+
```python
|
|
885
|
+
def pr(tag, v):
|
|
886
|
+
print(tag, v)
|
|
887
|
+
return v
|
|
888
|
+
```
|
|
889
|
+
|
|
890
|
+
With eager evaluation, the function creates all three elements up front and stores them in a list before iteration begins. With lazy evaluation, the function returns a generator that creates each element only when it is needed.
|
|
891
|
+
|
|
892
|
+
<table>
|
|
893
|
+
<tr> <td width="50%" valign="top"><strong>Eager</strong></td> <td width="50%" valign="top"><strong>Lazy</strong></td></tr>
|
|
894
|
+
<tr><td width="50%" valign="top">
|
|
895
|
+
|
|
896
|
+
```python
|
|
897
|
+
def fun():
|
|
898
|
+
result = []
|
|
899
|
+
for i in range(3):
|
|
900
|
+
result.append(pr('create:', i))
|
|
901
|
+
return result
|
|
902
|
+
|
|
903
|
+
for i in fun():
|
|
904
|
+
pr('use:', i)
|
|
905
|
+
```
|
|
906
|
+
|
|
907
|
+
Run in [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/eager_return.py&play)
|
|
908
|
+
|
|
909
|
+
</td><td width="50%" valign="top">
|
|
910
|
+
|
|
911
|
+
```python
|
|
912
|
+
def fun():
|
|
913
|
+
for i in range(3):
|
|
914
|
+
yield pr('create:', i)
|
|
915
|
+
|
|
916
|
+
|
|
917
|
+
|
|
918
|
+
for i in fun():
|
|
919
|
+
pr('use:', i)
|
|
920
|
+
```
|
|
921
|
+
|
|
922
|
+
Run in [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/lazy_yield.py&play)
|
|
923
|
+
|
|
924
|
+
</td></tr>
|
|
925
|
+
<tr><td width="50%" valign="top">
|
|
926
|
+
|
|
927
|
+
```python
|
|
928
|
+
def fun():
|
|
929
|
+
return [
|
|
930
|
+
pr('create:', i)
|
|
931
|
+
for i in range(3)
|
|
932
|
+
]
|
|
933
|
+
|
|
934
|
+
for i in fun():
|
|
935
|
+
pr('use:', i)
|
|
936
|
+
```
|
|
937
|
+
|
|
938
|
+
Run in [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/eager_compri.py&play)
|
|
939
|
+
|
|
940
|
+
</td><td width="50%" valign="top">
|
|
941
|
+
|
|
942
|
+
```python
|
|
943
|
+
def fun():
|
|
944
|
+
return (
|
|
945
|
+
pr('create:', i)
|
|
946
|
+
for i in range(3)
|
|
947
|
+
)
|
|
948
|
+
|
|
949
|
+
for i in fun():
|
|
950
|
+
pr('use:', i)
|
|
951
|
+
```
|
|
952
|
+
|
|
953
|
+
Run in [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/lazy_express.py&play)
|
|
954
|
+
|
|
955
|
+
</td></tr>
|
|
956
|
+
<tr><td width="50%" valign="top">
|
|
957
|
+
|
|
958
|
+
```text
|
|
959
|
+
create: 0
|
|
960
|
+
create: 1
|
|
961
|
+
create: 2
|
|
962
|
+
use: 0
|
|
963
|
+
use: 1
|
|
964
|
+
use: 2
|
|
965
|
+
```
|
|
966
|
+
|
|
967
|
+
</td><td width="50%" valign="top">
|
|
968
|
+
|
|
969
|
+
```text
|
|
970
|
+
create: 0
|
|
971
|
+
use: 0
|
|
972
|
+
create: 1
|
|
973
|
+
use: 1
|
|
974
|
+
create: 2
|
|
975
|
+
use: 2
|
|
976
|
+
```
|
|
977
|
+
|
|
978
|
+
</td></tr>
|
|
979
|
+
</table>
|
|
980
|
+
|
|
981
|
+
|
|
877
982
|
# Configuration #
|
|
878
983
|
Different aspects of memory_graph can be configured. The default configuration can be reset by calling 'mg.config_default.reset()'. The Memory Graph Web Debugger gives examples of the [most important configurations](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/config.py&play).
|
|
879
984
|
|
|
@@ -752,7 +752,6 @@ This example shows the flow of control when using inheritance with:
|
|
|
752
752
|
- class variable `message_count`
|
|
753
753
|
|
|
754
754
|
```python
|
|
755
|
-
from datetime import datetime
|
|
756
755
|
|
|
757
756
|
class Notification_Service:
|
|
758
757
|
message_count = 0
|
|
@@ -790,14 +789,14 @@ class SMS_Notification(Notification_Service):
|
|
|
790
789
|
email = Email_Notification(3, 'support@company.com')
|
|
791
790
|
email.send('customer@email.com', 'Your report is ready')
|
|
792
791
|
email.send('customer@email.com', 'Update to Privacy Policy')
|
|
793
|
-
sms =
|
|
792
|
+
sms = SMS_Notification(3, '0123456789')
|
|
794
793
|
sms.send('001122334455', 'Update to Privacy Policy')
|
|
795
794
|
```
|
|
796
|
-
Run it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/inheritance.py&breakpoints=
|
|
795
|
+
Run it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/inheritance.py&breakpoints=35&continues=1&play).
|
|
797
796
|
|
|
798
797
|
## Decorator ##
|
|
799
798
|
|
|
800
|
-
This example shows the flow of control when using a decorator.
|
|
799
|
+
This example shows the flow of control when using a decorator. A decorator wraps a function and is active before and after the function is called.
|
|
801
800
|
|
|
802
801
|
```python
|
|
803
802
|
def log_call(function):
|
|
@@ -831,29 +830,135 @@ This example shows the flow of control when using exception handling.
|
|
|
831
830
|
def fun2():
|
|
832
831
|
try:
|
|
833
832
|
d = [0] * 3
|
|
834
|
-
for i in range(
|
|
833
|
+
for i in range(6):
|
|
835
834
|
try:
|
|
836
|
-
|
|
837
|
-
|
|
835
|
+
print(f'{i=}')
|
|
836
|
+
d[i] = i # raises IndexError when i>=3
|
|
837
|
+
except ZeroDivisionError as e:
|
|
838
838
|
print(type(e), e)
|
|
839
839
|
except AssertionError as e:
|
|
840
840
|
print(type(e), e)
|
|
841
|
-
|
|
841
|
+
print('fun2() returns')
|
|
842
|
+
|
|
842
843
|
def fun1():
|
|
843
844
|
try:
|
|
844
845
|
return fun2()
|
|
845
846
|
except NameError as e:
|
|
846
847
|
print(type(e), e)
|
|
847
|
-
|
|
848
|
+
print('fun1() returns')
|
|
849
|
+
|
|
848
850
|
try:
|
|
849
851
|
fun1()
|
|
850
852
|
except LookupError as e:
|
|
851
853
|
print(type(e), e)
|
|
854
|
+
print('program ended cleanly')
|
|
852
855
|
```
|
|
853
|
-
Run it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/exceptions.py&breakpoints=
|
|
856
|
+
Run it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/exceptions.py&breakpoints=22&continues=1&play). In the program an `IndexError` exception is raised which propagates up the call stack until it reaches an except clause that matches its type where it is handled. Here, it is handled by the `LookupError` except clause because `IndexError` is a subclass of `LookupError`. Exceptions that are not handled terminate the execution of a program while its traceback is shown for analyses.
|
|
854
857
|
|
|
855
858
|

|
|
856
859
|
|
|
860
|
+
## Lazy Evaluation ##
|
|
861
|
+
|
|
862
|
+
In the following Eager and Lazy ealuation examples, we use this `pr()` function to print in what order things are created and used.
|
|
863
|
+
|
|
864
|
+
```python
|
|
865
|
+
def pr(tag, v):
|
|
866
|
+
print(tag, v)
|
|
867
|
+
return v
|
|
868
|
+
```
|
|
869
|
+
|
|
870
|
+
With eager evaluation, the function creates all three elements up front and stores them in a list before iteration begins. With lazy evaluation, the function returns a generator that creates each element only when it is needed.
|
|
871
|
+
|
|
872
|
+
<table>
|
|
873
|
+
<tr> <td width="50%" valign="top"><strong>Eager</strong></td> <td width="50%" valign="top"><strong>Lazy</strong></td></tr>
|
|
874
|
+
<tr><td width="50%" valign="top">
|
|
875
|
+
|
|
876
|
+
```python
|
|
877
|
+
def fun():
|
|
878
|
+
result = []
|
|
879
|
+
for i in range(3):
|
|
880
|
+
result.append(pr('create:', i))
|
|
881
|
+
return result
|
|
882
|
+
|
|
883
|
+
for i in fun():
|
|
884
|
+
pr('use:', i)
|
|
885
|
+
```
|
|
886
|
+
|
|
887
|
+
Run in [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/eager_return.py&play)
|
|
888
|
+
|
|
889
|
+
</td><td width="50%" valign="top">
|
|
890
|
+
|
|
891
|
+
```python
|
|
892
|
+
def fun():
|
|
893
|
+
for i in range(3):
|
|
894
|
+
yield pr('create:', i)
|
|
895
|
+
|
|
896
|
+
|
|
897
|
+
|
|
898
|
+
for i in fun():
|
|
899
|
+
pr('use:', i)
|
|
900
|
+
```
|
|
901
|
+
|
|
902
|
+
Run in [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/lazy_yield.py&play)
|
|
903
|
+
|
|
904
|
+
</td></tr>
|
|
905
|
+
<tr><td width="50%" valign="top">
|
|
906
|
+
|
|
907
|
+
```python
|
|
908
|
+
def fun():
|
|
909
|
+
return [
|
|
910
|
+
pr('create:', i)
|
|
911
|
+
for i in range(3)
|
|
912
|
+
]
|
|
913
|
+
|
|
914
|
+
for i in fun():
|
|
915
|
+
pr('use:', i)
|
|
916
|
+
```
|
|
917
|
+
|
|
918
|
+
Run in [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/eager_compri.py&play)
|
|
919
|
+
|
|
920
|
+
</td><td width="50%" valign="top">
|
|
921
|
+
|
|
922
|
+
```python
|
|
923
|
+
def fun():
|
|
924
|
+
return (
|
|
925
|
+
pr('create:', i)
|
|
926
|
+
for i in range(3)
|
|
927
|
+
)
|
|
928
|
+
|
|
929
|
+
for i in fun():
|
|
930
|
+
pr('use:', i)
|
|
931
|
+
```
|
|
932
|
+
|
|
933
|
+
Run in [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/lazy_express.py&play)
|
|
934
|
+
|
|
935
|
+
</td></tr>
|
|
936
|
+
<tr><td width="50%" valign="top">
|
|
937
|
+
|
|
938
|
+
```text
|
|
939
|
+
create: 0
|
|
940
|
+
create: 1
|
|
941
|
+
create: 2
|
|
942
|
+
use: 0
|
|
943
|
+
use: 1
|
|
944
|
+
use: 2
|
|
945
|
+
```
|
|
946
|
+
|
|
947
|
+
</td><td width="50%" valign="top">
|
|
948
|
+
|
|
949
|
+
```text
|
|
950
|
+
create: 0
|
|
951
|
+
use: 0
|
|
952
|
+
create: 1
|
|
953
|
+
use: 1
|
|
954
|
+
create: 2
|
|
955
|
+
use: 2
|
|
956
|
+
```
|
|
957
|
+
|
|
958
|
+
</td></tr>
|
|
959
|
+
</table>
|
|
960
|
+
|
|
961
|
+
|
|
857
962
|
# Configuration #
|
|
858
963
|
Different aspects of memory_graph can be configured. The default configuration can be reset by calling 'mg.config_default.reset()'. The Memory Graph Web Debugger gives examples of the [most important configurations](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/config.py&play).
|
|
859
964
|
|
|
@@ -29,10 +29,13 @@ type_to_string = { }
|
|
|
29
29
|
|
|
30
30
|
def to_string(data):
|
|
31
31
|
""" Convert data to string. """
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
try:
|
|
33
|
+
data_type = type(data)
|
|
34
|
+
if data_type in type_to_string:
|
|
35
|
+
return type_to_string[data_type](data)
|
|
36
|
+
return str(data)
|
|
37
|
+
except Exception as e:
|
|
38
|
+
return f'no stringification, {type(e).__name__}: {e}'
|
|
36
39
|
|
|
37
40
|
type_to_node = { }
|
|
38
41
|
|
|
@@ -15,6 +15,7 @@ def get_dict_attributes(value):
|
|
|
15
15
|
return getattr(value,"__dict__")
|
|
16
16
|
|
|
17
17
|
def is_not_state(obj):
|
|
18
|
+
""" Returns 'True' if 'obj' is not considered state, e.g. a function or method. """
|
|
18
19
|
if isinstance(obj, (types.FunctionType, types.MethodType,
|
|
19
20
|
types.BuiltinFunctionType, types.BuiltinMethodType,
|
|
20
21
|
classmethod, staticmethod,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: memory_graph
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.74
|
|
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
|
|
@@ -772,7 +772,6 @@ This example shows the flow of control when using inheritance with:
|
|
|
772
772
|
- class variable `message_count`
|
|
773
773
|
|
|
774
774
|
```python
|
|
775
|
-
from datetime import datetime
|
|
776
775
|
|
|
777
776
|
class Notification_Service:
|
|
778
777
|
message_count = 0
|
|
@@ -810,14 +809,14 @@ class SMS_Notification(Notification_Service):
|
|
|
810
809
|
email = Email_Notification(3, 'support@company.com')
|
|
811
810
|
email.send('customer@email.com', 'Your report is ready')
|
|
812
811
|
email.send('customer@email.com', 'Update to Privacy Policy')
|
|
813
|
-
sms =
|
|
812
|
+
sms = SMS_Notification(3, '0123456789')
|
|
814
813
|
sms.send('001122334455', 'Update to Privacy Policy')
|
|
815
814
|
```
|
|
816
|
-
Run it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/inheritance.py&breakpoints=
|
|
815
|
+
Run it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/inheritance.py&breakpoints=35&continues=1&play).
|
|
817
816
|
|
|
818
817
|
## Decorator ##
|
|
819
818
|
|
|
820
|
-
This example shows the flow of control when using a decorator.
|
|
819
|
+
This example shows the flow of control when using a decorator. A decorator wraps a function and is active before and after the function is called.
|
|
821
820
|
|
|
822
821
|
```python
|
|
823
822
|
def log_call(function):
|
|
@@ -851,29 +850,135 @@ This example shows the flow of control when using exception handling.
|
|
|
851
850
|
def fun2():
|
|
852
851
|
try:
|
|
853
852
|
d = [0] * 3
|
|
854
|
-
for i in range(
|
|
853
|
+
for i in range(6):
|
|
855
854
|
try:
|
|
856
|
-
|
|
857
|
-
|
|
855
|
+
print(f'{i=}')
|
|
856
|
+
d[i] = i # raises IndexError when i>=3
|
|
857
|
+
except ZeroDivisionError as e:
|
|
858
858
|
print(type(e), e)
|
|
859
859
|
except AssertionError as e:
|
|
860
860
|
print(type(e), e)
|
|
861
|
-
|
|
861
|
+
print('fun2() returns')
|
|
862
|
+
|
|
862
863
|
def fun1():
|
|
863
864
|
try:
|
|
864
865
|
return fun2()
|
|
865
866
|
except NameError as e:
|
|
866
867
|
print(type(e), e)
|
|
867
|
-
|
|
868
|
+
print('fun1() returns')
|
|
869
|
+
|
|
868
870
|
try:
|
|
869
871
|
fun1()
|
|
870
872
|
except LookupError as e:
|
|
871
873
|
print(type(e), e)
|
|
874
|
+
print('program ended cleanly')
|
|
872
875
|
```
|
|
873
|
-
Run it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/exceptions.py&breakpoints=
|
|
876
|
+
Run it in the [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/exceptions.py&breakpoints=22&continues=1&play). In the program an `IndexError` exception is raised which propagates up the call stack until it reaches an except clause that matches its type where it is handled. Here, it is handled by the `LookupError` except clause because `IndexError` is a subclass of `LookupError`. Exceptions that are not handled terminate the execution of a program while its traceback is shown for analyses.
|
|
874
877
|
|
|
875
878
|

|
|
876
879
|
|
|
880
|
+
## Lazy Evaluation ##
|
|
881
|
+
|
|
882
|
+
In the following Eager and Lazy ealuation examples, we use this `pr()` function to print in what order things are created and used.
|
|
883
|
+
|
|
884
|
+
```python
|
|
885
|
+
def pr(tag, v):
|
|
886
|
+
print(tag, v)
|
|
887
|
+
return v
|
|
888
|
+
```
|
|
889
|
+
|
|
890
|
+
With eager evaluation, the function creates all three elements up front and stores them in a list before iteration begins. With lazy evaluation, the function returns a generator that creates each element only when it is needed.
|
|
891
|
+
|
|
892
|
+
<table>
|
|
893
|
+
<tr> <td width="50%" valign="top"><strong>Eager</strong></td> <td width="50%" valign="top"><strong>Lazy</strong></td></tr>
|
|
894
|
+
<tr><td width="50%" valign="top">
|
|
895
|
+
|
|
896
|
+
```python
|
|
897
|
+
def fun():
|
|
898
|
+
result = []
|
|
899
|
+
for i in range(3):
|
|
900
|
+
result.append(pr('create:', i))
|
|
901
|
+
return result
|
|
902
|
+
|
|
903
|
+
for i in fun():
|
|
904
|
+
pr('use:', i)
|
|
905
|
+
```
|
|
906
|
+
|
|
907
|
+
Run in [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/eager_return.py&play)
|
|
908
|
+
|
|
909
|
+
</td><td width="50%" valign="top">
|
|
910
|
+
|
|
911
|
+
```python
|
|
912
|
+
def fun():
|
|
913
|
+
for i in range(3):
|
|
914
|
+
yield pr('create:', i)
|
|
915
|
+
|
|
916
|
+
|
|
917
|
+
|
|
918
|
+
for i in fun():
|
|
919
|
+
pr('use:', i)
|
|
920
|
+
```
|
|
921
|
+
|
|
922
|
+
Run in [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/lazy_yield.py&play)
|
|
923
|
+
|
|
924
|
+
</td></tr>
|
|
925
|
+
<tr><td width="50%" valign="top">
|
|
926
|
+
|
|
927
|
+
```python
|
|
928
|
+
def fun():
|
|
929
|
+
return [
|
|
930
|
+
pr('create:', i)
|
|
931
|
+
for i in range(3)
|
|
932
|
+
]
|
|
933
|
+
|
|
934
|
+
for i in fun():
|
|
935
|
+
pr('use:', i)
|
|
936
|
+
```
|
|
937
|
+
|
|
938
|
+
Run in [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/eager_compri.py&play)
|
|
939
|
+
|
|
940
|
+
</td><td width="50%" valign="top">
|
|
941
|
+
|
|
942
|
+
```python
|
|
943
|
+
def fun():
|
|
944
|
+
return (
|
|
945
|
+
pr('create:', i)
|
|
946
|
+
for i in range(3)
|
|
947
|
+
)
|
|
948
|
+
|
|
949
|
+
for i in fun():
|
|
950
|
+
pr('use:', i)
|
|
951
|
+
```
|
|
952
|
+
|
|
953
|
+
Run in [Memory Graph Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/lazy_express.py&play)
|
|
954
|
+
|
|
955
|
+
</td></tr>
|
|
956
|
+
<tr><td width="50%" valign="top">
|
|
957
|
+
|
|
958
|
+
```text
|
|
959
|
+
create: 0
|
|
960
|
+
create: 1
|
|
961
|
+
create: 2
|
|
962
|
+
use: 0
|
|
963
|
+
use: 1
|
|
964
|
+
use: 2
|
|
965
|
+
```
|
|
966
|
+
|
|
967
|
+
</td><td width="50%" valign="top">
|
|
968
|
+
|
|
969
|
+
```text
|
|
970
|
+
create: 0
|
|
971
|
+
use: 0
|
|
972
|
+
create: 1
|
|
973
|
+
use: 1
|
|
974
|
+
create: 2
|
|
975
|
+
use: 2
|
|
976
|
+
```
|
|
977
|
+
|
|
978
|
+
</td></tr>
|
|
979
|
+
</table>
|
|
980
|
+
|
|
981
|
+
|
|
877
982
|
# Configuration #
|
|
878
983
|
Different aspects of memory_graph can be configured. The default configuration can be reset by calling 'mg.config_default.reset()'. The Memory Graph Web Debugger gives examples of the [most important configurations](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/config.py&play).
|
|
879
984
|
|
|
@@ -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.74"
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|