summaryrefslogtreecommitdiff
path: root/tests/run/annotation_typing.pyx
diff options
context:
space:
mode:
Diffstat (limited to 'tests/run/annotation_typing.pyx')
-rw-r--r--tests/run/annotation_typing.pyx251
1 files changed, 211 insertions, 40 deletions
diff --git a/tests/run/annotation_typing.pyx b/tests/run/annotation_typing.pyx
index 2582c3d03..7c49fea40 100644
--- a/tests/run/annotation_typing.pyx
+++ b/tests/run/annotation_typing.pyx
@@ -3,19 +3,28 @@
cimport cython
from cython cimport typeof
+from cpython.ref cimport PyObject
+
+try:
+ from typing import Optional
+except ImportError:
+ pass
-def old_dict_syntax(a: list, b: "int" = 2, c: {'ctype': 'long int'} = 3, d: {'type': 'float'} = 4) -> list:
+def old_dict_syntax(a: list, b: "int" = 2, c: {'ctype': 'long int'} = 3, d: {'type': 'long int'} = 4) -> list:
"""
>>> old_dict_syntax([1])
- ('list object', 'int', 'long', 'float')
- [1, 2, 3, 4.0]
+ ('list object', 'Python object', 'long', 'long')
+ [1, 2, 3, 4]
>>> old_dict_syntax([1], 3)
- ('list object', 'int', 'long', 'float')
- [1, 3, 3, 4.0]
+ ('list object', 'Python object', 'long', 'long')
+ [1, 3, 3, 4]
>>> old_dict_syntax(123)
Traceback (most recent call last):
TypeError: Argument 'a' has incorrect type (expected list, got int)
+ >>> old_dict_syntax(None)
+ Traceback (most recent call last):
+ TypeError: Argument 'a' has incorrect type (expected list, got NoneType)
"""
print(typeof(a), typeof(b), typeof(c), typeof(d))
a.append(b)
@@ -24,60 +33,77 @@ def old_dict_syntax(a: list, b: "int" = 2, c: {'ctype': 'long int'} = 3, d: {'ty
return a
-def pytypes_def(a: list, b: int = 2, c: long = 3, d: float = 4) -> list:
+def pytypes_def(a: list, b: int = 2, c: long = 3, d: float = 4.0, n: list = None, o: Optional[tuple] = ()) -> list:
"""
>>> pytypes_def([1])
- ('list object', 'Python object', 'Python object', 'double')
- [1, 2, 3, 4.0]
+ ('list object', 'Python object', 'Python object', 'double', 'list object', 'tuple object')
+ [1, 2, 3, 4.0, None, ()]
>>> pytypes_def([1], 3)
- ('list object', 'Python object', 'Python object', 'double')
- [1, 3, 3, 4.0]
+ ('list object', 'Python object', 'Python object', 'double', 'list object', 'tuple object')
+ [1, 3, 3, 4.0, None, ()]
+ >>> pytypes_def([1], 3, 2, 1, [], None)
+ ('list object', 'Python object', 'Python object', 'double', 'list object', 'tuple object')
+ [1, 3, 2, 1.0, [], None]
>>> pytypes_def(123)
Traceback (most recent call last):
TypeError: Argument 'a' has incorrect type (expected list, got int)
+ >>> pytypes_def(None)
+ Traceback (most recent call last):
+ TypeError: Argument 'a' has incorrect type (expected list, got NoneType)
"""
- print(typeof(a), typeof(b), typeof(c), typeof(d))
+ print(typeof(a), typeof(b), typeof(c), typeof(d), typeof(n), typeof(o))
a.append(b)
a.append(c)
a.append(d)
+ a.append(n)
+ a.append(o)
return a
-cpdef pytypes_cpdef(a: list, b: int = 2, c: long = 3, d: float = 4):
+cpdef pytypes_cpdef(a: list, b: int = 2, c: long = 3, d: float = 4.0, n: list = None, o: Optional[tuple] = ()):
"""
>>> pytypes_cpdef([1])
- ('list object', 'Python object', 'Python object', 'double')
- [1, 2, 3, 4.0]
+ ('list object', 'Python object', 'Python object', 'double', 'list object', 'tuple object')
+ [1, 2, 3, 4.0, None, ()]
>>> pytypes_cpdef([1], 3)
- ('list object', 'Python object', 'Python object', 'double')
- [1, 3, 3, 4.0]
+ ('list object', 'Python object', 'Python object', 'double', 'list object', 'tuple object')
+ [1, 3, 3, 4.0, None, ()]
+ >>> pytypes_cpdef([1], 3, 2, 1, [], None)
+ ('list object', 'Python object', 'Python object', 'double', 'list object', 'tuple object')
+ [1, 3, 2, 1.0, [], None]
>>> pytypes_cpdef(123)
Traceback (most recent call last):
TypeError: Argument 'a' has incorrect type (expected list, got int)
+ >>> pytypes_cpdef(None)
+ Traceback (most recent call last):
+ TypeError: Argument 'a' has incorrect type (expected list, got NoneType)
"""
- print(typeof(a), typeof(b), typeof(c), typeof(d))
+ print(typeof(a), typeof(b), typeof(c), typeof(d), typeof(n), typeof(o))
a.append(b)
a.append(c)
a.append(d)
+ a.append(n)
+ a.append(o)
return a
-cdef c_pytypes_cdef(a: list, b: int = 2, c: long = 3, d: float = 4):
- print(typeof(a), typeof(b), typeof(c), typeof(d))
+cdef c_pytypes_cdef(a: list, b: int = 2, c: long = 3, d: float = 4.0, n: list = None):
+ print(typeof(a), typeof(b), typeof(c), typeof(d), typeof(n))
a.append(b)
a.append(c)
a.append(d)
+ a.append(n)
return a
def pytypes_cdef(a, b=2, c=3, d=4):
"""
>>> pytypes_cdef([1])
- ('list object', 'Python object', 'Python object', 'double')
- [1, 2, 3, 4.0]
+ ('list object', 'Python object', 'Python object', 'double', 'list object')
+ [1, 2, 3, 4.0, None]
>>> pytypes_cdef([1], 3)
- ('list object', 'Python object', 'Python object', 'double')
- [1, 3, 3, 4.0]
+ ('list object', 'Python object', 'Python object', 'double', 'list object')
+ [1, 3, 3, 4.0, None]
>>> pytypes_cdef(123) # doctest: +ELLIPSIS
Traceback (most recent call last):
TypeError: ...
@@ -85,6 +111,15 @@ def pytypes_cdef(a, b=2, c=3, d=4):
return c_pytypes_cdef(a, b, c, d)
+def pyint(a: int):
+ """
+ >>> large_int = eval('0x'+'F'*64) # definitely bigger than C int64
+ >>> pyint(large_int) == large_int
+ True
+ """
+ return a
+
+
def ctypes_def(a: list, b: cython.int = 2, c: cython.long = 3, d: cython.float = 4) -> list:
"""
>>> ctypes_def([1])
@@ -114,6 +149,15 @@ def return_tuple_for_carray() -> tuple:
return x
+def invalid_ctuple_syntax(a: (cython.int, cython.int), b: (int, int)):
+ """
+ >>> invalid_ctuple_syntax([1, 2], [3, 4])
+ [1, 2, 3, 4]
+ """
+ result: (cython.int, cython.int, cython.int, cython.int) = a + b
+ return result
+
+
MyStruct = cython.struct(x=cython.int, y=cython.int, data=cython.double)
@@ -123,6 +167,9 @@ def struct_io(s : MyStruct) -> MyStruct:
>>> d = struct_io(dict(x=1, y=2, data=3))
>>> sorted(d.items())
[('data', 3.0), ('x', 2), ('y', 1)]
+ >>> d = struct_io(None)
+ Traceback (most recent call last):
+ TypeError: Expected a mapping, got NoneType
"""
t = s
t.x, t.y = s.y, s.x
@@ -142,6 +189,9 @@ def call_struct_io(s : MyStruct) -> MyStruct:
>>> d = call_struct_io(dict(x=1, y=2, data=3))
>>> sorted(d.items())
[('data', 3.0), ('x', 2), ('y', 1)]
+ >>> d = call_struct_io(None)
+ Traceback (most recent call last):
+ TypeError: Expected a mapping, got NoneType
"""
return struct_io(s)
@@ -196,6 +246,37 @@ def call_exception_default(raise_exc=False):
return exception_default(raise_exc)
+@cython.test_assert_path_exists(
+ "//CFuncDefNode",
+ "//CFuncDefNode//DefNode",
+ "//CFuncDefNode[@return_type]",
+ "//CFuncDefNode[@return_type.is_int = True]",
+)
+@cython.ccall
+def exception_default_uint(raise_exc : cython.bint = False) -> cython.uint:
+ """
+ >>> print(exception_default_uint(raise_exc=False))
+ 10
+ >>> exception_default_uint(raise_exc=True)
+ Traceback (most recent call last):
+ ValueError: huhu!
+ """
+ if raise_exc:
+ raise ValueError("huhu!")
+ return 10
+
+
+def call_exception_default_uint(raise_exc=False):
+ """
+ >>> print(call_exception_default_uint(raise_exc=False))
+ 10
+ >>> call_exception_default_uint(raise_exc=True)
+ Traceback (most recent call last):
+ ValueError: huhu!
+ """
+ return exception_default_uint(raise_exc)
+
+
class EarlyClass(object):
"""
>>> a = EarlyClass(1)
@@ -215,34 +296,124 @@ class LateClass(object):
pass
-def py_float_default(price : float=None, ndigits=4):
+def py_float_default(price : Optional[float]=None, ndigits=4):
"""
Python default arguments should prevent C type inference.
>>> py_float_default()
(None, 4)
- >>> py_float_default(2)
- (2, 4)
+ >>> py_float_default(None)
+ (None, 4)
+ >>> py_float_default(2) # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ TypeError: ...float...
>>> py_float_default(2.0)
(2.0, 4)
- >>> py_float_default(2, 3)
- (2, 3)
+ >>> py_float_default(2, 3) # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ TypeError: ...float...
"""
return price, ndigits
+cdef class ClassAttribute:
+ cls_attr : cython.float = 1.
+
+
+@cython.cfunc
+def take_ptr(obj: cython.pointer(PyObject)):
+ pass
+
+def call_take_ptr():
+ """
+ >>> call_take_ptr() # really just a compile-test
+ """
+ python_dict = {"abc": 123}
+ take_ptr(cython.cast(cython.pointer(PyObject), python_dict))
+
+@cython.cclass
+class HasPtr:
+ """
+ >>> HasPtr()
+ HasPtr(1, 1)
+ """
+ a: cython.pointer(cython.int)
+ b: cython.int
+
+ def __init__(self):
+ self.b = 1
+ self.a = cython.address(self.b)
+ def __repr__(self):
+ return f"HasPtr({self.a[0]}, {self.b})"
+
+
+@cython.annotation_typing(False)
+def turn_off_typing(x: float, d: dict):
+ """
+ >>> turn_off_typing('not a float', []) # ignore the typing
+ ('Python object', 'Python object', 'not a float', [])
+ """
+ return typeof(x), typeof(d), x, d
+
+
+@cython.annotation_typing(False)
+cdef class ClassTurnOffTyping:
+ x: float
+ d: dict
+
+ def get_var_types(self, arg: float):
+ """
+ >>> ClassTurnOffTyping().get_var_types(1.0)
+ ('Python object', 'Python object', 'Python object')
+ """
+ return typeof(self.x), typeof(self.d), typeof(arg)
+
+ @cython.annotation_typing(True)
+ def and_turn_it_back_on_again(self, arg: float):
+ """
+ >>> ClassTurnOffTyping().and_turn_it_back_on_again(1.0)
+ ('Python object', 'Python object', 'double')
+ """
+ return typeof(self.x), typeof(self.d), typeof(arg)
+
+
+from cython cimport int as cy_i
+
+
+def int_alias(a: cython.int, b: cy_i):
+ """
+ >>> int_alias(1, 2)
+ int
+ int
+ """
+ print(cython.typeof(a))
+ print(cython.typeof(b))
+
+
_WARNINGS = """
-8:32: Strings should no longer be used for type declarations. Use 'cython.int' etc. directly.
-8:47: Dicts should no longer be used as type annotations. Use 'cython.int' etc. directly.
-8:56: Strings should no longer be used for type declarations. Use 'cython.int' etc. directly.
-8:77: Dicts should no longer be used as type annotations. Use 'cython.int' etc. directly.
-8:85: Python type declaration in signature annotation does not refer to a Python type
-8:85: Strings should no longer be used for type declarations. Use 'cython.int' etc. directly.
-211:44: Unknown type declaration in annotation, ignoring
-218:29: Ambiguous types in annotation, ignoring
+14:32: Strings should no longer be used for type declarations. Use 'cython.int' etc. directly.
+14:47: Dicts should no longer be used as type annotations. Use 'cython.int' etc. directly.
+14:56: Strings should no longer be used for type declarations. Use 'cython.int' etc. directly.
+14:77: Dicts should no longer be used as type annotations. Use 'cython.int' etc. directly.
+14:85: Python type declaration in signature annotation does not refer to a Python type
+14:85: Strings should no longer be used for type declarations. Use 'cython.int' etc. directly.
+36:40: Found Python 2.x type 'long' in a Python annotation. Did you mean to use 'cython.long'?
+36:66: PEP-484 recommends 'typing.Optional[...]' for arguments that can be None.
+63:44: Found Python 2.x type 'long' in a Python annotation. Did you mean to use 'cython.long'?
+63:70: PEP-484 recommends 'typing.Optional[...]' for arguments that can be None.
+90:44: Found Python 2.x type 'long' in a Python annotation. Did you mean to use 'cython.long'?
+90:70: PEP-484 recommends 'typing.Optional[...]' for arguments that can be None.
+152:30: Tuples cannot be declared as simple tuples of types. Use 'tuple[type1, type2, ...]'.
+152:59: Tuples cannot be declared as simple tuples of types. Use 'tuple[type1, type2, ...]'.
+157:13: Tuples cannot be declared as simple tuples of types. Use 'tuple[type1, type2, ...]'.
+292:44: Unknown type declaration in annotation, ignoring
+320:15: Annotation ignored since class-level attributes must be Python objects. Were you trying to set up an instance attribute?
+# DUPLICATE:
+63:44: Found Python 2.x type 'long' in a Python annotation. Did you mean to use 'cython.long'?
# BUG:
-46:6: 'pytypes_cpdef' redeclared
-121:0: 'struct_io' redeclared
-156:0: 'struct_convert' redeclared
-175:0: 'exception_default' redeclared
+63:6: 'pytypes_cpdef' redeclared
+164:0: 'struct_io' redeclared
+199:0: 'struct_convert' redeclared
+218:0: 'exception_default' redeclared
+249:0: 'exception_default_uint' redeclared
"""