fix function declarations inside of 'with' blocks
[cython.git] / Cython / Shadow.py
index ddfb3fc55700659239986c4d03fe28737367f319..e909a99031eeee29a0b52f6e711b25740b2d79da 100644 (file)
@@ -2,13 +2,29 @@
 
 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
+
+def test_fail_if_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,24 +54,24 @@ 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
 
 def typeof(arg):
     return type(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,66 +91,98 @@ 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]
-        elif value is None:
+        elif value is None or value is 0:
             self._items = []
         else:
             raise ValueError
-            
+
     def __getitem__(self, ix):
         if ix < 0:
             raise IndexError("negative indexing not allowed in C")
         return self._items[ix]
-        
+
     def __setitem__(self, ix, value):
         if ix < 0:
             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 not self._items and not value._items
+
 class ArrayType(PointerType):
-    
+
     def __init__(self):
         self._items = [None] * self._n
 
 
 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:
             self.__dict__[key] = cast(self._members[key], value)
         else:
             raise AttributeError("Struct has no member '%s'" % key)
-    
+
 
 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):
         if key in '__dict__':
             CythonType.__setattr__(self, key, value)
@@ -172,12 +220,11 @@ 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
-        
+
 
 
 py_int = int
@@ -214,7 +261,7 @@ for name in int_types:
     if name != 'Py_UNICODE' and not name.endswith('size_t'):
         gs['u'+name] = typedef(py_int)
         gs['s'+name] = typedef(py_int)
-    
+
 for name in float_types:
     gs[name] = typedef(py_float)
 
@@ -229,4 +276,4 @@ for t in int_types + float_types + complex_types + other_types:
         gs["%s_%s" % ('p'*i, t)] = globals()[t]._pointer(i)
 
 void = typedef(None)
-NULL = None
+NULL = p_void(0)