On Monday, March 24, 2014 11:37:05 AM UTC-5, Edward K. Ream wrote:
> I am using the g.SherlockTracing class to do the executing. This is, in
essence, and alternate version of pdb, with many cool features.
The present Sherlock code only handles Python calls and returns, but
Python's sys.settrace mechanism allows the trapping of *any* kind of Python
statement. sys.settrace is a great window into the workings of Python
interp--I am surprised that only a few interesting applications have been
developed.
sys.setttrace allows the execution of *any* code whatever, not just
pdb-like code. Rather than stopping, which is *way* too slow, Sherlock
runs something like full machine speed (say 10x slower). Rather than
relying on human data-gathering capabilities, which is *way* too limited,
Sherlock allows data gathering driving by computer code. By manipulating
the present (and future) Sherlock args, the human can do what we do best,
which is find patterns and meaning.
There are several extensions to the Sherlock idea I would like to explore:
1. Simulating backward execution.
The idea is simple: store Sherlock traces in a list instead of printing
them immediately. Then, when something "interesting" happens, say the use
of an object at **a particular** address/id, filter the list so that only
traces pertaining to that id are shown. This allows "backward" filtering.
If we simply reverse the list before printing it we show the execution "in
reverse".
2. Tracing the flow of data rather than (or in addition to) tracing
execution flow.
Again, the idea is simple: save lists or dicts of information about objects
and show/filter them to make them maximally convenient to understand.
Points 1 and 2 above are intimately related, and I'll be exploring various
combinations of them soon.
This will be driven by real exploration of pylint. Here is the test code I
am presently using to explore how pylint works::
# Test this file by running pylint --tt
class aClass:
def __init__ (self):
self.a = 2
self.b()
def b(self):
return self.a.c
We expect pylint to give an error.
Here is the output of pylint --tt. Note that most of the opening lines
were produced by print statements within Sherlock or pylint-leo.py or
pylint itself, not by the enabled Sherlock patterns::
<module 'pylint.lint' from
'c:\python26\lib\site-packages\pylint-0.25.1-py2.6.egg\pylint\lint.pyc'>
pylint-leo.py: c:\leo.repo\static-type-checking\test\pylint\pylint_test.py
pylint-leo.py: enabling Sherlock traces
patterns contained in plyint-leo.py
Sherlock patterns:
+PyLinter::add_message
+:.*typecheck.py
typecheck.py .....+<module>()
typecheck.py ......+TypeChecker()
typecheck.py ......-TypeChecker -> dict
typecheck.py .....-<module>
typecheck.py .....+register(linter=<pylint.lint.PyLinter object at
0x02AA5EF0>)
typecheck.py .....-register
typecheck.py ...+TypeChecker::open()
typecheck.py ...-TypeChecker::open
utils.py
........+PyLinter::add_message(msgid='C0111',node=<Module(pylint_test)>)
utils.py ........-PyLinter::add_message
utils.py
.........+PyLinter::add_message(msgid='C0111',node=<Class(aClass)>)
utils.py .........-PyLinter::add_message
typecheck.py ........+TypeChecker::visit_assign(node=<Assign>)
typecheck.py ........-TypeChecker::visit_assign
typecheck.py .........+TypeChecker::visit_assattr(node=<AssAttr(a)>)
typecheck.py .........-TypeChecker::visit_assattr
typecheck.py .........+TypeChecker::visit_callfunc(node=<CallFunc>)
typecheck.py .........-TypeChecker::visit_callfunc
typecheck.py ..........+TypeChecker::visit_getattr(node=<Getattr(b)>)
typecheck.py ..........-TypeChecker::visit_getattr
utils.py
..........+PyLinter::add_message(msgid='C0111',node=<Function(b)>)
utils.py ..........-PyLinter::add_message
typecheck.py .........+TypeChecker::visit_getattr(node=<Getattr(c)>)
utils.py
...........+PyLinter::add_message(msgid='E1101',node=<Getattr(c)>,args=['Instance
of','int','c'])
************* Module pylint_test
E1101: 9,0:aClass.b: Instance of 'int' has no 'c' member
utils.py ...........-PyLinter::add_message
typecheck.py .........-TypeChecker::visit_getattr
typecheck.py ..........+TypeChecker::visit_getattr(node=<Getattr(a)>)
typecheck.py ..........-TypeChecker::visit_getattr
EKR: time: 0.12 sec, exit status: 2
Note 1: The following lines are the actual pylint error message:
************* Module pylint_test
E1101: 9,0:aClass.b: Instance of 'int' has no 'c' member
Note 2: The data part of this trace is produced by one of pylint's __repr__
methods, modified by me to make them more readable. For example, the
<Getattr(a)> in::
TypeChecker::visit_getattr(node=<Getattr(a)>
Otoh, Sherlock produces everything else, including the list of arguments to
visit_getattr. (Sherlock discovers that "node" is the name of the formal
argument). It's a nifty division of responsibilities.
I ran the test above (with many different traces) to answer two question:
1. How the actual message gets printed (answer PyLinter.add_message)
2. The order in which nodes of the ast (abstract syntax tree) are visited
in order to check the tree. The answer: the order shown by the various
visit_ methods.
An unanswered question: why aren't visit_ClassDef and visit_FunctionDef
called? Something truly clever is going on.
The part that isn't shown by this trace is the entire "inference"
machinery. I'll be exploring that next.
Edward
--
You received this message because you are subscribed to the Google Groups
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.