Is there a utility to tally function calls from other files?

Chris Angelico rosuav at gmail.com
Sat Jun 13 15:31:22 EDT 2015


On Sun, Jun 14, 2015 at 5:10 AM, C.D. Reimer <chris at cdreimer.com> wrote:
> I'm converting 101 BASIC games from an old book
> (http://www.atariarchives.org/basicgames/) into Python scripts. After a
> dozen conversions, I've created a helper file for common functions (i.e.,
> pick_card(), replay_game() and roll_dice()). The functions for card and dice
> games are obvious candidates for the helper file, but other functions that
> might be one offs that shouldn't be included.
>
> Is there utility that will take the function names from the helper file and
> scan the other files to tally up how many times a particular function got
> called?

Can you guarantee that your function names are absolutely unique text
strings? If so, grep can do what you want. I don't have a huge Python
project to demo this on, but grep is language-agnostic.

rosuav at sikorsky:~/Gypsum$ grep gtksignal *.pike plugins/*.pike
globals.pike://Usage:
gtksignal(some_object,"some_signal",handler,arg,arg,arg) --> save that
object.
globals.pike:class gtksignal(object obj)
globals.pike: mi->signals=({gtksignal(mi->menuitem,"activate",menu_clicked)});
globals.pike: mi->signals=({gtksignal(mi->menuitem,"activate",menu_clicked)});
globals.pike: //a gtksignal object or the integer 0, though as of
20150103 nothing depends on this.
globals.pike: gtksignal(win->mainwindow,"delete_event",closewindow),
globals.pike: win->stock_close &&
gtksignal(win->stock_close,"clicked",closewindow),
globals.pike: win->signals+=({gtksignal(obj,parts[i+1..]*"_",this[key],arg,UNDEFINED,b4)});
globals.pike: if (actionbtn)
win->signals+=({gtksignal(win->pb_action,"clicked",action_callback)});
globals.pike: statustxt->signals=({gtksignal(statustxt->evbox,"button_press_event",mousedown)});
window.pike: //an additional argument to signal_connect/gtksignal
would provide that value here)
plugins/hpgraph.pike:
win->signals+=({gtksignal(win["color"+j+i],"clicked",update_color,i)});
plugins/hpgraph.pike:
info->signals=({gtksignal(info->evbox,"button_press_event",mousedown)});
plugins/rmimport.pike:
gtksignal(win->pb_selectall,"clicked",pb_select_click,1), //Same
handler for these, just an arg
plugins/rmimport.pike:
gtksignal(win->pb_selectnone,"clicked",pb_select_click,0),
//Technically, since the default is 0, I could call this
sig_pb_selectnone_clicked, but this way is clearer.
plugins/search.pike:
statustxt->signals=({gtksignal(statustxt->ef,"key_press_event",keypress,0,UNDEFINED,1)});
plugins/zoneinfo.pike:
win->signals+=({gtksignal(win[pfx+"_"+sfx],"changed",pfx=="Thresh"?convert_th:convert_rl,pfx)});

Each of those lines is one usage of the gtksignal() class/function.
One of them is actually a comment (in window.pike), and the first two
at the top of globals.pike are the class definition, with an
associated usage comment, but all the rest are actual uses. As long as
you can depend on names like roll_dice not occurring anywhere else,
this is a great way to find out what you need to know.

If you _can't_ rely on that, it's a bit harder. You could possibly
append an open parenthesis to it, to require classic function-call
syntax, but that may not necessarily be enough (depends how strict
your style guide is). You can do lexical analysis of a Python program
to see where the name is used in a function call, which might be
better. Or you could instrument the function to find out where it's
being called from, and then run every program and see how many of them
call it - something like this:

def pick_card():
    import __main__
    print("Called from %s"%__main__.__file__)
    # rest of pick_card's definition

Log that to a file instead of the screen, and you have yourself a
guaranteed log that shows which programs use that function. Of course,
that depends on actually running the program far enough to get to the
call, which might require interaction.

Depending on your requirements, it could be anywhere from easy to
hard. Good luck :)

ChrisA



More information about the Python-list mailing list