improved the pure Python shadow module
authorHaoyu Bai <baihaoyu@gmail.com>
Thu, 31 Mar 2011 18:37:42 +0000 (02:37 +0800)
committerHaoyu Bai <baihaoyu@gmail.com>
Thu, 31 Mar 2011 19:36:19 +0000 (03:36 +0800)
Cython/Shadow.py
tests/run/pure_py.py

index d0e401ea81bf6ecc988f1705da90bdc7302e0843..085ed8650ac74586ecb458d8d10cb817bb814752 100644 (file)
@@ -2,13 +2,26 @@
 
 compiled = False
 
-def empty_decorator(x):
-    return x
+_Unspecified = object()
 
 # Function decorators
 
+def _empty_decorator(x):
+    return x
+
 def locals(**arg_types):
-    return empty_decorator
+    return _empty_decorator
+
+def test_assert_path_exists(path):
+    return _empty_decorator
+
+class _EmptyDecoratorAndManager(object):
+    def __call__(self, x):
+        return x
+    def __enter__(self):
+        pass
+    def __exit__(self, exc_type, exc_value, traceback):
+        pass
 
 def inline(f, *args, **kwds):
   if isinstance(f, basestring):
@@ -38,11 +51,11 @@ def cmod(a, b):
 
 # Emulated language constructs
 
-def cast(type, arg):
+def cast(type, *args):
     if hasattr(type, '__call__'):
-        return type(arg)
+        return type(*args)
     else:
-        return arg
+        return args[0]
 
 def sizeof(arg):
     return 1
@@ -53,9 +66,9 @@ def typeof(arg):
 def address(arg):
     return pointer(type(arg))([arg])
 
-def declare(type=None, value=None, **kwds):
+def declare(type=None, value=_Unspecified, **kwds):
     if type is not None and hasattr(type, '__call__'):
-        if value:
+        if value is not _Unspecified:
             return type(value)
         else:
             return type()
@@ -75,21 +88,24 @@ del _nogil
 
 # Emulated types
 
-class CythonType(object):
+class CythonMetaType(type):
+
+    def __getitem__(type, ix):
+        return array(type, ix)
+
+CythonTypeObject = CythonMetaType('CythonTypeObject', (object,), {})
+
+class CythonType(CythonTypeObject):
 
     def _pointer(self, n=1):
         for i in range(n):
             self = pointer(self)
         return self
 
-    def __getitem__(self, ix):
-        return array(self, ix)
-
-
 class PointerType(CythonType):
 
     def __init__(self, value=None):
-        if isinstance(value, ArrayType):
+        if isinstance(value, (ArrayType, PointerType)):
             self._items = [cast(self._basetype, a) for a in value._items]
         elif isinstance(value, list):
             self._items = [cast(self._basetype, a) for a in value]
@@ -108,6 +124,14 @@ class PointerType(CythonType):
             raise IndexError("negative indexing not allowed in C")
         self._items[ix] = cast(self._basetype, value)
 
+    def __eq__(self, value):
+        if value is None and not self._items:
+            return True
+        elif type(self) != type(value):
+            return False
+        else:
+            return self._items == value._items
+
 class ArrayType(PointerType):
 
     def __init__(self):
@@ -116,9 +140,18 @@ class ArrayType(PointerType):
 
 class StructType(CythonType):
 
-    def __init__(self, **data):
-        for key, value in data.iteritems():
-            setattr(self, key, value)
+    def __init__(self, cast_from=_Unspecified, **data):
+        if cast_from is not _Unspecified:
+            # do cast
+            if len(data) > 0:
+                raise ValueError('Cannot accept keyword arguments when casting.')
+            if type(cast_from) is not type(self):
+                raise ValueError('Cannot cast from %s'%cast_from)
+            for key, value in cast_from.__dict__.items():
+                setattr(self, key, value)
+        else:
+            for key, value in data.iteritems():
+                setattr(self, key, value)
 
     def __setattr__(self, key, value):
         if key in self._members:
@@ -129,10 +162,22 @@ class StructType(CythonType):
 
 class UnionType(CythonType):
 
-    def __init__(self, **data):
-        if len(data) > 0:
+    def __init__(self, cast_from=_Unspecified, **data):
+        if cast_from is not _Unspecified:
+            # do type cast
+            if len(data) > 0:
+                raise ValueError('Cannot accept keyword arguments when casting.')
+            if isinstance(cast_from, dict):
+                datadict = cast_from
+            elif type(cast_from) is type(self):
+                datadict = cast_from.__dict__
+            else:
+                raise ValueError('Cannot cast from %s'%cast_from)
+        else:
+            datadict = data
+        if len(datadict) > 1:
             raise AttributeError("Union can only store one field at a time.")
-        for key, value in data.iteritems():
+        for key, value in datadict.iteritems():
             setattr(self, key, value)
 
     def __setattr__(self, key, value):
