[py-svn] r32868 - in py/branch/apigen/py: code test/tracer test/tracer/testing
fijal at codespeak.net
fijal at codespeak.net
Wed Oct 4 13:48:46 CEST 2006
Author: fijal
Date: Wed Oct 4 13:48:43 2006
New Revision: 32868
Added:
py/branch/apigen/py/test/tracer/
py/branch/apigen/py/test/tracer/__init__.py (contents, props changed)
py/branch/apigen/py/test/tracer/testing/
py/branch/apigen/py/test/tracer/testing/test_docgen.py (contents, props changed)
py/branch/apigen/py/test/tracer/tracer.py (contents, props changed)
Modified:
py/branch/apigen/py/code/code.py
py/branch/apigen/py/code/frame.py
Log:
Added simple wrappers.
Added first test for type gathering of functions. Need to steal something from pypy annotation suite.
Modified: py/branch/apigen/py/code/code.py
==============================================================================
--- py/branch/apigen/py/code/code.py (original)
+++ py/branch/apigen/py/code/code.py Wed Oct 4 13:48:43 2006
@@ -68,3 +68,7 @@
fullsource = property(fullsource, None, None,
"full source containing this code object")
+ def getargs(self):
+ # handfull shortcut for getting args
+ raw = self.raw
+ return raw.co_varnames[:raw.co_argcount]
Modified: py/branch/apigen/py/code/frame.py
==============================================================================
--- py/branch/apigen/py/code/frame.py (original)
+++ py/branch/apigen/py/code/frame.py Wed Oct 4 13:48:43 2006
@@ -31,5 +31,3 @@
def is_true(self, object):
return object
-
-
Added: py/branch/apigen/py/test/tracer/__init__.py
==============================================================================
Added: py/branch/apigen/py/test/tracer/testing/test_docgen.py
==============================================================================
--- (empty file)
+++ py/branch/apigen/py/test/tracer/testing/test_docgen.py Wed Oct 4 13:48:43 2006
@@ -0,0 +1,29 @@
+
+""" test doc generation
+"""
+
+import py
+import sys
+
+from py.__.test.tracer.tracer import DocStorage, Tracer
+
+#def setup_module(mod):
+# data_path = py.path.local(mod.__file__).dirpath().join("data")
+# sys.path.insert(0, str(data_path))
+
+def fun(a, b, c):
+ return "d"
+
+def test_basic():
+ descs = {"fun":fun}
+ ds = DocStorage.from_dict(descs)
+ t = Tracer(ds)
+ t.start_tracing()
+ fun(1, ("g", 3), 8)
+ t.end_tracing()
+ funcdesc = ds.descs[0]
+ assert funcdesc.fullname == 'fun'
+ assert len(funcdesc.args) == 3
+ assert funcdesc.args['a']._type is int
+ assert funcdesc.args['b']._type is tuple
+ assert funcdesc.args['c']._type is int
Added: py/branch/apigen/py/test/tracer/tracer.py
==============================================================================
--- (empty file)
+++ py/branch/apigen/py/test/tracer/tracer.py Wed Oct 4 13:48:43 2006
@@ -0,0 +1,126 @@
+
+""" simple tracer for API generation
+"""
+
+import py
+import sys
+import types
+
+# We have to steal as much as possible from union of types
+# from pypy's code.
+# BLAH BLAH BLAH
+
+class UnionError(Exception):
+ pass
+
+class TypeDesc(object):
+ def __init__(self, _type):
+ self._type = _type
+
+ def generalize(self, _type):
+ if self._type is _type:
+ return
+ raise UnionError("%r and %r incompatible" % (self._type, _type))
+
+class FuncDesc(object):
+ """ XXX This is totally random description used for testing.
+ We'll need descriptions for all tracked object types
+ """
+ def __init__(self, fullname, obj):
+ self.fullname = fullname
+ self.obj = obj
+ self.args = {}
+
+ def check_is(self, frame):
+ return self.obj.func_code is frame.code.raw
+
+ def __eq__(self, other):
+ return self.fullname == other.fullname and self.obj is other.obj
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ def __hash__(self):
+ return hash(self.fullname)
+
+ def consider_call(self, frame):
+ assert isinstance(frame, py.code.Frame)
+ for arg in frame.code.getargs():
+ self.setarg(arg, frame.f_locals[arg])
+
+ def setarg(self, arg, value):
+ # set argument annotation
+ if arg in self.args:
+ self.args[arg].generalize(type(value))
+ else:
+ self.args[arg] = TypeDesc(type(value))
+
+def make_desc(fullname, obj):
+ # XXX hash it at some point
+ if type(obj) is types.FunctionType:
+ return FuncDesc(fullname, obj)
+ raise NotImplementedError("%r type has no description" % type(obj))
+
+class DocStorage(object):
+ """ Class storing info about API
+ """
+ def __init__(self, descs):
+ self.descs = descs
+
+ def consider_call(self, frame):
+ # check if we have available description for that call
+ self.frame = frame
+ desc = self.check_desc(frame)
+ if not desc:
+ return
+ desc.consider_call(frame)
+
+ def consider_return(self, frame, arg):
+ pass
+
+ def check_desc(self, frame):
+ assert isinstance(frame, py.code.Frame)
+ for desc in self.descs:
+ if desc.check_is(frame):
+ return desc
+ return None
+
+ def from_pkg(self, module):
+ """ Initialize DocStorage from module.__package__
+ """
+ # all elements should be stored in some kind of dictionary.
+ # they're usually not hashable, so we are creating some
+ # descriptions of them
+ descs = [make_desc(key, val) for key, val in
+ module.__package__.__dict__.iteritems()]
+ return DocStorage(descs)
+ from_pkg = staticmethod(from_pkg)
+
+ def from_dict(_dict):
+ return DocStorage([make_desc(key, val) for key, val in _dict.iteritems()])
+ from_dict = staticmethod(from_dict)
+
+class Tracer(object):
+ """ Basic tracer object, used for gathering additional info
+ about API functions
+ """
+ def __init__(self, docstorage):
+ self.docstorage = docstorage
+
+ def _tracer(self, frame, event, arg):
+
+ # perform actuall tracing
+ frame = py.code.Frame(frame)
+ if event == 'call':
+ assert arg is None
+ self.docstorage.consider_call(frame)
+ elif event == 'return':
+ self.docstorage.consider_return(frame, arg)
+
+ return self._tracer
+
+ def start_tracing(self):
+ sys.settrace(self._tracer)
+
+ def end_tracing(self):
+ sys.settrace(None)
More information about the pytest-commit
mailing list