invocation-tree 0.0.1__tar.gz → 0.0.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. invocation_tree-0.0.2/PKG-INFO +178 -0
  2. invocation_tree-0.0.2/README.md +159 -0
  3. invocation_tree-0.0.2/images/create_gif.sh +19 -0
  4. invocation_tree-0.0.2/images/create_images.sh +16 -0
  5. invocation_tree-0.0.2/images/create_images.sh~ +4 -0
  6. invocation_tree-0.0.2/images/factorial.gif +0 -0
  7. invocation_tree-0.0.2/images/factorial.py +9 -0
  8. invocation_tree-0.0.2/images/factorial.py~ +11 -0
  9. invocation_tree-0.0.2/images/factorial1.png +0 -0
  10. invocation_tree-0.0.2/images/factorial2.png +0 -0
  11. invocation_tree-0.0.2/images/factorial3.png +0 -0
  12. invocation_tree-0.0.2/images/factorial4.png +0 -0
  13. invocation_tree-0.0.2/images/factorial5.png +0 -0
  14. invocation_tree-0.0.2/images/factorial6.png +0 -0
  15. invocation_tree-0.0.2/images/factorial7.png +0 -0
  16. invocation_tree-0.0.2/images/factorial8.gv +36 -0
  17. invocation_tree-0.0.2/images/factorial9.gv +37 -0
  18. invocation_tree-0.0.2/images/invocation_tree.pdf +0 -0
  19. invocation_tree-0.0.2/images/invocation_tree0.pdf +0 -0
  20. invocation_tree-0.0.2/images/permutations.gif +0 -0
  21. invocation_tree-0.0.2/images/permutations.py +13 -0
  22. invocation_tree-0.0.2/images/permutations.py~ +8 -0
  23. invocation_tree-0.0.2/images/permutations1.png +0 -0
  24. invocation_tree-0.0.2/images/permutations10.png +0 -0
  25. invocation_tree-0.0.2/images/permutations11.png +0 -0
  26. invocation_tree-0.0.2/images/permutations12.png +0 -0
  27. invocation_tree-0.0.2/images/permutations13.png +0 -0
  28. invocation_tree-0.0.2/images/permutations14.png +0 -0
  29. invocation_tree-0.0.2/images/permutations15.png +0 -0
  30. invocation_tree-0.0.2/images/permutations16.png +0 -0
  31. invocation_tree-0.0.2/images/permutations17.png +0 -0
  32. invocation_tree-0.0.2/images/permutations18.png +0 -0
  33. invocation_tree-0.0.2/images/permutations19.png +0 -0
  34. invocation_tree-0.0.2/images/permutations2.png +0 -0
  35. invocation_tree-0.0.2/images/permutations20.png +0 -0
  36. invocation_tree-0.0.2/images/permutations21.png +0 -0
  37. invocation_tree-0.0.2/images/permutations22.png +0 -0
  38. invocation_tree-0.0.2/images/permutations22.png~ +0 -0
  39. invocation_tree-0.0.2/images/permutations23.png +0 -0
  40. invocation_tree-0.0.2/images/permutations24.png +0 -0
  41. invocation_tree-0.0.2/images/permutations25.png +0 -0
  42. invocation_tree-0.0.2/images/permutations26.png +0 -0
  43. invocation_tree-0.0.2/images/permutations27.png +0 -0
  44. invocation_tree-0.0.2/images/permutations28.png +0 -0
  45. invocation_tree-0.0.2/images/permutations29.png +0 -0
  46. invocation_tree-0.0.2/images/permutations3.png +0 -0
  47. invocation_tree-0.0.2/images/permutations4.png +0 -0
  48. invocation_tree-0.0.2/images/permutations5.png +0 -0
  49. invocation_tree-0.0.2/images/permutations6.png +0 -0
  50. invocation_tree-0.0.2/images/permutations7.png +0 -0
  51. invocation_tree-0.0.2/images/permutations8.png +0 -0
  52. invocation_tree-0.0.2/images/permutations9.png +0 -0
  53. invocation_tree-0.0.2/images/student.gif +0 -0
  54. invocation_tree-0.0.2/images/students.gif +0 -0
  55. invocation_tree-0.0.2/images/students.py +27 -0
  56. invocation_tree-0.0.2/images/students.py~ +30 -0
  57. invocation_tree-0.0.2/images/students1.png +0 -0
  58. invocation_tree-0.0.2/images/students10.png +0 -0
  59. invocation_tree-0.0.2/images/students11.png +0 -0
  60. invocation_tree-0.0.2/images/students12.png +0 -0
  61. invocation_tree-0.0.2/images/students13.png +0 -0
  62. invocation_tree-0.0.2/images/students14.png +0 -0
  63. invocation_tree-0.0.2/images/students15.png +0 -0
  64. invocation_tree-0.0.2/images/students16.gv +44 -0
  65. invocation_tree-0.0.2/images/students17.gv +50 -0
  66. invocation_tree-0.0.2/images/students18.gv +51 -0
  67. invocation_tree-0.0.2/images/students19.gv +58 -0
  68. invocation_tree-0.0.2/images/students2.png +0 -0
  69. invocation_tree-0.0.2/images/students20.gv +59 -0
  70. invocation_tree-0.0.2/images/students21.gv +60 -0
  71. invocation_tree-0.0.2/images/students22.gv +61 -0
  72. invocation_tree-0.0.2/images/students23.gv +60 -0
  73. invocation_tree-0.0.2/images/students24.gv +66 -0
  74. invocation_tree-0.0.2/images/students25.gv +68 -0
  75. invocation_tree-0.0.2/images/students26.gv +68 -0
  76. invocation_tree-0.0.2/images/students27.gv +68 -0
  77. invocation_tree-0.0.2/images/students28.gv +67 -0
  78. invocation_tree-0.0.2/images/students29.gv +68 -0
  79. invocation_tree-0.0.2/images/students3.png +0 -0
  80. invocation_tree-0.0.2/images/students30.gv +69 -0
  81. invocation_tree-0.0.2/images/students4.png +0 -0
  82. invocation_tree-0.0.2/images/students5.png +0 -0
  83. invocation_tree-0.0.2/images/students6.png +0 -0
  84. invocation_tree-0.0.2/images/students7.png +0 -0
  85. invocation_tree-0.0.2/images/students8.png +0 -0
  86. invocation_tree-0.0.2/images/students9.png +0 -0
  87. invocation_tree-0.0.2/images/test.py +15 -0
  88. invocation_tree-0.0.2/images/tree0.gv +7 -0
  89. invocation_tree-0.0.2/images/tree1.gv +13 -0
  90. invocation_tree-0.0.2/images/tree10.gv +56 -0
  91. invocation_tree-0.0.2/images/tree11.gv +64 -0
  92. invocation_tree-0.0.2/images/tree12.gv +66 -0
  93. invocation_tree-0.0.2/images/tree13.gv +67 -0
  94. invocation_tree-0.0.2/images/tree14.gv +72 -0
  95. invocation_tree-0.0.2/images/tree15.gv +73 -0
  96. invocation_tree-0.0.2/images/tree16.gv +75 -0
  97. invocation_tree-0.0.2/images/tree17.gv +75 -0
  98. invocation_tree-0.0.2/images/tree2.gv +22 -0
  99. invocation_tree-0.0.2/images/tree3.gv +30 -0
  100. invocation_tree-0.0.2/images/tree4.gv +32 -0
  101. invocation_tree-0.0.2/images/tree5.gv +33 -0
  102. invocation_tree-0.0.2/images/tree6.gv +39 -0
  103. invocation_tree-0.0.2/images/tree7.gv +47 -0
  104. invocation_tree-0.0.2/images/tree8.gv +49 -0
  105. invocation_tree-0.0.2/images/tree9.gv +50 -0
  106. invocation_tree-0.0.2/images/vscode.png +0 -0
  107. invocation_tree-0.0.2/invocation_tree/__init__.py +276 -0
  108. invocation_tree-0.0.2/invocation_tree.egg-info/PKG-INFO +178 -0
  109. invocation_tree-0.0.2/invocation_tree.egg-info/SOURCES.txt +115 -0
  110. {invocation_tree-0.0.1 → invocation_tree-0.0.2}/setup.py +2 -2
  111. invocation_tree-0.0.1/PKG-INFO +0 -27
  112. invocation_tree-0.0.1/README.md +0 -8
  113. invocation_tree-0.0.1/images/invocation_tree.pdf +0 -0
  114. invocation_tree-0.0.1/images/permutation.py +0 -23
  115. invocation_tree-0.0.1/invocation_tree/__init__.py +0 -151
  116. invocation_tree-0.0.1/invocation_tree.egg-info/PKG-INFO +0 -27
  117. invocation_tree-0.0.1/invocation_tree.egg-info/SOURCES.txt +0 -13
  118. {invocation_tree-0.0.1 → invocation_tree-0.0.2}/LICENSE.txt +0 -0
  119. {invocation_tree-0.0.1 → invocation_tree-0.0.2}/MANIFEST.in +0 -0
  120. {invocation_tree-0.0.1 → invocation_tree-0.0.2}/install.txt +0 -0
  121. {invocation_tree-0.0.1 → invocation_tree-0.0.2}/invocation_tree.egg-info/dependency_links.txt +0 -0
  122. {invocation_tree-0.0.1 → invocation_tree-0.0.2}/invocation_tree.egg-info/requires.txt +0 -0
  123. {invocation_tree-0.0.1 → invocation_tree-0.0.2}/invocation_tree.egg-info/top_level.txt +0 -0
  124. {invocation_tree-0.0.1 → invocation_tree-0.0.2}/setup.cfg +0 -0
