[py-svn] r33965 - in py/dist/py/apigen: rest tracer tracer/testing
guido at codespeak.net
guido at codespeak.net
Tue Oct 31 17:09:38 CET 2006
Author: guido
Date: Tue Oct 31 17:09:35 2006
New Revision: 33965
Modified:
py/dist/py/apigen/rest/genrest.py
py/dist/py/apigen/tracer/description.py
py/dist/py/apigen/tracer/docstorage.py
py/dist/py/apigen/tracer/testing/test_docgen.py
py/dist/py/apigen/tracer/testing/test_package.py
py/dist/py/apigen/tracer/tracer.py
Log:
Improved (and actually got it to work :) displaying of changes in self.__dict__
after method calls. Also some whitespace and reformatting.
Modified: py/dist/py/apigen/rest/genrest.py
==============================================================================
--- py/dist/py/apigen/rest/genrest.py (original)
+++ py/dist/py/apigen/rest/genrest.py Tue Oct 31 17:09:35 2006
@@ -330,6 +330,17 @@
items.append(Text(next))
lst.append(ListItem(*items))
+ local_changes = self.dsa.get_function_local_changes(functionname)
+ lst.append(Paragraph('Changes in __dict__:'))
+ from py.__.apigen.tracer.description import NoValue
+ for k, (oldvalue, newvalue) in local_changes.iteritems():
+ description = 'value changed'
+ if oldvalue is NoValue:
+ description = 'newly added'
+ elif newvalue is NoValue:
+ description = 'deleted'
+ lst.append(ListItem('%s: %s' % (k, description)))
+
# XXX missing implementation of dsa.get_function_location()
#filename, lineno = self.dsa.get_function_location(functionname)
#linkname, linktarget = self.linkgen.getlink(filename, lineno)
Modified: py/dist/py/apigen/tracer/description.py
==============================================================================
--- py/dist/py/apigen/tracer/description.py (original)
+++ py/dist/py/apigen/tracer/description.py Tue Oct 31 17:09:35 2006
@@ -42,6 +42,9 @@
def __cmp__(self, other):
return cmp(self._getval(), other._getval())
+class NoValue(object):
+ """used in MethodDesc.get_local_changes() when there is no value"""
+
def cut_stack(stack, frame, upward_frame=None):
if hasattr(frame, 'raw'):
frame = frame.raw
@@ -121,7 +124,6 @@
self.keep_frames = kwargs.get('keep_frames', False)
self.frame_copier = kwargs.get('frame_copier', lambda x:x)
self.retval = model.s_ImpossibleValue
- self.local_changes = {}
def consider_call(self, inputcells):
for cell_num, cell in enumerate(inputcells):
@@ -148,13 +150,19 @@
def consider_return(self, arg):
self.retval = model.unionof(arg, self.retval)
- def handle_local_changes(self, changeset):
- self.local_changes = changeset
+ def consider_start_locals(self, frame):
+ pass
+ def consider_end_locals(self, frame):
+ pass
+
def getcode(self):
return self.pyobj.func_code
code = property(getcode)
+ def get_local_changes(self):
+ return {}
+
class ClassDesc(Desc):
def __init__(self, *args, **kwargs):
super(ClassDesc, self).__init__(*args, **kwargs)
@@ -196,6 +204,12 @@
def consider_return(self, arg):
pass # we *know* what return value we do have
+
+ def consider_start_locals(self, frame):
+ pass
+
+ def consider_end_locals(self, frame):
+ pass
def consider_call_site(self, frame, cut_frame):
self.fields['__init__'].consider_call_site(frame, cut_frame)
@@ -217,9 +231,42 @@
##
##
class MethodDesc(FunctionDesc):
+ def __init__(self, *args, **kwargs):
+ super(MethodDesc, self).__init__(*args, **kwargs)
+ self.old_dict = {}
+ self.new_dict = {}
+
# right now it's not different than method desc, only code is different
def getcode(self):
return self.pyobj.im_func.func_code
code = property(getcode)
## def has_code(self, code):
## return self.pyobj.im_func.func_code is code
+
+ def consider_start_locals(self, frame):
+ # XXX recursion issues?
+ obj = frame.f_locals.get('self')
+ if not obj:
+ # static method
+ return
+ self.old_dict = obj.__dict__.copy()
+
+ def consider_end_locals(self, frame):
+ obj = frame.f_locals.get('self')
+ if not obj:
+ # static method
+ return
+ self.new_dict = obj.__dict__.copy()
+
+ def get_local_changes(self):
+ changeset = {}
+ for k, v in self.old_dict.iteritems():
+ if k not in self.new_dict:
+ changeset[k] = (v, NoValue)
+ elif self.new_dict[k] != v:
+ changeset[k] = (v, self.new_dict[k])
+ for k, v in self.new_dict.iteritems():
+ if k not in self.old_dict:
+ changeset[k] = (NoValue, v)
+ return changeset
+
Modified: py/dist/py/apigen/tracer/docstorage.py
==============================================================================
--- py/dist/py/apigen/tracer/docstorage.py (original)
+++ py/dist/py/apigen/tracer/docstorage.py Tue Oct 31 17:09:35 2006
@@ -21,13 +21,8 @@
if desc:
self.generalize_args(desc, frame)
desc.consider_call_site(caller_frame, upward_cut_frame)
+ desc.consider_start_locals(frame)
- def handle_local_changes(self, frame, changes):
- assert isinstance(frame, py.code.Frame)
- desc = self.find_desc(frame.code)
- if desc:
- desc.handle_local_changes(changes)
-
def generalize_args(self, desc, frame):
args = [arg for key, arg in frame.getargs()]
#self.call_stack.append((desc, args))
@@ -41,6 +36,7 @@
desc = self.find_desc(frame.code)
if desc:
self.generalize_retval(desc, arg)
+ desc.consider_end_locals(frame)
def find_desc(self, code):
return self.desc_cache.get(code.raw, None)
@@ -208,7 +204,7 @@
return self.ds.descs[name].get_call_sites()
def get_function_local_changes(self, name):
- return self.ds.descs[name].local_changes
+ return self.ds.descs[name].get_local_changes()
def get_module_name(self):
if hasattr(self.ds, 'module'):
Modified: py/dist/py/apigen/tracer/testing/test_docgen.py
==============================================================================
--- py/dist/py/apigen/tracer/testing/test_docgen.py (original)
+++ py/dist/py/apigen/tracer/testing/test_docgen.py Tue Oct 31 17:09:35 2006
@@ -145,3 +145,36 @@
t.end_tracing()
assert isinstance(ds.descs['A'].fields['method'].inputcells[1], model.SomeInt)
assert isinstance(ds.descs['B'].fields['method'].inputcells[1], model.SomeInt)
+
+def test_local_changes():
+ class testclass(object):
+ def __init__(self):
+ self.foo = 0
+ def bar(self, x):
+ self.foo = x
+ ds = DocStorage().from_dict({'testclass': testclass})
+ t = Tracer(ds)
+ t.start_tracing()
+ c = testclass()
+ c.bar(1)
+ t.end_tracing()
+ desc = ds.descs['testclass']
+ methdesc = desc.fields['bar']
+ assert methdesc.old_dict != methdesc.new_dict
+ assert methdesc.get_local_changes() == {'foo': (0, 1)}
+
+def test_local_changes_nochange():
+ class testclass(object):
+ def __init__(self):
+ self.foo = 0
+ def bar(self, x):
+ self.foo = x
+ ds = DocStorage().from_dict({'testclass': testclass})
+ t = Tracer(ds)
+ t.start_tracing()
+ c = testclass()
+ t.end_tracing()
+ desc = ds.descs['testclass']
+ methdesc = desc.fields['bar']
+ assert methdesc.get_local_changes() == {}
+
Modified: py/dist/py/apigen/tracer/testing/test_package.py
==============================================================================
--- py/dist/py/apigen/tracer/testing/test_package.py (original)
+++ py/dist/py/apigen/tracer/testing/test_package.py Tue Oct 31 17:09:35 2006
@@ -45,3 +45,4 @@
methdesc = desc.fields['__init__']
assert isinstance(methdesc.inputcells[0], model.SomeInstance)
assert isinstance(methdesc.inputcells[1], model.SomeInt)
+
Modified: py/dist/py/apigen/tracer/tracer.py
==============================================================================
--- py/dist/py/apigen/tracer/tracer.py (original)
+++ py/dist/py/apigen/tracer/tracer.py Tue Oct 31 17:09:35 2006
@@ -28,31 +28,13 @@
# perform actuall tracing
frame = py.code.Frame(frame)
- frameid = '%s:%s' % (frame.code.filename, frame.code.firstlineno)
if event == 'call':
assert arg is None
self.docstorage.consider_call(frame,
py.code.Frame(sys._getframe(2)),
self.frame)
- self._locals[frameid] = frame.f_locals.copy()
elif event == 'return':
self.docstorage.consider_return(frame, arg)
- changeset = {}
- if frameid in self._locals:
- oldlocals = self._locals[frameid]
- newlocals = frame.f_locals
- __marker__ = []
- for k, v in newlocals.items():
- oldvalue = oldlocals.get(k, __marker__)
- if oldvalue is not v:
- if oldvalue is __marker__:
- changeset[k] = (NoValue, v)
- else:
- changeset[k] = (oldvalue, v)
- for k, v in oldlocals.items():
- if k not in newlocals:
- changeset[k] = (oldvalue, NoValue)
- self.docstorage.handle_local_changes(frame, changeset)
return self._tracer
def start_tracing(self):
More information about the pytest-commit
mailing list