From a13fab256a308d4ccd1b545aa932607b35de9e2e Mon Sep 17 00:00:00 2001 From: Haoyu Bai Date: Fri, 1 Apr 2011 02:37:42 +0800 Subject: [PATCH] improved the pure Python shadow module --- Cython/Shadow.py | 91 +++++++++++++++++++++++++++++++++----------- tests/run/pure_py.py | 80 ++++++++++++++++++-------------------- 2 files changed, 105 insertions(+), 66 deletions(-) diff --git a/Cython/Shadow.py b/Cython/Shadow.py index d0e401ea..085ed865 100644 --- a/Cython/Shadow.py +++ b/Cython/Shadow.py @@ -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 + diff --git a/tests/run/pure_py.py b/tests/run/pure_py.py index 3adfb371..cd0b46d4 100644 --- a/tests/run/pure_py.py +++ b/tests/run/pure_py.py @@ -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): """ -- 2.26.2