@@ -173,9 +218,8 @@ class typedef(CythonType):
     def __init__(self, type):
         self._basetype = type
 
-    def __call__(self, value=None):
-        if value is not None:
-            value = cast(self._basetype, value)
+    def __call__(self, *arg):
+        value = cast(self._basetype, *arg)
         return value
 
 
@@ -230,3 +274,4 @@ for t in int_types + float_types + complex_types + other_types:
 
 void = typedef(None)
 NULL = None
+
index 3adfb3716c3cee53f52e4486d81e03884820dc71..cd0b46d486cce833c619fc5dbcf2d6a5739c7d3e 100644 (file)
@@ -19,26 +19,24 @@ def test_sizeof():
     else:
         print(cython.sizeof(cython.char) == 1)
 
-## CURRENTLY BROKEN - FIXME!!
-
-## def test_declare(n):
-##     """
-##     >>> test_declare(100)
-##     (100, 100)
-##     >>> test_declare(100.5)
-##     (100, 100)
-##     >>> test_declare(None)
-##     Traceback (most recent call last):
-##     ...
-##     TypeError: an integer is required
-##     """
-##     x = cython.declare(cython.int)
-##     y = cython.declare(cython.int, n)
-##     if cython.compiled:
-##         cython.declare(xx=cython.int, yy=cython.long)
-##         i = sizeof(xx)
-##     ptr = cython.declare(cython.p_int, cython.address(y))
-##     return y, ptr[0]
+def test_declare(n):
+    """
+    >>> test_declare(100)
+    (100, 100)
+    >>> test_declare(100.5)
+    (100, 100)
+    >>> test_declare(None) #doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ...
+    TypeError: ...
+    """
+    x = cython.declare(cython.int)
+    y = cython.declare(cython.int, n)
+    if cython.compiled:
+        cython.declare(xx=cython.int, yy=cython.long)
+        i = sizeof(xx)
+    ptr = cython.declare(cython.p_int, cython.address(y))
+    return y, ptr[0]
 
 @cython.locals(x=cython.double, n=cython.int)
 def test_cast(x):
@@ -59,6 +57,7 @@ def test_address(x):
     return y[0]
 
 ## CURRENTLY BROKEN - FIXME!!
+## Is this test make sense? Implicit conversion in pure Python??
 
 ## @cython.locals(x=cython.int)
 ## @cython.locals(y=cython.bint)
@@ -93,21 +92,19 @@ def test_with_nogil(nogil):
             result = True
     return result
 
-## CURRENTLY BROKEN - FIXME!!
+MyUnion = cython.union(n=cython.int, x=cython.double)
+MyStruct = cython.struct(is_integral=cython.bint, data=MyUnion)
+MyStruct2 = cython.typedef(MyStruct[2])
 
-## MyUnion = cython.union(n=cython.int, x=cython.double)
-## MyStruct = cython.struct(is_integral=cython.bint, data=MyUnion)
-## MyStruct2 = cython.typedef(MyStruct[2])
-
-## def test_struct(n, x):
-##     """
-##     >>> test_struct(389, 1.64493)
-##     (389, 1.64493)
-##     """
-##     a = cython.declare(MyStruct2)
-##     a[0] = MyStruct(True, data=MyUnion(n=n))
-##     a[1] = MyStruct(is_integral=False, data={'x': x})
-##     return a[0].data.n, a[1].data.x
+def test_struct(n, x):
+    """
+    >>> test_struct(389, 1.64493)
+    (389, 1.64493)
+    """
+    a = cython.declare(MyStruct2)
+    a[0] = MyStruct(is_integral=True, data=MyUnion(n=n))
+    a[1] = MyStruct(is_integral=False, data={'x': x})
+    return a[0].data.n, a[1].data.x
 
 import cython as cy
 from cython import declare, cast, locals, address, typedef, p_void, compiled
@@ -116,24 +113,21 @@ from cython import declare as my_declare, locals as my_locals, p_void as my_void
 @my_locals(a=cython.p_void)
 def test_imports():
     """
-    >>> test_imports()  # (True, True)
-    True
+    >>> test_imports()
+    (True, True)
     """
     a = cython.NULL
     b = declare(p_void, cython.NULL)
     c = my_declare(my_void_star, cython.NULL)
     d = cy.declare(cy.p_void, cython.NULL)
 
-    ## CURRENTLY BROKEN - FIXME!!
-    #return a == d, compiled == my_compiled
-
-    return compiled == my_compiled
+    return a == d, compiled == my_compiled
 
 ## CURRENTLY BROKEN - FIXME!!
 
-## MyStruct3 = typedef(MyStruct[3])
-## MyStruct4 = my_typedef(MyStruct[4])
-## MyStruct5 = cy.typedef(MyStruct[5])
+# MyStruct3 = typedef(MyStruct[3])
+# MyStruct4 = my_typedef(MyStruct[4])
+# MyStruct5 = cy.typedef(MyStruct[5])
 
 def test_declare_c_types(n):
     """