@@ -0,0 +1,178 @@
1
+ Metadata-Version: 2.1
2
+ Name: invocation_tree
3
+ Version: 0.0.2
4
+ Summary: Generate an invocation tree of functions calls.
5
+ Home-page: https://github.com/bterwijn/invocation_tree
6
+ Author: Bas Terwijn
7
+ Author-email: bterwijn@gmail.com
8
+ License: BSD 2-clause
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Education
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: BSD License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Education
15
+ Classifier: Topic :: Software Development :: Debuggers
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE.txt
18
+ Requires-Dist: graphviz
19
+
20
+ # Installation #
21
+ Install (or upgrade) `invocation_tree` using pip:
22
+ ```
23
+ pip install --upgrade invocation_tree
24
+ ```
25
+ Additionally [Graphviz](https://graphviz.org/download/) needs to be installed.
26
+
27
+ # Invocation Tree #
28
+ The [invocation_tree](https://pypi.org/project/invocation-tree/) package is designed to help with **program understanding and debugging** by visualizing the **tree of function invocations** that occur during program execution. Here’s an example of how it works:
29
+
30
+ ```python
31
+ import invocation_tree as invo_tree
32
+ import math
33
+
34
+ def main():
35
+ students = {'Ann':[7.5, 8.0],
36
+ 'Bob':[4.5, 6.0],
37
+ 'Coy':[7.5, 6.0]}
38
+ averages = {student:compute_average(grades)
39
+ for student, grades in students.items()}
40
+ passing = passing_students(averages)
41
+ print(passing)
42
+
43
+ def compute_average(grades):
44
+ average = sum(grades)/len(grades)
45
+ return my_round(average, 1)
46
+
47
+ def my_round(value, digits=0):
48
+ shift = 10 ** digits
49
+ return math.floor(value * shift + 0.5) / shift
50
+
51
+ def passing_students(avg):
52
+ return [student
53
+ for student, average in avg.items()
54
+ if average >= 5.5]
55
+
56
+ if __name__ == '__main__':
57
+ tree = invo_tree.blocking()
58
+ tree(main) # show invocation tree starting at main
59
+ ```
60
+ ![invocation tree](https://raw.githubusercontent.com/bterwijn/invocation_tree/main/images/students.gif)
61
+
62
+ Each node in the tree represents a function call, and node's color indicates its state:
63
+
64
+ - White: The function is currently being executed (it is at the top of the call stack).
65
+ - Green: The function is paused and will resume execution later (it is lower down on the call stack).
66
+ - Red: The function has completed execution and returned (it has been removed from the call stack).
67
+
68
+ For every function, the package displays its **local variables** and **return value**. Changes to these values over time are highlighted using bold text and gray shading to make them easy to track.
69
+
70
+ The [invocation_tree](https://pypi.org/project/invocation-tree/) package visualizes function calls at different moments in time. If you want a more detailed visualization of your data at a specific moment in time, check out the [memory_graph](https://pypi.org/project/memory-graph/) package.
71
+
72
+ ## Blocking ##
73
+ 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) where a change of value occured, use instead:
74
+
75
+ ```python
76
+ tree = invo_tree.blocking_each_line()
77
+ ```
78
+
79
+ # Debugger #
80
+ To visualize the invocation tree in a debugger tool, such as the integrated debugger in Visual Studio Code, use instead:
81
+
82
+ ```python
83
+ tree = invo_tree.debugger()
84
+ ```
85
+
86
+ and open the 'tree.pdf' file manually.
87
+ ![Visual Studio Code debugger](https://raw.githubusercontent.com/bterwijn/invocation_tree/main/images/vscode.png)
88
+
89
+ # Recursion #
90
+ An invocation tree is particularly useful to better understand recursion. A simple `factorial()` example:
91
+
92
+ ```python
93
+ import invocation_tree as invo_tree
94
+
95
+ def factorial(n):
96
+ if n <= 1:
97
+ return 1
98
+ return n * factorial(n - 1)
99
+
100
+ tree = invo_tree.blocking()
101
+ tree(factorial, 4) # calls factorial(4)
102
+ ```
103
+ ![factorial](https://raw.githubusercontent.com/bterwijn/invocation_tree/main/images/factorial.gif)
104
+
105
+ This `permutations()` example shows the depth-first nature of recursive execution:
106
+
107
+ ```python
108
+ import invocation_tree as invo_tree
109
+
110
+ def permutations(elements, perm, n):
111
+ if n==0:
112
+ return [perm]
113
+ all_perms = []
114
+ for element in elements:
115
+ all_perms.extend(permutations(elements, perm + element, n-1))
116
+ return all_perms
117
+
118
+ tree = invo_tree.blocking()
119
+ result = tree(permutations, ['L','R'], '', 3)
120
+ print(result) # all permutations of going Left and Right of length 3
121
+ ```
122
+ ![permutations](https://raw.githubusercontent.com/bterwijn/invocation_tree/main/images/permutations.gif)
123
+
124
+ ## Hide variables ##
125
+ In an educational context it can be useful to hide certian variables to avoid unnecessary complexity. This can for example be done with:
126
+
127
+ ```python
128
+ tree = invo_tree.blocking()
129
+ tree.hide.add('permutations.elements')
130
+ tree.hide.add('permutations.element')
131
+ tree.hide.add('permutations.all_perms')
132
+ ```
133
+
134
+ # Configuration #
135
+ These configuration settings are available for an `Invocation_Tree` objects:
136
+
137
+ ```python
138
+ tree = invo_tree.Invocation_Tree()
139
+ ```
140
+
141
+ - **tree.filename** : str
142
+ - filename to save the tree to, defaults to 'tree.pdf'
143
+ - **tree.show** : bool
144
+ - if `True` the default application is open to view 'tree.filename'
145
+ - **tree.block** : bool
146
+ - if `True` program execution is blocked after the tree is saved
147
+ - **tree.src_loc** : bool
148
+ - if `True` the source location is printed when blocking
149
+ - **tree.each_line** : bool
150
+ - if `True` each line of the program is stepped through
151
+ - **tree.max_string_len** : int
152
+ - the maximum string length, only the end is shown of longer strings
153
+ - **tree.gifcount** : int
154
+ - if `>=0` the out filename is numbered for animated gif making
155
+ - **tree.indent** : string
156
+ - the string used for identing the local variables
157
+ - **tree.color_active** : string
158
+ - HTML color name for active function
159
+ - **tree.color_paused*** : string
160
+ - HTML color name for paused functions
161
+ - **tree.color_returned***: string
162
+ - HTML color name for returned functions
163
+ - **tree.hide** : set()
164
+ - set of all variables names that are not shown in the tree
165
+ - **tree.to_string** : dict[str, fun]
166
+ - mapping from type/name to a to_string() function for custom printing of values
167
+
168
+ For convenience we provide these functions to set common configurations:
169
+
170
+ - **invo_tree.blocking()**, for blocking on function call and return
171
+ - **invo_tree.blocking_each_line()**, for blocking on each line of the program
172
+ - **invo_tree.debugger()**, for use in debugger tool (open 'tree.pdf') manually
173
+ - **invo_tree.gif(filename)**, for generating many output files on function call and return for gif creation
174
+ - **invo_tree.gif_each_line(filename)**, for generating many output files on each line for gif creation
175
+
176
+ # Troubleshooting #
177
+
178
+ - 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,159 @@
1
+ # Installation #
2
+ Install (or upgrade) `invocation_tree` using pip:
3
+ ```
4
+ pip install --upgrade invocation_tree
5
+ ```
6
+ Additionally [Graphviz](https://graphviz.org/download/) needs to be installed.
7
+
8
+ # Invocation Tree #
9
+ The [invocation_tree](https://pypi.org/project/invocation-tree/) package is designed to help with **program understanding and debugging** by visualizing the **tree of function invocations** that occur during program execution. Here’s an example of how it works:
10
+
11
+ ```python
12
+ import invocation_tree as invo_tree
13
+ import math
14
+
15
+ def main():
16
+ students = {'Ann':[7.5, 8.0],
17
+ 'Bob':[4.5, 6.0],
18
+ 'Coy':[7.5, 6.0]}
19
+ averages = {student:compute_average(grades)
20
+ for student, grades in students.items()}
21
+ passing = passing_students(averages)
22
+ print(passing)
23
+
24
+ def compute_average(grades):
25
+ average = sum(grades)/len(grades)
26
+ return my_round(average, 1)
27
+
28
+ def my_round(value, digits=0):
29
+ shift = 10 ** digits
30
+ return math.floor(value * shift + 0.5) / shift
31
+
32
+ def passing_students(avg):
33
+ return [student
34
+ for student, average in avg.items()
35
+ if average >= 5.5]
36
+
37
+ if __name__ == '__main__':
38
+ tree = invo_tree.blocking()
39
+ tree(main) # show invocation tree starting at main
40
+ ```
41
+ ![invocation tree](https://raw.githubusercontent.com/bterwijn/invocation_tree/main/images/students.gif)
42
+
43
+ Each node in the tree represents a function call, and node's color indicates its state:
44
+
45
+ - White: The function is currently being executed (it is at the top of the call stack).
46
+ - Green: The function is paused and will resume execution later (it is lower down on the call stack).
47
+ - Red: The function has completed execution and returned (it has been removed from the call stack).
48
+
49
+ For every function, the package displays its **local variables** and **return value**. Changes to these values over time are highlighted using bold text and gray shading to make them easy to track.
50
+
51
+ The [invocation_tree](https://pypi.org/project/invocation-tree/) package visualizes function calls at different moments in time. If you want a more detailed visualization of your data at a specific moment in time, check out the [memory_graph](https://pypi.org/project/memory-graph/) package.
52
+
53
+ ## Blocking ##
54
+ The program blocks execution at every function call and return statement, printing the current location in the source code. Press the &lt;Enter&gt; key to continue execution. To block at every line of the program (like in a debugger tool) where a change of value occured, use instead:
55
+
56
+ ```python
57
+ tree = invo_tree.blocking_each_line()
58
+ ```
59
+
60
+ # Debugger #
61
+ To visualize the invocation tree in a debugger tool, such as the integrated debugger in Visual Studio Code, use instead:
62
+
63
+ ```python
64
+ tree = invo_tree.debugger()
65
+ ```
66
+
67
+ and open the 'tree.pdf' file manually.
68
+ ![Visual Studio Code debugger](https://raw.githubusercontent.com/bterwijn/invocation_tree/main/images/vscode.png)
69
+
70
+ # Recursion #
71
+ An invocation tree is particularly useful to better understand recursion. A simple `factorial()` example:
72
+
73
+ ```python
74
+ import invocation_tree as invo_tree
75
+
76
+ def factorial(n):
77
+ if n <= 1:
78
+ return 1
79
+ return n * factorial(n - 1)
80
+
81
+ tree = invo_tree.blocking()
82
+ tree(factorial, 4) # calls factorial(4)
83
+ ```
84
+ ![factorial](https://raw.githubusercontent.com/bterwijn/invocation_tree/main/images/factorial.gif)
85
+
86
+ This `permutations()` example shows the depth-first nature of recursive execution:
87
+
88
+ ```python
89
+ import invocation_tree as invo_tree
90
+
91
+ def permutations(elements, perm, n):
92
+ if n==0:
93
+ return [perm]
94
+ all_perms = []
95
+ for element in elements:
96
+ all_perms.extend(permutations(elements, perm + element, n-1))
97
+ return all_perms
98
+
99
+ tree = invo_tree.blocking()
100
+ result = tree(permutations, ['L','R'], '', 3)
101
+ print(result) # all permutations of going Left and Right of length 3
102
+ ```
103
+ ![permutations](https://raw.githubusercontent.com/bterwijn/invocation_tree/main/images/permutations.gif)
104
+
105
+ ## Hide variables ##
106
+ In an educational context it can be useful to hide certian variables to avoid unnecessary complexity. This can for example be done with:
107
+
108
+ ```python
109
+ tree = invo_tree.blocking()
110
+ tree.hide.add('permutations.elements')
111
+ tree.hide.add('permutations.element')
112
+ tree.hide.add('permutations.all_perms')
113
+ ```
114
+
115
+ # Configuration #
116
+ These configuration settings are available for an `Invocation_Tree` objects:
117
+
118
+ ```python
119
+ tree = invo_tree.Invocation_Tree()
120
+ ```
121
+
122
+ - **tree.filename** : str
123
+ - filename to save the tree to, defaults to 'tree.pdf'
124
+ - **tree.show** : bool
125
+ - if `True` the default application is open to view 'tree.filename'
126
+ - **tree.block** : bool
127
+ - if `True` program execution is blocked after the tree is saved
128
+ - **tree.src_loc** : bool
129
+ - if `True` the source location is printed when blocking
130
+ - **tree.each_line** : bool
131
+ - if `True` each line of the program is stepped through
132
+ - **tree.max_string_len** : int
133
+ - the maximum string length, only the end is shown of longer strings
134
+ - **tree.gifcount** : int
135
+ - if `>=0` the out filename is numbered for animated gif making
136
+ - **tree.indent** : string
137
+ - the string used for identing the local variables
138
+ - **tree.color_active** : string
139
+ - HTML color name for active function
140
+ - **tree.color_paused*** : string
141
+ - HTML color name for paused functions
142
+ - **tree.color_returned***: string
143
+ - HTML color name for returned functions
144
+ - **tree.hide** : set()
145
+ - set of all variables names that are not shown in the tree
146
+ - **tree.to_string** : dict[str, fun]
147
+ - mapping from type/name to a to_string() function for custom printing of values
148
+
149
+ For convenience we provide these functions to set common configurations:
150
+
151
+ - **invo_tree.blocking()**, for blocking on function call and return
152
+ - **invo_tree.blocking_each_line()**, for blocking on each line of the program
153
+ - **invo_tree.debugger()**, for use in debugger tool (open 'tree.pdf') manually
154
+ - **invo_tree.gif(filename)**, for generating many output files on function call and return for gif creation
155
+ - **invo_tree.gif_each_line(filename)**, for generating many output files on each line for gif creation
156
+
157
+ # Troubleshooting #
158
+
159
+ - 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,19 @@
1
+ #!/bin/bash
2
+ #
3
+ # install:
4
+ #
5
+ # sudo apt install imagemagick
6
+
7
+ name="$1"
8
+ files=$(ls -v $name*.png)
9
+ echo "creating gif with:"
10
+ echo "$files"
11
+
12
+ largest_size=$(identify -format "%Wx%H %f\n" $name*.png | sort -nr | head -n1)
13
+ echo "largest_size: $largest_size"
14
+
15
+ echo "resizing images"
16
+ mogrify -resize $largest_size -background white -gravity center -extent $largest_size $files
17
+ echo "creating file: $name.gif"
18
+ convert -delay 150 -loop 0 $files $name.gif
19
+ echo "done"
@@ -0,0 +1,16 @@
1
+
2
+ rm -f students*.png
3
+ python students.py
4
+ rm -f students0.png
5
+ bash create_gif.sh students
6
+
7
+ rm -f factorial*.png
8
+ python factorial.py
9
+ rm -f factorial0.png
10
+ bash create_gif.sh factorial
11
+
12
+ rm -f permutations*.png
13
+ python permutations.py
14
+ rm -f permutations0.png
15
+ bash create_gif.sh permutations
16
+
@@ -0,0 +1,4 @@
1
+
2
+ python students.py
3
+ rm students0.png
4
+ bash create_gif.sh students
@@ -0,0 +1,9 @@
1
+ import invocation_tree as invo_tree
2
+
3
+ def factorial(n):
4
+ if n <= 1:
5
+ return 1
6
+ return n * factorial(n - 1)
7
+
8
+ tree = invo_tree.gif('factorial.png')
9
+ tree(factorial, 4)
@@ -0,0 +1,11 @@
1
+ import invocation_tree
2
+
3
+ def factorial(n):
4
+ if n <= 0:
5
+ return 1
6
+ return n * factorial(n - 1)
7
+
8
+ invocation_tree = invocation_tree.Invocation_Tree()
9
+ invocation_tree.block = False
10
+
11
+ print( invocation_tree(factorial, 4) )
@@ -0,0 +1,36 @@
1
+ digraph invocation_tree {
2
+ node [shape=plaintext]
3
+ 0 [label=<
4
+ <TABLE BORDER="3" CELLBORDER="0" CELLSPACING="0" BGCOLOR="#ffffff">
5
+ <TR><TD ALIGN="left">➤factorial</TD></TR>
6
+ <TR><TD ALIGN="left"> n: 4</TD></TR>
7
+ </TABLE>>]
8
+ 1 [label=<
9
+ <TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" BGCOLOR="#ffcccc">
10
+ <TR><TD ALIGN="left">➤factorial</TD></TR>
11
+ <TR><TD ALIGN="left"> n: 3</TD></TR>
12
+ <TR><TD ALIGN="left">return <B>6</B></TD></TR>
13
+ </TABLE>>]
14
+ 2 [label=<
15
+ <TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" BGCOLOR="#ffcccc">
16
+ <TR><TD ALIGN="left">➤factorial</TD></TR>
17
+ <TR><TD ALIGN="left"> n: 2</TD></TR>
18
+ <TR><TD ALIGN="left">return 2</TD></TR>
19
+ </TABLE>>]
20
+ 3 [label=<
21
+ <TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" BGCOLOR="#ffcccc">
22
+ <TR><TD ALIGN="left">➤factorial</TD></TR>
23
+ <TR><TD ALIGN="left"> n: 1</TD></TR>
24
+ <TR><TD ALIGN="left">return 1</TD></TR>
25
+ </TABLE>>]
26
+ 4 [label=<
27
+ <TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" BGCOLOR="#ffcccc">
28
+ <TR><TD ALIGN="left">➤factorial</TD></TR>
29
+ <TR><TD ALIGN="left"> n: 0</TD></TR>
30
+ <TR><TD ALIGN="left">return 1</TD></TR>
31
+ </TABLE>>]
32
+ 0 -> 1
33
+ 1 -> 2
34
+ 2 -> 3
35
+ 3 -> 4
36
+ }
@@ -0,0 +1,37 @@
1
+ digraph invocation_tree {
2
+ node [shape=plaintext]
3
+ 0 [label=<
4
+ <TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" BGCOLOR="#ffcccc">
5
+ <TR><TD ALIGN="left">➤factorial</TD></TR>
6
+ <TR><TD ALIGN="left"> n: 4</TD></TR>
7
+ <TR><TD ALIGN="left">return <B>24</B></TD></TR>
8
+ </TABLE>>]
9
+ 1 [label=<
10
+ <TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" BGCOLOR="#ffcccc">
11
+ <TR><TD ALIGN="left">➤factorial</TD></TR>
12
+ <TR><TD ALIGN="left"> n: 3</TD></TR>
13
+ <TR><TD ALIGN="left">return 6</TD></TR>
14
+ </TABLE>>]
15
+ 2 [label=<
16
+ <TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" BGCOLOR="#ffcccc">
17
+ <TR><TD ALIGN="left">➤factorial</TD></TR>
18
+ <TR><TD ALIGN="left"> n: 2</TD></TR>
19
+ <TR><TD ALIGN="left">return 2</TD></TR>
20
+ </TABLE>>]
21
+ 3 [label=<
22
+ <TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" BGCOLOR="#ffcccc">
23
+ <TR><TD ALIGN="left">➤factorial</TD></TR>
24
+ <TR><TD ALIGN="left"> n: 1</TD></TR>
25
+ <TR><TD ALIGN="left">return 1</TD></TR>
26
+ </TABLE>>]
27
+ 4 [label=<
28
+ <TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" BGCOLOR="#ffcccc">
29
+ <TR><TD ALIGN="left">➤factorial</TD></TR>
30
+ <TR><TD ALIGN="left"> n: 0</TD></TR>
31
+ <TR><TD ALIGN="left">return 1</TD></TR>
32
+ </TABLE>>]
33
+ 0 -> 1
34
+ 1 -> 2
35
+ 2 -> 3
36
+ 3 -> 4
37
+ }
@@ -0,0 +1,13 @@
1
+ import invocation_tree as invo_tree
2
+
3
+ def permutations(elements, perm, n):
4
+ if n==0:
5
+ return [perm]
6
+ all_perms = []
7
+ for element in elements:
8
+ all_perms.extend(permutations(elements, perm + element, n-1))
9
+ return all_perms
10
+
11
+ tree = invo_tree.gif('permutations.png')
12
+ result = tree(permutations, ['L','R'], '', 3)
13
+ print(result)
@@ -0,0 +1,8 @@
1
+
2
+ def permutations(elements, perm, n):
3
+ if n==0:
4
+ return [perm]
5
+ for element in elements:
6
+ permutations(perm + element, n-1)
7
+
8
+ permutations(['L','R'])
Binary file
@@ -0,0 +1,27 @@
1
+ import invocation_tree as invo_tree
2
+ import math
3
+
4
+ def main():
5
+ students = {'Ann':[7.5, 8.0],
6
+ 'Bob':[4.5, 6.0],
7
+ 'Coy':[7.5, 6.0]}
8
+ averages = {student:compute_average(grades)
9
+ for student, grades in students.items()}
10
+ passing = passing_students(averages)
11
+ print(passing)
12
+
13
+ def compute_average(grades):
14
+ average = sum(grades)/len(grades)
15
+ return my_round(average, 1)
16
+
17
+ def my_round(value, digits=0):
18
+ shift = 10 ** digits
19
+ return math.floor(value * shift + 0.5) / shift
20
+
21
+ def passing_students(avg):
22
+ return [student
23
+ for student, average in avg.items()
24
+ if average >= 5.5]
25
+
26
+ if __name__ == '__main__':
27
+ invo_tree.gif(filename="students.png")(main)