[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