summaryrefslogtreecommitdiff
path: root/tests/run/fused_cpdef.pyx
diff options
context:
space:
mode:
Diffstat (limited to 'tests/run/fused_cpdef.pyx')
-rw-r--r--tests/run/fused_cpdef.pyx127
1 files changed, 116 insertions, 11 deletions
diff --git a/tests/run/fused_cpdef.pyx b/tests/run/fused_cpdef.pyx
index 0b63c8b98..3378a5083 100644
--- a/tests/run/fused_cpdef.pyx
+++ b/tests/run/fused_cpdef.pyx
@@ -1,13 +1,17 @@
+# cython: language_level=3str
+# mode: run
+
cimport cython
+import sys, io
cy = __import__("cython")
cpdef func1(self, cython.integral x):
- print "%s," % (self,),
+ print(f"{self},", end=' ')
if cython.integral is int:
- print 'x is int', x, cython.typeof(x)
+ print('x is int', x, cython.typeof(x))
else:
- print 'x is long', x, cython.typeof(x)
+ print('x is long', x, cython.typeof(x))
class A(object):
@@ -16,6 +20,18 @@ class A(object):
def __str__(self):
return "A"
+cdef class B:
+ cpdef int meth(self, cython.integral x):
+ print(f"{self},", end=' ')
+ if cython.integral is int:
+ print('x is int', x, cython.typeof(x))
+ else:
+ print('x is long', x, cython.typeof(x))
+ return 0
+
+ def __str__(self):
+ return "B"
+
pyfunc = func1
def test_fused_cpdef():
@@ -32,23 +48,71 @@ def test_fused_cpdef():
A, x is long 2 long
A, x is long 2 long
A, x is long 2 long
+ <BLANKLINE>
+ B, x is long 2 long
"""
func1[int](None, 2)
func1[long](None, 2)
func1(None, 2)
- print
+ print()
pyfunc[cy.int](None, 2)
pyfunc(None, 2)
- print
+ print()
A.meth[cy.int](A(), 2)
A.meth(A(), 2)
A().meth[cy.long](2)
A().meth(2)
+ print()
+
+ B().meth(2)
+
+
+midimport_run = io.StringIO()
+if sys.version_info.major < 3:
+ # Monkey-patch midimport_run.write to accept non-unicode strings under Python 2.
+ midimport_run.write = lambda c: io.StringIO.write(midimport_run, unicode(c))
+
+realstdout = sys.stdout
+sys.stdout = midimport_run
+
+try:
+ # Run `test_fused_cpdef()` during import and save the result for
+ # `test_midimport_run()`.
+ test_fused_cpdef()
+except Exception as e:
+ midimport_run.write(f"{e!r}\n")
+finally:
+ sys.stdout = realstdout
+
+def test_midimport_run():
+ # At one point, dynamically calling fused cpdef functions during import
+ # would fail because the type signature-matching indices weren't
+ # yet initialized.
+ # (See Compiler.FusedNode.FusedCFuncDefNode._fused_signature_index,
+ # GH-3366.)
+ """
+ >>> test_midimport_run()
+ None, x is int 2 int
+ None, x is long 2 long
+ None, x is long 2 long
+ <BLANKLINE>
+ None, x is int 2 int
+ None, x is long 2 long
+ <BLANKLINE>
+ A, x is int 2 int
+ A, x is long 2 long
+ A, x is long 2 long
+ A, x is long 2 long
+ <BLANKLINE>
+ B, x is long 2 long
+ """
+ print(midimport_run.getvalue(), end='')
+
def assert_raise(func, *args):
try:
@@ -70,23 +134,31 @@ def test_badcall():
assert_raise(A.meth)
assert_raise(A().meth[cy.int])
assert_raise(A.meth[cy.int])
+ assert_raise(B().meth, 1, 2, 3)
+
+def test_nomatch():
+ """
+ >>> func1(None, ())
+ Traceback (most recent call last):
+ TypeError: No matching signature found
+ """
ctypedef long double long_double
cpdef multiarg(cython.integral x, cython.floating y):
if cython.integral is int:
- print "x is an int,",
+ print("x is an int,", end=' ')
else:
- print "x is a long,",
+ print("x is a long,", end=' ')
if cython.floating is long_double:
- print "y is a long double:",
+ print("y is a long double:", end=' ')
elif float is cython.floating:
- print "y is a float:",
+ print("y is a float:", end=' ')
else:
- print "y is a double:",
+ print("y is a double:", end=' ')
- print x, y
+ print(x, y)
def test_multiarg():
"""
@@ -104,3 +176,36 @@ def test_multiarg():
multiarg[int, float](1, 2.0)
multiarg[cy.int, cy.float](1, 2.0)
multiarg(4, 5.0)
+
+def test_ambiguousmatch():
+ """
+ >>> multiarg(5, ())
+ Traceback (most recent call last):
+ TypeError: Function call with ambiguous argument types
+ >>> multiarg((), 2.0)
+ Traceback (most recent call last):
+ TypeError: Function call with ambiguous argument types
+ """
+
+# https://github.com/cython/cython/issues/4409
+# default arguments + fused cpdef were crashing
+cpdef literal_default(cython.integral x, some_string="value"):
+ return x, some_string
+
+cpdef mutable_default(cython.integral x, some_value=[]):
+ some_value.append(x)
+ return some_value
+
+def test_defaults():
+ """
+ >>> literal_default(1)
+ (1, 'value')
+ >>> literal_default(1, "hello")
+ (1, 'hello')
+ >>> mutable_default(1)
+ [1]
+ >>> mutable_default(2)
+ [1, 2]
+ >>> mutable_default(3,[])
+ [3]
+ """