Edward K. Ream
unread,Nov 29, 2012, 7:41:49 AM11/29/12Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to leo-e...@googlegroups.com
Recent revs contain work on a nifty new tracing tool: the SherlockTracer class in leoGlobals.py. This is a stand-alone class: it is not a subclass of pdb.Pdb, and it requires no imports (it does it's own imports)
In essence, the SherlockTracer class does everything my old Sherlock tracing tool did, and it's a lot more flexible. The idea is that you can enable and disable traces for any method or function with tracing arguments. Here is the code that I am using to trace the execution of the Rope refactoring tool::
sherlock = g.SherlockTracer(verbose=True,
patterns=['+.*','+:.*','-:.*\\lib\\.*','+:.*rope.*','-:.*leoGlobals.py',
'-:.*worder.py','-:.*prefs.py','-:.*resources.py',])
sherlock.run()
try:
<< rope code to be traced >>
finally:
sherlock.stop()
sherlock.print_stats(patterns=['+:.*rope.*',])
The arguments in the pattern lists determine which functions get traced or which stats get printed. Each pattern starts with "+", "-", "+:" or "-:", followed by a regular expression.
"+x" Enables tracing (or stats) for all functions/methods whose name matches the regular expression x.
"-x" Disables tracing for functions/methods.
"+:x" Enables tracing for all functions in the **file** whose name matches x.
"-:x" Disables tracing for an entire file.
The cute part is that enabling and disabling depends on the order of arguments in the pattern list. Consider the arguments for the Rope trace::
patterns=['+.*','+:.*','-:.*\\lib\\.*','+:.*rope.*','-:.*leoGlobals.py',
'-:.*worder.py','-:.*prefs.py','-:.*resources.py',])
This enables tracing for everything, then disables tracing for all library modules, except for all rope modules. Finally, it disables the tracing for Rope's worder, prefs and resources modules. Btw, this is one of the best uses for regular expressions that I know of.
Being able to zero in on the code of interest can be a big help in studying other people's code. This is a non-invasive method: no tracing code needs to be inserted anywhere.
Here is a snippet of a recent trace of Rope's validate call::
.project.py:validate
..project.py:<lambda>
...project.py:get_resource
....project.py:_get_resource_path
..project.py:validate
...resourceobserver.py:validate
....project.py:_invalid
...resourceobserver.py:validate
....resourceobserver.py:__init__
....resourceobserver.py:_search_resource_moves
....resourceobserver.py:_search_resource_changes
....resourceobserver.py:_search_resource_creations
....resourceobserver.py:_perform_changes
...resourceobserver.py:validate
....resourceobserver.py:__init__
....resourceobserver.py:_search_resource_moves
....resourceobserver.py:_search_resource_changes
....resourceobserver.py:_search_resource_creations
....resourceobserver.py:_perform_changes
...resourceobserver.py:validate
The leading dots (level dots) indicate the level of nesting of the calls. The call to project.py:validate is the top-level call: it has only one level dot. With this kind of trace it is easy to see who calls whom.
Without the verbose argument, the filenames would be omitted from the trace.
That's about it. I'll probably be adding features to g.SherlockTracer in the next few days.
Edward