invocation-tree 0.0.11__tar.gz → 0.0.13__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.13}/PKG-INFO +21 -20
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/README.md +20 -19
- invocation_tree-0.0.13/images/#generator_function.py# +13 -0
- invocation_tree-0.0.13/images/compute.py +22 -0
- invocation_tree-0.0.11/images/compute.py → invocation_tree-0.0.13/images/compute.py~ +3 -3
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/compute1.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/compute2.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/compute3.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/compute4.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/compute5.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/compute6.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/compute7.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/compute8.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/compute9.png +0 -0
- invocation_tree-0.0.13/images/create_images.sh~ +4 -0
- invocation_tree-0.0.13/images/eager_pipeline.py~ +28 -0
- invocation_tree-0.0.13/images/eager_pipeline1.png +0 -0
- invocation_tree-0.0.13/images/eager_pipeline2.png +0 -0
- invocation_tree-0.0.13/images/eager_pipeline3.png +0 -0
- invocation_tree-0.0.13/images/eager_pipeline4.png +0 -0
- invocation_tree-0.0.13/images/eager_pipeline5.png +0 -0
- invocation_tree-0.0.13/images/eager_pipeline6.png +0 -0
- invocation_tree-0.0.13/images/eager_pipeline7.png +0 -0
- invocation_tree-0.0.13/images/factorial.gif +0 -0
- invocation_tree-0.0.13/images/factorial.py +10 -0
- invocation_tree-0.0.13/images/factorial.py~ +11 -0
- invocation_tree-0.0.13/images/factorial1.png +0 -0
- invocation_tree-0.0.13/images/factorial2.png +0 -0
- invocation_tree-0.0.13/images/factorial3.png +0 -0
- invocation_tree-0.0.13/images/factorial4.png +0 -0
- invocation_tree-0.0.13/images/factorial5.png +0 -0
- invocation_tree-0.0.13/images/factorial6.png +0 -0
- invocation_tree-0.0.13/images/factorial7.png +0 -0
- invocation_tree-0.0.13/images/generator_expression.py~ +9 -0
- invocation_tree-0.0.13/images/generator_expression1.png +0 -0
- invocation_tree-0.0.13/images/generator_expression2.png +0 -0
- invocation_tree-0.0.13/images/generator_expression3.png +0 -0
- invocation_tree-0.0.13/images/generator_expression4.png +0 -0
- invocation_tree-0.0.13/images/generator_expression5.png +0 -0
- invocation_tree-0.0.13/images/generator_expression6.png +0 -0
- invocation_tree-0.0.13/images/generator_expression7.png +0 -0
- invocation_tree-0.0.13/images/generator_expression8.png +0 -0
- invocation_tree-0.0.13/images/generator_expression9.png +0 -0
- invocation_tree-0.0.13/images/generator_function1.png +0 -0
- invocation_tree-0.0.13/images/generator_function2.png +0 -0
- invocation_tree-0.0.13/images/generator_function3.png +0 -0
- invocation_tree-0.0.13/images/generator_function4.png +0 -0
- invocation_tree-0.0.13/images/generator_function5.png +0 -0
- invocation_tree-0.0.13/images/generator_function6.png +0 -0
- invocation_tree-0.0.13/images/generator_function7.png +0 -0
- invocation_tree-0.0.13/images/generator_function8.png +0 -0
- invocation_tree-0.0.13/images/generator_function9.png +0 -0
- invocation_tree-0.0.13/images/generator_pipeline.py~ +26 -0
- invocation_tree-0.0.13/images/generator_pipeline1.png +0 -0
- invocation_tree-0.0.13/images/generator_pipeline10.png +0 -0
- invocation_tree-0.0.13/images/generator_pipeline11.png +0 -0
- invocation_tree-0.0.13/images/generator_pipeline12.png +0 -0
- invocation_tree-0.0.13/images/generator_pipeline13.png +0 -0
- invocation_tree-0.0.13/images/generator_pipeline14.png +0 -0
- invocation_tree-0.0.13/images/generator_pipeline15.png +0 -0
- invocation_tree-0.0.13/images/generator_pipeline16.png +0 -0
- invocation_tree-0.0.13/images/generator_pipeline17.png +0 -0
- invocation_tree-0.0.13/images/generator_pipeline18.png +0 -0
- invocation_tree-0.0.13/images/generator_pipeline19.png +0 -0
- invocation_tree-0.0.13/images/generator_pipeline2.png +0 -0
- invocation_tree-0.0.13/images/generator_pipeline20.png +0 -0
- invocation_tree-0.0.13/images/generator_pipeline21.png +0 -0
- invocation_tree-0.0.13/images/generator_pipeline22.png +0 -0
- invocation_tree-0.0.13/images/generator_pipeline23.png +0 -0
- invocation_tree-0.0.13/images/generator_pipeline24.png +0 -0
- invocation_tree-0.0.13/images/generator_pipeline25.png +0 -0
- invocation_tree-0.0.13/images/generator_pipeline26.png +0 -0
- invocation_tree-0.0.13/images/generator_pipeline27.png +0 -0
- invocation_tree-0.0.13/images/generator_pipeline3.png +0 -0
- invocation_tree-0.0.13/images/generator_pipeline4.png +0 -0
- invocation_tree-0.0.13/images/generator_pipeline5.png +0 -0
- invocation_tree-0.0.13/images/generator_pipeline6.png +0 -0
- invocation_tree-0.0.13/images/generator_pipeline7.png +0 -0
- invocation_tree-0.0.13/images/generator_pipeline8.png +0 -0
- invocation_tree-0.0.13/images/generator_pipeline9.png +0 -0
- invocation_tree-0.0.13/images/invocation_tree.pdf +0 -0
- invocation_tree-0.0.13/images/invocation_tree0.pdf +0 -0
- invocation_tree-0.0.13/images/iterable.py +44 -0
- invocation_tree-0.0.13/images/iterable.py~ +31 -0
- invocation_tree-0.0.13/images/my_list.py +20 -0
- invocation_tree-0.0.13/images/my_list.py~ +4 -0
- invocation_tree-0.0.13/images/my_range.py~ +14 -0
- invocation_tree-0.0.13/images/my_range0.png +0 -0
- invocation_tree-0.0.13/images/my_range1.png +0 -0
- invocation_tree-0.0.13/images/my_range10.png +0 -0
- invocation_tree-0.0.13/images/my_range11.png +0 -0
- invocation_tree-0.0.13/images/my_range12.png +0 -0
- invocation_tree-0.0.13/images/my_range13.png +0 -0
- invocation_tree-0.0.13/images/my_range14.png +0 -0
- invocation_tree-0.0.13/images/my_range15.png +0 -0
- invocation_tree-0.0.13/images/my_range2.png +0 -0
- invocation_tree-0.0.13/images/my_range3.png +0 -0
- invocation_tree-0.0.13/images/my_range4.png +0 -0
- invocation_tree-0.0.13/images/my_range5.png +0 -0
- invocation_tree-0.0.13/images/my_range6.png +0 -0
- invocation_tree-0.0.13/images/my_range7.png +0 -0
- invocation_tree-0.0.13/images/my_range8.png +0 -0
- invocation_tree-0.0.13/images/my_range9.png +0 -0
- invocation_tree-0.0.13/images/out.txt +8 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/permutations.py +2 -2
- invocation_tree-0.0.13/images/permutations.py~ +8 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/permutations1.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/permutations10.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/permutations11.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/permutations12.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/permutations13.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/permutations2.png +0 -0
- invocation_tree-0.0.13/images/permutations22.png~ +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/permutations3.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/permutations4.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/permutations5.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/permutations6.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/permutations7.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/permutations8.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/permutations9.png +0 -0
- invocation_tree-0.0.13/images/student.gif +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/students.py +2 -2
- invocation_tree-0.0.13/images/students.py~ +30 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/students1.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/students10.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/students11.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/students12.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/students13.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/students14.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/students15.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/students2.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/students3.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/students4.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/students5.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/students6.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/students7.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/students8.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/students9.png +0 -0
- invocation_tree-0.0.13/images/test.py +15 -0
- invocation_tree-0.0.13/images/tree.gv~ +22 -0
- invocation_tree-0.0.13/images/tree.pdf +0 -0
- invocation_tree-0.0.13/install.txt +31 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/invocation_tree/__init__.py +1 -1
- {invocation_tree-0.0.11 → invocation_tree-0.0.13/invocation_tree.egg-info}/PKG-INFO +21 -20
- invocation_tree-0.0.13/invocation_tree.egg-info/SOURCES.txt +156 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/setup.py +1 -1
- invocation_tree-0.0.11/images/factorial.gif +0 -0
- invocation_tree-0.0.11/images/factorial.py +0 -9
- invocation_tree-0.0.11/images/factorial1.png +0 -0
- invocation_tree-0.0.11/images/factorial2.png +0 -0
- invocation_tree-0.0.11/images/factorial3.png +0 -0
- invocation_tree-0.0.11/images/factorial4.png +0 -0
- invocation_tree-0.0.11/images/factorial5.png +0 -0
- invocation_tree-0.0.11/images/factorial6.png +0 -0
- invocation_tree-0.0.11/images/factorial7.png +0 -0
- invocation_tree-0.0.11/invocation_tree.egg-info/SOURCES.txt +0 -65
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/LICENSE.txt +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/MANIFEST.in +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/compute.gif +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/create_gif.sh +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/create_images.sh +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/permutations.gif +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/students.gif +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/images/vscode.png +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/invocation_tree.egg-info/dependency_links.txt +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/invocation_tree.egg-info/requires.txt +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/invocation_tree.egg-info/top_level.txt +0 -0
- {invocation_tree-0.0.11 → invocation_tree-0.0.13}/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.13
|
|
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,15 @@ 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
|
+
prev_result = factorial(n - 1)
|
|
161
|
+
return n * prev_result
|
|
161
162
|
|
|
162
|
-
tree =
|
|
163
|
+
tree = ivt.blocking()
|
|
163
164
|
print( tree(factorial, 4) ) # show invocation tree of calling factorial(4)
|
|
164
165
|
```
|
|
165
166
|

|
|
@@ -170,7 +171,7 @@ print( tree(factorial, 4) ) # show invocation tree of calling factorial(4)
|
|
|
170
171
|
This `permutations()` example shows the depth-first nature of recursive execution:
|
|
171
172
|
|
|
172
173
|
```python
|
|
173
|
-
import invocation_tree as
|
|
174
|
+
import invocation_tree as ivt
|
|
174
175
|
|
|
175
176
|
def permutations(elements, perm, n):
|
|
176
177
|
if n==0:
|
|
@@ -180,7 +181,7 @@ def permutations(elements, perm, n):
|
|
|
180
181
|
all_perms.extend(permutations(elements, perm + element, n-1))
|
|
181
182
|
return all_perms
|
|
182
183
|
|
|
183
|
-
tree =
|
|
184
|
+
tree = ivt.blocking()
|
|
184
185
|
result = tree(permutations, ['L','R'], '', 2)
|
|
185
186
|
print(result) # all permutations of going Left or Right of length 2
|
|
186
187
|
```
|
|
@@ -193,7 +194,7 @@ print(result) # all permutations of going Left or Right of length 2
|
|
|
193
194
|
In an educational context it can be useful to hide certian variables to avoid unnecessary complexity. This can for example be done with:
|
|
194
195
|
|
|
195
196
|
```python
|
|
196
|
-
tree =
|
|
197
|
+
tree = ivt.blocking()
|
|
197
198
|
tree.hide.add('permutations.elements')
|
|
198
199
|
tree.hide.add('permutations.element')
|
|
199
200
|
tree.hide.add('permutations.all_perms')
|
|
@@ -203,7 +204,7 @@ tree.hide.add('permutations.all_perms')
|
|
|
203
204
|
These invocation_tree configurations are available for an `Invocation_Tree` objects:
|
|
204
205
|
|
|
205
206
|
```python
|
|
206
|
-
tree =
|
|
207
|
+
tree = ivt.Invocation_Tree()
|
|
207
208
|
```
|
|
208
209
|
|
|
209
210
|
- **tree.filename** : str
|
|
@@ -235,12 +236,12 @@ tree = invo_tree.Invocation_Tree()
|
|
|
235
236
|
|
|
236
237
|
For convenience we provide these functions to set common configurations:
|
|
237
238
|
|
|
238
|
-
- **
|
|
239
|
-
- **
|
|
240
|
-
- **
|
|
241
|
-
- **
|
|
242
|
-
- **
|
|
243
|
-
- **
|
|
239
|
+
- **ivt.blocking(filename)**, blocks on function call and return
|
|
240
|
+
- **ivt.blocking_each_change(filename)**, blocks on each change of value
|
|
241
|
+
- **ivt.debugger(filename)**, non-blocking for use in debugger tool (open <filename> manually)
|
|
242
|
+
- **ivt.gif(filename)**, generates many output files on function call and return for gif creation
|
|
243
|
+
- **ivt.gif_each_change(filename)**, generates many output files on each change of value for gif creation
|
|
244
|
+
- **ivt.non_blocking(filename)**, non-blocking on each function call and return
|
|
244
245
|
|
|
245
246
|
# Troubleshooting #
|
|
246
247
|
- 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,15 @@ 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
|
+
prev_result = factorial(n - 1)
|
|
142
|
+
return n * prev_result
|
|
142
143
|
|
|
143
|
-
tree =
|
|
144
|
+
tree = ivt.blocking()
|
|
144
145
|
print( tree(factorial, 4) ) # show invocation tree of calling factorial(4)
|
|
145
146
|
```
|
|
146
147
|

|
|
@@ -151,7 +152,7 @@ print( tree(factorial, 4) ) # show invocation tree of calling factorial(4)
|
|
|
151
152
|
This `permutations()` example shows the depth-first nature of recursive execution:
|
|
152
153
|
|
|
153
154
|
```python
|
|
154
|
-
import invocation_tree as
|
|
155
|
+
import invocation_tree as ivt
|
|
155
156
|
|
|
156
157
|
def permutations(elements, perm, n):
|
|
157
158
|
if n==0:
|
|
@@ -161,7 +162,7 @@ def permutations(elements, perm, n):
|
|
|
161
162
|
all_perms.extend(permutations(elements, perm + element, n-1))
|
|
162
163
|
return all_perms
|
|
163
164
|
|
|
164
|
-
tree =
|
|
165
|
+
tree = ivt.blocking()
|
|
165
166
|
result = tree(permutations, ['L','R'], '', 2)
|
|
166
167
|
print(result) # all permutations of going Left or Right of length 2
|
|
167
168
|
```
|
|
@@ -174,7 +175,7 @@ print(result) # all permutations of going Left or Right of length 2
|
|
|
174
175
|
In an educational context it can be useful to hide certian variables to avoid unnecessary complexity. This can for example be done with:
|
|
175
176
|
|
|
176
177
|
```python
|
|
177
|
-
tree =
|
|
178
|
+
tree = ivt.blocking()
|
|
178
179
|
tree.hide.add('permutations.elements')
|
|
179
180
|
tree.hide.add('permutations.element')
|
|
180
181
|
tree.hide.add('permutations.all_perms')
|
|
@@ -184,7 +185,7 @@ tree.hide.add('permutations.all_perms')
|
|
|
184
185
|
These invocation_tree configurations are available for an `Invocation_Tree` objects:
|
|
185
186
|
|
|
186
187
|
```python
|
|
187
|
-
tree =
|
|
188
|
+
tree = ivt.Invocation_Tree()
|
|
188
189
|
```
|
|
189
190
|
|
|
190
191
|
- **tree.filename** : str
|
|
@@ -216,12 +217,12 @@ tree = invo_tree.Invocation_Tree()
|
|
|
216
217
|
|
|
217
218
|
For convenience we provide these functions to set common configurations:
|
|
218
219
|
|
|
219
|
-
- **
|
|
220
|
-
- **
|
|
221
|
-
- **
|
|
222
|
-
- **
|
|
223
|
-
- **
|
|
224
|
-
- **
|
|
220
|
+
- **ivt.blocking(filename)**, blocks on function call and return
|
|
221
|
+
- **ivt.blocking_each_change(filename)**, blocks on each change of value
|
|
222
|
+
- **ivt.debugger(filename)**, non-blocking for use in debugger tool (open <filename> manually)
|
|
223
|
+
- **ivt.gif(filename)**, generates many output files on function call and return for gif creation
|
|
224
|
+
- **ivt.gif_each_change(filename)**, generates many output files on each change of value for gif creation
|
|
225
|
+
- **ivt.non_blocking(filename)**, non-blocking on each function call and return
|
|
225
226
|
|
|
226
227
|
# Troubleshooting #
|
|
227
228
|
- 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
|
|
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())
|