66import pydot
77
88
9- graph = pydot .Dot (graph_type = "digraph" )
10- node_count = 0
9+ class Visualiser (object ):
10+ node_count = 0
11+ graph = pydot .Dot (graph_type = "digraph" )
12+ def __init__ (self , ignore_args ):
13+ self .ignore_args = ignore_args
1114
12- class TraceCalls (object ):
13- def __init__ (self , stream = sys .stdout , indent_step = 2 , show_ret = False ):
14- self .stream = stream
15- self .indent_step = indent_step
16- self .show_ret = show_ret
15+ @classmethod
16+ def write_image (self , filename = "out" ):
17+ self .graph .write_png (f"{ filename } .png" )
1718
1819
1920
@@ -35,57 +36,56 @@ def wrapper(*args, **kwargs):
3536 caller_func_name = sys ._getframe (1 ).f_code .co_name
3637 caller_func_arg_names = sys ._getframe (1 ).f_code .co_varnames [:fn .__code__ .co_argcount ]
3738
38- caller_func_args = sys ._getframe (1 ).f_locals
39- caller_func_args = OrderedDict (sorted (caller_func_args .items ()))
39+ caller_func_locals = sys ._getframe (1 ).f_locals
40+ caller_func_locals = OrderedDict (sorted (caller_func_locals .items ()))
4041
4142 caller_func_args = ', ' .join (
42- [f"{ key } ={ value } " for key , value in caller_func_args .items () if key in caller_func_arg_names ])
43+ [f"{ key } ={ value } " for key , value in caller_func_locals .items () if ( key in caller_func_arg_names ) ])
4344 caller_func_signature = f"{ caller_func_name } ({ caller_func_args } )"
4445
46+ caller_func_args = ', ' .join (
47+ [f"{ key } ={ value } " for key , value in caller_func_locals .items () if
48+ (key in caller_func_arg_names and key not in self .ignore_args )])
49+ caller_func_node_label = f"{ caller_func_name } ({ caller_func_args } )"
50+
51+ if caller_func_name == '<module>' :
52+ print (f"Drawing for { current_func_signature } " )
53+
54+ result = fn (* args , ** kwargs )
55+
56+ argstr = ', ' .join (
57+ [repr (a ) for a in args ] +
58+ ["%s=%s" % (a , repr (b )) for a , b in kwargs .items () if a not in self .ignore_args ])
59+ current_node_label = f"{ current_func_name } ({ argstr } )"
4560
4661 # # Child Node
47- child_label = current_func_signature
62+ child_label = current_node_label
4863 child_name = current_func_signature
4964 v = pydot .Node (name = child_name , label = child_label )
50- graph .add_node (v )
65+ self . graph .add_node (v )
5166
5267 # Parent Node
5368 u = None
5469
55- if caller_func_name == '<module>' :
56- print ("Start Call" )
57- print (f"Drawing for { current_func_signature } " )
58- else :
70+ if caller_func_name != '<module>' :
5971 print (f"Called { current_func_signature } by { caller_func_signature } " )
60- u = pydot .Node (name = caller_func_signature , label = caller_func_signature )
61- graph .add_node (u )
72+ u = pydot .Node (name = caller_func_signature , label = caller_func_node_label )
73+ self . graph .add_node (u )
6274 edge = pydot .Edge (u , v )
63- graph .add_edge (edge )
75+ self . graph .add_edge (edge )
6476
65- result = fn (* args , ** kwargs )
6677 return result
67-
6878 return wrapper
6979
70- @TraceCalls ()
71- def fib (n , node_num ):
72- global node_count
73- if n <= 1 :
74- return n
75- node_count += 1
76- left = fib (n = n - 1 , node_num = node_count )
77- node_count += 1
78- right = fib (n = n - 2 , node_num = node_count )
79- return left + right
80-
81- @TraceCalls ()
80+
81+
82+
83+ @Visualiser (ignore_args = ['node_num' ])
8284def fact (n , node_num ):
83- global node_count
8485 if n == 1 :
86+ Visualiser .node_count += 1
8587 return 1
8688
87- node_count += 1
88- return n * fact (n = n - 1 , node_num = node_count )
89+ Visualiser . node_count += 1
90+ return n * fact (n = n - 1 , node_num = Visualiser . node_count )
8991
90- print (fib (n = 4 , node_num = 0 ))
91- graph .write_png ('hawa.png' )
0 commit comments