invocation-tree 0.0.11__tar.gz → 0.0.12__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.
- {invocation_tree-0.0.11/invocation_tree.egg-info → invocation_tree-0.0.12}/PKG-INFO +19 -19
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/README.md +18 -18
- invocation_tree-0.0.12/images/#generator_function.py# +13 -0
- invocation_tree-0.0.12/images/compute.py +22 -0
- invocation_tree-0.0.11/images/compute.py → invocation_tree-0.0.12/images/compute.py~ +3 -3
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/compute1.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/compute2.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/compute3.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/compute4.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/compute5.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/compute6.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/compute7.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/compute8.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/compute9.png +0 -0
- invocation_tree-0.0.12/images/create_images.sh~ +4 -0
- invocation_tree-0.0.12/images/eager_pipeline.py~ +28 -0
- invocation_tree-0.0.12/images/eager_pipeline1.png +0 -0
- invocation_tree-0.0.12/images/eager_pipeline2.png +0 -0
- invocation_tree-0.0.12/images/eager_pipeline3.png +0 -0
- invocation_tree-0.0.12/images/eager_pipeline4.png +0 -0
- invocation_tree-0.0.12/images/eager_pipeline5.png +0 -0
- invocation_tree-0.0.12/images/eager_pipeline6.png +0 -0
- invocation_tree-0.0.12/images/eager_pipeline7.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/factorial.py +2 -2
- invocation_tree-0.0.12/images/factorial.py~ +11 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/factorial1.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/factorial2.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/factorial3.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/factorial4.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/factorial5.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/factorial6.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/factorial7.png +0 -0
- invocation_tree-0.0.12/images/generator_expression.py~ +9 -0
- invocation_tree-0.0.12/images/generator_expression1.png +0 -0
- invocation_tree-0.0.12/images/generator_expression2.png +0 -0
- invocation_tree-0.0.12/images/generator_expression3.png +0 -0
- invocation_tree-0.0.12/images/generator_expression4.png +0 -0
- invocation_tree-0.0.12/images/generator_expression5.png +0 -0
- invocation_tree-0.0.12/images/generator_expression6.png +0 -0
- invocation_tree-0.0.12/images/generator_expression7.png +0 -0
- invocation_tree-0.0.12/images/generator_expression8.png +0 -0
- invocation_tree-0.0.12/images/generator_expression9.png +0 -0
- invocation_tree-0.0.12/images/generator_function1.png +0 -0
- invocation_tree-0.0.12/images/generator_function2.png +0 -0
- invocation_tree-0.0.12/images/generator_function3.png +0 -0
- invocation_tree-0.0.12/images/generator_function4.png +0 -0
- invocation_tree-0.0.12/images/generator_function5.png +0 -0
- invocation_tree-0.0.12/images/generator_function6.png +0 -0
- invocation_tree-0.0.12/images/generator_function7.png +0 -0
- invocation_tree-0.0.12/images/generator_function8.png +0 -0
- invocation_tree-0.0.12/images/generator_function9.png +0 -0
- invocation_tree-0.0.12/images/generator_pipeline.py~ +26 -0
- invocation_tree-0.0.12/images/generator_pipeline1.png +0 -0
- invocation_tree-0.0.12/images/generator_pipeline10.png +0 -0
- invocation_tree-0.0.12/images/generator_pipeline11.png +0 -0
- invocation_tree-0.0.12/images/generator_pipeline12.png +0 -0
- invocation_tree-0.0.12/images/generator_pipeline13.png +0 -0
- invocation_tree-0.0.12/images/generator_pipeline14.png +0 -0
- invocation_tree-0.0.12/images/generator_pipeline15.png +0 -0
- invocation_tree-0.0.12/images/generator_pipeline16.png +0 -0
- invocation_tree-0.0.12/images/generator_pipeline17.png +0 -0
- invocation_tree-0.0.12/images/generator_pipeline18.png +0 -0
- invocation_tree-0.0.12/images/generator_pipeline19.png +0 -0
- invocation_tree-0.0.12/images/generator_pipeline2.png +0 -0
- invocation_tree-0.0.12/images/generator_pipeline20.png +0 -0
- invocation_tree-0.0.12/images/generator_pipeline21.png +0 -0
- invocation_tree-0.0.12/images/generator_pipeline22.png +0 -0
- invocation_tree-0.0.12/images/generator_pipeline23.png +0 -0
- invocation_tree-0.0.12/images/generator_pipeline24.png +0 -0
- invocation_tree-0.0.12/images/generator_pipeline25.png +0 -0
- invocation_tree-0.0.12/images/generator_pipeline26.png +0 -0
- invocation_tree-0.0.12/images/generator_pipeline27.png +0 -0
- invocation_tree-0.0.12/images/generator_pipeline3.png +0 -0
- invocation_tree-0.0.12/images/generator_pipeline4.png +0 -0
- invocation_tree-0.0.12/images/generator_pipeline5.png +0 -0
- invocation_tree-0.0.12/images/generator_pipeline6.png +0 -0
- invocation_tree-0.0.12/images/generator_pipeline7.png +0 -0
- invocation_tree-0.0.12/images/generator_pipeline8.png +0 -0
- invocation_tree-0.0.12/images/generator_pipeline9.png +0 -0
- invocation_tree-0.0.12/images/invocation_tree.pdf +0 -0
- invocation_tree-0.0.12/images/invocation_tree0.pdf +0 -0
- invocation_tree-0.0.12/images/iterable.py +44 -0
- invocation_tree-0.0.12/images/iterable.py~ +31 -0
- invocation_tree-0.0.12/images/my_list.py +20 -0
- invocation_tree-0.0.12/images/my_list.py~ +4 -0
- invocation_tree-0.0.12/images/my_range.py~ +14 -0
- invocation_tree-0.0.12/images/my_range0.png +0 -0
- invocation_tree-0.0.12/images/my_range1.png +0 -0
- invocation_tree-0.0.12/images/my_range10.png +0 -0
- invocation_tree-0.0.12/images/my_range11.png +0 -0
- invocation_tree-0.0.12/images/my_range12.png +0 -0
- invocation_tree-0.0.12/images/my_range13.png +0 -0
- invocation_tree-0.0.12/images/my_range14.png +0 -0
- invocation_tree-0.0.12/images/my_range15.png +0 -0
- invocation_tree-0.0.12/images/my_range2.png +0 -0
- invocation_tree-0.0.12/images/my_range3.png +0 -0
- invocation_tree-0.0.12/images/my_range4.png +0 -0
- invocation_tree-0.0.12/images/my_range5.png +0 -0
- invocation_tree-0.0.12/images/my_range6.png +0 -0
- invocation_tree-0.0.12/images/my_range7.png +0 -0
- invocation_tree-0.0.12/images/my_range8.png +0 -0
- invocation_tree-0.0.12/images/my_range9.png +0 -0
- invocation_tree-0.0.12/images/out.txt +8 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/permutations.py +2 -2
- invocation_tree-0.0.12/images/permutations.py~ +8 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/permutations1.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/permutations10.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/permutations11.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/permutations12.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/permutations13.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/permutations2.png +0 -0
- invocation_tree-0.0.12/images/permutations22.png~ +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/permutations3.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/permutations4.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/permutations5.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/permutations6.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/permutations7.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/permutations8.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/permutations9.png +0 -0
- invocation_tree-0.0.12/images/student.gif +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/students.py +2 -2
- invocation_tree-0.0.12/images/students.py~ +30 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/students1.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/students10.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/students11.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/students12.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/students13.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/students14.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/students15.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/students2.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/students3.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/students4.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/students5.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/students6.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/students7.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/students8.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/students9.png +0 -0
- invocation_tree-0.0.12/images/test.py +15 -0
- invocation_tree-0.0.12/images/tree.gv~ +22 -0
- invocation_tree-0.0.12/images/tree.pdf +0 -0
- invocation_tree-0.0.12/install.txt +31 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/invocation_tree/__init__.py +1 -1
- {invocation_tree-0.0.11 → invocation_tree-0.0.12/invocation_tree.egg-info}/PKG-INFO +19 -19
- invocation_tree-0.0.12/invocation_tree.egg-info/SOURCES.txt +156 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/setup.py +1 -1
- invocation_tree-0.0.11/invocation_tree.egg-info/SOURCES.txt +0 -65
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/LICENSE.txt +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/MANIFEST.in +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/compute.gif +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/create_gif.sh +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/create_images.sh +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/factorial.gif +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/permutations.gif +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/students.gif +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/images/vscode.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/invocation_tree.egg-info/dependency_links.txt +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/invocation_tree.egg-info/requires.txt +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/invocation_tree.egg-info/top_level.txt +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.12}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: invocation_tree
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.12
|
|
4
4
|
Summary: Generate an invocation tree of functions calls.
|
|
5
5
|
Home-page: https://github.com/bterwijn/invocation_tree
|
|
6
6
|
Author: Bas Terwijn
|
|
@@ -32,7 +32,7 @@ The [invocation_tree](https://pypi.org/project/invocation-tree/) package is desi
|
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
```python
|
|
35
|
-
import invocation_tree as
|
|
35
|
+
import invocation_tree as ivt
|
|
36
36
|
|
|
37
37
|
def main():
|
|
38
38
|
a = 1
|
|
@@ -52,7 +52,7 @@ def add(a, b):
|
|
|
52
52
|
def multiply(a, b):
|
|
53
53
|
return a * b
|
|
54
54
|
|
|
55
|
-
tree =
|
|
55
|
+
tree = ivt.blocking()
|
|
56
56
|
print( tree(main) ) # show invocation tree starting at main
|
|
57
57
|
```
|
|
58
58
|
Running the program and pressing <Enter> a number of times results in:
|
|
@@ -96,7 +96,7 @@ ___
|
|
|
96
96
|
In this more interesting example we compute which students pass a course by using list and dictionary comprehensions.
|
|
97
97
|
|
|
98
98
|
```python
|
|
99
|
-
import invocation_tree as
|
|
99
|
+
import invocation_tree as ivt
|
|
100
100
|
from decimal import Decimal, ROUND_HALF_UP
|
|
101
101
|
|
|
102
102
|
def main():
|
|
@@ -123,7 +123,7 @@ def passing_students(averages):
|
|
|
123
123
|
if average >= 5.5]
|
|
124
124
|
|
|
125
125
|
if __name__ == '__main__':
|
|
126
|
-
tree =
|
|
126
|
+
tree = ivt.blocking()
|
|
127
127
|
tree(main)
|
|
128
128
|
```
|
|
129
129
|

|
|
@@ -135,14 +135,14 @@ if __name__ == '__main__':
|
|
|
135
135
|
The program blocks execution at every function call and return statement, printing the current location in the source code. Press the <Enter> key to continue execution. To block at every line of the program (like in a debugger tool) and only where a change of value occured, use instead:
|
|
136
136
|
|
|
137
137
|
```python
|
|
138
|
-
tree =
|
|
138
|
+
tree = ivt.blocking_each_change()
|
|
139
139
|
```
|
|
140
140
|
|
|
141
141
|
# Debugger #
|
|
142
142
|
To visualize the invocation tree in a debugger tool, such as the integrated debugger in Visual Studio Code, use instead:
|
|
143
143
|
|
|
144
144
|
```python
|
|
145
|
-
tree =
|
|
145
|
+
tree = ivt.debugger()
|
|
146
146
|
```
|
|
147
147
|
|
|
148
148
|
and open the 'tree.pdf' file manually.
|
|
@@ -152,14 +152,14 @@ and open the 'tree.pdf' file manually.
|
|
|
152
152
|
An invocation tree is particularly helpful to better understand recursion. A simple `factorial()` example:
|
|
153
153
|
|
|
154
154
|
```python
|
|
155
|
-
import invocation_tree as
|
|
155
|
+
import invocation_tree as ivt
|
|
156
156
|
|
|
157
157
|
def factorial(n):
|
|
158
158
|
if n <= 1:
|
|
159
159
|
return 1
|
|
160
160
|
return n * factorial(n - 1)
|
|
161
161
|
|
|
162
|
-
tree =
|
|
162
|
+
tree = ivt.blocking()
|
|
163
163
|
print( tree(factorial, 4) ) # show invocation tree of calling factorial(4)
|
|
164
164
|
```
|
|
165
165
|

|
|
@@ -170,7 +170,7 @@ print( tree(factorial, 4) ) # show invocation tree of calling factorial(4)
|
|
|
170
170
|
This `permutations()` example shows the depth-first nature of recursive execution:
|
|
171
171
|
|
|
172
172
|
```python
|
|
173
|
-
import invocation_tree as
|
|
173
|
+
import invocation_tree as ivt
|
|
174
174
|
|
|
175
175
|
def permutations(elements, perm, n):
|
|
176
176
|
if n==0:
|
|
@@ -180,7 +180,7 @@ def permutations(elements, perm, n):
|
|
|
180
180
|
all_perms.extend(permutations(elements, perm + element, n-1))
|
|
181
181
|
return all_perms
|
|
182
182
|
|
|
183
|
-
tree =
|
|
183
|
+
tree = ivt.blocking()
|
|
184
184
|
result = tree(permutations, ['L','R'], '', 2)
|
|
185
185
|
print(result) # all permutations of going Left or Right of length 2
|
|
186
186
|
```
|
|
@@ -193,7 +193,7 @@ print(result) # all permutations of going Left or Right of length 2
|
|
|
193
193
|
In an educational context it can be useful to hide certian variables to avoid unnecessary complexity. This can for example be done with:
|
|
194
194
|
|
|
195
195
|
```python
|
|
196
|
-
tree =
|
|
196
|
+
tree = ivt.blocking()
|
|
197
197
|
tree.hide.add('permutations.elements')
|
|
198
198
|
tree.hide.add('permutations.element')
|
|
199
199
|
tree.hide.add('permutations.all_perms')
|
|
@@ -203,7 +203,7 @@ tree.hide.add('permutations.all_perms')
|
|
|
203
203
|
These invocation_tree configurations are available for an `Invocation_Tree` objects:
|
|
204
204
|
|
|
205
205
|
```python
|
|
206
|
-
tree =
|
|
206
|
+
tree = ivt.Invocation_Tree()
|
|
207
207
|
```
|
|
208
208
|
|
|
209
209
|
- **tree.filename** : str
|
|
@@ -235,12 +235,12 @@ tree = invo_tree.Invocation_Tree()
|
|
|
235
235
|
|
|
236
236
|
For convenience we provide these functions to set common configurations:
|
|
237
237
|
|
|
238
|
-
- **
|
|
239
|
-
- **
|
|
240
|
-
- **
|
|
241
|
-
- **
|
|
242
|
-
- **
|
|
243
|
-
- **
|
|
238
|
+
- **ivt.blocking(filename)**, blocks on function call and return
|
|
239
|
+
- **ivt.blocking_each_change(filename)**, blocks on each change of value
|
|
240
|
+
- **ivt.debugger(filename)**, non-blocking for use in debugger tool (open <filename> manually)
|
|
241
|
+
- **ivt.gif(filename)**, generates many output files on function call and return for gif creation
|
|
242
|
+
- **ivt.gif_each_change(filename)**, generates many output files on each change of value for gif creation
|
|
243
|
+
- **ivt.non_blocking(filename)**, non-blocking on each function call and return
|
|
244
244
|
|
|
245
245
|
# Troubleshooting #
|
|
246
246
|
- Adobe Acrobat Reader [doesn't refresh a PDF file](https://superuser.com/questions/337011/windows-pdf-viewer-that-auto-refreshes-pdf-when-compiling-with-pdflatex) when it changes on disk and blocks updates which results in an `Could not open 'somefile.pdf' for writing : Permission denied` error. One solution is to install a PDF reader that does refresh ([Evince](https://www.fosshub.com/Evince.html), [Okular](https://okular.kde.org/), [SumatraPDF](https://www.sumatrapdfreader.org/), ...) and set it as the default PDF reader. Another solution is to save the tree to a different [Graphviz Output Format](https://graphviz.org/docs/outputs/).
|
|
@@ -13,7 +13,7 @@ The [invocation_tree](https://pypi.org/project/invocation-tree/) package is desi
|
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
```python
|
|
16
|
-
import invocation_tree as
|
|
16
|
+
import invocation_tree as ivt
|
|
17
17
|
|
|
18
18
|
def main():
|
|
19
19
|
a = 1
|
|
@@ -33,7 +33,7 @@ def add(a, b):
|
|
|
33
33
|
def multiply(a, b):
|
|
34
34
|
return a * b
|
|
35
35
|
|
|
36
|
-
tree =
|
|
36
|
+
tree = ivt.blocking()
|
|
37
37
|
print( tree(main) ) # show invocation tree starting at main
|
|
38
38
|
```
|
|
39
39
|
Running the program and pressing <Enter> a number of times results in:
|
|
@@ -77,7 +77,7 @@ ___
|
|
|
77
77
|
In this more interesting example we compute which students pass a course by using list and dictionary comprehensions.
|
|
78
78
|
|
|
79
79
|
```python
|
|
80
|
-
import invocation_tree as
|
|
80
|
+
import invocation_tree as ivt
|
|
81
81
|
from decimal import Decimal, ROUND_HALF_UP
|
|
82
82
|
|
|
83
83
|
def main():
|
|
@@ -104,7 +104,7 @@ def passing_students(averages):
|
|
|
104
104
|
if average >= 5.5]
|
|
105
105
|
|
|
106
106
|
if __name__ == '__main__':
|
|
107
|
-
tree =
|
|
107
|
+
tree = ivt.blocking()
|
|
108
108
|
tree(main)
|
|
109
109
|
```
|
|
110
110
|

|
|
@@ -116,14 +116,14 @@ if __name__ == '__main__':
|
|
|
116
116
|
The program blocks execution at every function call and return statement, printing the current location in the source code. Press the <Enter> key to continue execution. To block at every line of the program (like in a debugger tool) and only where a change of value occured, use instead:
|
|
117
117
|
|
|
118
118
|
```python
|
|
119
|
-
tree =
|
|
119
|
+
tree = ivt.blocking_each_change()
|
|
120
120
|
```
|
|
121
121
|
|
|
122
122
|
# Debugger #
|
|
123
123
|
To visualize the invocation tree in a debugger tool, such as the integrated debugger in Visual Studio Code, use instead:
|
|
124
124
|
|
|
125
125
|
```python
|
|
126
|
-
tree =
|
|
126
|
+
tree = ivt.debugger()
|
|
127
127
|
```
|
|
128
128
|
|
|
129
129
|
and open the 'tree.pdf' file manually.
|
|
@@ -133,14 +133,14 @@ and open the 'tree.pdf' file manually.
|
|
|
133
133
|
An invocation tree is particularly helpful to better understand recursion. A simple `factorial()` example:
|
|
134
134
|
|
|
135
135
|
```python
|
|
136
|
-
import invocation_tree as
|
|
136
|
+
import invocation_tree as ivt
|
|
137
137
|
|
|
138
138
|
def factorial(n):
|
|
139
139
|
if n <= 1:
|
|
140
140
|
return 1
|
|
141
141
|
return n * factorial(n - 1)
|
|
142
142
|
|
|
143
|
-
tree =
|
|
143
|
+
tree = ivt.blocking()
|
|
144
144
|
print( tree(factorial, 4) ) # show invocation tree of calling factorial(4)
|
|
145
145
|
```
|
|
146
146
|

|
|
@@ -151,7 +151,7 @@ print( tree(factorial, 4) ) # show invocation tree of calling factorial(4)
|
|
|
151
151
|
This `permutations()` example shows the depth-first nature of recursive execution:
|
|
152
152
|
|
|
153
153
|
```python
|
|
154
|
-
import invocation_tree as
|
|
154
|
+
import invocation_tree as ivt
|
|
155
155
|
|
|
156
156
|
def permutations(elements, perm, n):
|
|
157
157
|
if n==0:
|
|
@@ -161,7 +161,7 @@ def permutations(elements, perm, n):
|
|
|
161
161
|
all_perms.extend(permutations(elements, perm + element, n-1))
|
|
162
162
|
return all_perms
|
|
163
163
|
|
|
164
|
-
tree =
|
|
164
|
+
tree = ivt.blocking()
|
|
165
165
|
result = tree(permutations, ['L','R'], '', 2)
|
|
166
166
|
print(result) # all permutations of going Left or Right of length 2
|
|
167
167
|
```
|
|
@@ -174,7 +174,7 @@ print(result) # all permutations of going Left or Right of length 2
|
|
|
174
174
|
In an educational context it can be useful to hide certian variables to avoid unnecessary complexity. This can for example be done with:
|
|
175
175
|
|
|
176
176
|
```python
|
|
177
|
-
tree =
|
|
177
|
+
tree = ivt.blocking()
|
|
178
178
|
tree.hide.add('permutations.elements')
|
|
179
179
|
tree.hide.add('permutations.element')
|
|
180
180
|
tree.hide.add('permutations.all_perms')
|
|
@@ -184,7 +184,7 @@ tree.hide.add('permutations.all_perms')
|
|
|
184
184
|
These invocation_tree configurations are available for an `Invocation_Tree` objects:
|
|
185
185
|
|
|
186
186
|
```python
|
|
187
|
-
tree =
|
|
187
|
+
tree = ivt.Invocation_Tree()
|
|
188
188
|
```
|
|
189
189
|
|
|
190
190
|
- **tree.filename** : str
|
|
@@ -216,12 +216,12 @@ tree = invo_tree.Invocation_Tree()
|
|
|
216
216
|
|
|
217
217
|
For convenience we provide these functions to set common configurations:
|
|
218
218
|
|
|
219
|
-
- **
|
|
220
|
-
- **
|
|
221
|
-
- **
|
|
222
|
-
- **
|
|
223
|
-
- **
|
|
224
|
-
- **
|
|
219
|
+
- **ivt.blocking(filename)**, blocks on function call and return
|
|
220
|
+
- **ivt.blocking_each_change(filename)**, blocks on each change of value
|
|
221
|
+
- **ivt.debugger(filename)**, non-blocking for use in debugger tool (open <filename> manually)
|
|
222
|
+
- **ivt.gif(filename)**, generates many output files on function call and return for gif creation
|
|
223
|
+
- **ivt.gif_each_change(filename)**, generates many output files on each change of value for gif creation
|
|
224
|
+
- **ivt.non_blocking(filename)**, non-blocking on each function call and return
|
|
225
225
|
|
|
226
226
|
# Troubleshooting #
|
|
227
227
|
- Adobe Acrobat Reader [doesn't refresh a PDF file](https://superuser.com/questions/337011/windows-pdf-viewer-that-auto-refreshes-pdf-when-compiling-with-pdflatex) when it changes on disk and blocks updates which results in an `Could not open 'somefile.pdf' for writing : Permission denied` error. One solution is to install a PDF reader that does refresh ([Evince](https://www.fosshub.com/Evince.html), [Okular](https://okular.kde.org/), [SumatraPDF](https://www.sumatrapdfreader.org/), ...) and set it as the default PDF reader. Another solution is to save the tree to a different [Graphviz Output Format](https://graphviz.org/docs/outputs/).
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import invocation_tree as ivt
|
|
2
|
+
|
|
3
|
+
def main():
|
|
4
|
+
a = 1
|
|
5
|
+
a = expression(a)
|
|
6
|
+
return multiply(a, 6)
|
|
7
|
+
|
|
8
|
+
def expression(a):
|
|
9
|
+
a = subtract(a, 3)
|
|
10
|
+
return add(a, 9)
|
|
11
|
+
|
|
12
|
+
def subtract(a, b):
|
|
13
|
+
return a - b
|
|
14
|
+
|
|
15
|
+
def add(a, b):
|
|
16
|
+
return a + b
|
|
17
|
+
|
|
18
|
+
def multiply(a, b):
|
|
19
|
+
return a * b
|
|
20
|
+
|
|
21
|
+
tree = ivt.gif('compute.png')
|
|
22
|
+
print( tree(main) )
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import invocation_tree as invo_tree
|
|
2
2
|
|
|
3
3
|
def main():
|
|
4
|
-
a =
|
|
4
|
+
a = 10
|
|
5
5
|
a = expression(a)
|
|
6
6
|
return multiply(a, 6)
|
|
7
7
|
|
|
8
8
|
def expression(a):
|
|
9
|
-
a = subtract(a,
|
|
10
|
-
return add(a,
|
|
9
|
+
a = subtract(a, 5)
|
|
10
|
+
return add(a, 2)
|
|
11
11
|
|
|
12
12
|
def subtract(a, b):
|
|
13
13
|
return a - b
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import invocation_tree as invo_tree
|
|
2
|
+
|
|
3
|
+
def subtract(pipeline):
|
|
4
|
+
for a in pipeline:
|
|
5
|
+
yield a - 3
|
|
6
|
+
|
|
7
|
+
def multiply(pipeline):
|
|
8
|
+
for a in pipeline:
|
|
9
|
+
yield a * 6
|
|
10
|
+
|
|
11
|
+
def my_sum(pipeline):
|
|
12
|
+
total = 0
|
|
13
|
+
for i in pipeline:
|
|
14
|
+
total += i
|
|
15
|
+
return total # return not yield, so not lazy
|
|
16
|
+
|
|
17
|
+
def main():
|
|
18
|
+
pipeline = range(1,4)
|
|
19
|
+
pipeline = subtract(pipeline)
|
|
20
|
+
pipeline = (a + 9 for a in pipeline)
|
|
21
|
+
pipeline = multiply(pipeline)
|
|
22
|
+
return my_sum(pipeline)
|
|
23
|
+
|
|
24
|
+
tree = invo_tree.blocking()
|
|
25
|
+
import types
|
|
26
|
+
tree.to_string[types.GeneratorType] = lambda x: 'generator' # short name for generators
|
|
27
|
+
tree.to_string[type(iter(range(0)))] = lambda x: 'iterator' # short name for iterator
|
|
28
|
+
print( tree(main) )
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import invocation_tree as invo_tree
|
|
2
|
+
|
|
3
|
+
def subtract(pipeline):
|
|
4
|
+
for a in pipeline:
|
|
5
|
+
yield a - 7
|
|
6
|
+
|
|
7
|
+
def add(pipeline):
|
|
8
|
+
for a in pipeline:
|
|
9
|
+
yield a + 2
|
|
10
|
+
|
|
11
|
+
def multiply(pipeline):
|
|
12
|
+
for a in pipeline:
|
|
13
|
+
yield a * 6
|
|
14
|
+
|
|
15
|
+
def main():
|
|
16
|
+
pipeline = range(1,4)
|
|
17
|
+
pipeline = subtract(pipeline)
|
|
18
|
+
pipeline = (a+2 for a in pipeline)
|
|
19
|
+
pipeline = multiply(pipeline)
|
|
20
|
+
return list(pipeline)
|
|
21
|
+
|
|
22
|
+
tree = invo_tree.blocking() # gif('generator_pipeline.png')
|
|
23
|
+
import types
|
|
24
|
+
tree.to_string[types.GeneratorType] = lambda x: 'generator' # short name for generators
|
|
25
|
+
tree.to_string[type(iter(range(0)))] = lambda x: 'range_iterator' # short name for range_iterator
|
|
26
|
+
print( tree(main) )
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import invocation_tree as ivt
|
|
2
|
+
|
|
3
|
+
class My_Iterator:
|
|
4
|
+
|
|
5
|
+
def __init__(self, my_iterable):
|
|
6
|
+
self.value = my_iterable.start
|
|
7
|
+
self.my_iterable = my_iterable
|
|
8
|
+
|
|
9
|
+
def __repr__(self):
|
|
10
|
+
return f'My_Iterator value:{self.value}'
|
|
11
|
+
|
|
12
|
+
def __next__(self):
|
|
13
|
+
prev = self.value
|
|
14
|
+
self.value += self.my_iterable.step
|
|
15
|
+
if prev < self.my_iterable.stop:
|
|
16
|
+
return prev
|
|
17
|
+
raise StopIteration()
|
|
18
|
+
|
|
19
|
+
class My_Iterable:
|
|
20
|
+
|
|
21
|
+
def __init__(self, stop, start=0, step=1):
|
|
22
|
+
self.stop = stop
|
|
23
|
+
self.step = step
|
|
24
|
+
self.start = start
|
|
25
|
+
print('self:',self)
|
|
26
|
+
|
|
27
|
+
def __repr__(self):
|
|
28
|
+
return f'My_Iterable start:{self.start} stop:{self.stop} step:{self.step}'
|
|
29
|
+
|
|
30
|
+
def __iter__(self):
|
|
31
|
+
return My_Iterator(self)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def main():
|
|
35
|
+
iterable = My_Iterable(start=1, stop=3)
|
|
36
|
+
for i in iterable:
|
|
37
|
+
print(i)
|
|
38
|
+
|
|
39
|
+
tree = ivt.blocking() # gif('genexp.png')
|
|
40
|
+
#tree.to_string[type(iter(range(0)))] = lambda ri: 'iterator' # short name for iterator
|
|
41
|
+
#tree.to_string[types.GeneratorType] = lambda gen: 'generator' # short name for generators
|
|
42
|
+
tree.cleanup = False
|
|
43
|
+
print('sum:', tree(main))
|
|
44
|
+
#print('sum:', main())
|