summaryrefslogtreecommitdiff
path: root/tests/run/pep442_tp_finalize.pyx
diff options
context:
space:
mode:
Diffstat (limited to 'tests/run/pep442_tp_finalize.pyx')
-rw-r--r--tests/run/pep442_tp_finalize.pyx382
1 files changed, 382 insertions, 0 deletions
diff --git a/tests/run/pep442_tp_finalize.pyx b/tests/run/pep442_tp_finalize.pyx
new file mode 100644
index 000000000..6532757f9
--- /dev/null
+++ b/tests/run/pep442_tp_finalize.pyx
@@ -0,0 +1,382 @@
+# mode: run
+
+from __future__ import print_function
+
+cimport cython
+
+import gc
+
+cdef class nontrivial_del:
+ def __init__(self):
+ print("init")
+
+ def __del__(self):
+ print("del")
+
+def test_del():
+ """
+ >>> test_del()
+ start
+ init
+ del
+ finish
+ """
+ print("start")
+ d = nontrivial_del()
+ d = None
+ gc.collect()
+ print("finish")
+
+
+cdef class del_and_dealloc:
+ def __init__(self):
+ print("init")
+
+ def __del__(self):
+ print("del")
+
+ def __dealloc__(self):
+ print("dealloc")
+
+def test_del_and_dealloc():
+ """
+ >>> test_del_and_dealloc()
+ start
+ init
+ del
+ dealloc
+ finish
+ """
+ print("start")
+ d = del_and_dealloc()
+ d = None
+ gc.collect()
+ print("finish")
+
+@cython.final
+cdef class FinalClass:
+ def __init__(self):
+ print("init")
+ def __del__(self):
+ print("del")
+
+def test_final_class():
+ """
+ >>> test_final_class()
+ start
+ init
+ del
+ finish
+ """
+ print("start")
+ d = FinalClass()
+ d = None
+ gc.collect()
+ print("finish")
+
+@cython.final
+cdef class FinalInherits(nontrivial_del):
+ def __init__(self):
+ super().__init__()
+ print("FinalInherits init")
+ # no __del__ but nontrivial_del should still be called
+ def __dealloc__(self):
+ pass # define __dealloc__ so as not to fall back on base __dealloc__
+
+def test_final_inherited():
+ """
+ >>> test_final_inherited()
+ start
+ init
+ FinalInherits init
+ del
+ finish
+ """
+ print("start")
+ d = FinalInherits()
+ d = None
+ gc.collect()
+ print("finish")
+
+cdef class DummyBase:
+ pass
+
+class RegularClass:
+ __slots__ = ()
+ def __del__(self):
+ print("del")
+
+@cython.final
+cdef class FinalMultipleInheritance(DummyBase, RegularClass):
+ def __init__(self):
+ super().__init__()
+ print("init")
+ def __dealloc__(self):
+ pass
+
+def test_final_multiple_inheritance():
+ """
+ >>> test_final_multiple_inheritance()
+ start
+ init
+ del
+ finish
+ """
+ print("start")
+ d = FinalMultipleInheritance()
+ d = None
+ gc.collect()
+ print("finish")
+
+cdef class del_with_exception:
+ def __init__(self):
+ print("init")
+
+ def __del__(self):
+ print("del")
+ raise Exception("Error")
+
+def test_del_with_exception():
+ """
+ >>> test_del_with_exception()
+ start
+ init
+ del
+ finish
+ """
+ print("start")
+ d = nontrivial_del()
+ d = None
+ gc.collect()
+ print("finish")
+
+
+def test_nontrivial_del_with_exception():
+ """
+ >>> test_nontrivial_del_with_exception()
+ start
+ init
+ del
+ end
+ """
+ print("start")
+ def inner():
+ c = nontrivial_del()
+ raise RuntimeError()
+
+ try:
+ inner()
+ except RuntimeError:
+ pass
+
+ print("end")
+
+
+cdef class parent:
+ def __del__(self):
+ print("del parent")
+
+class child(parent):
+ def __del__(self):
+ print("del child")
+
+def test_del_inheritance():
+ """
+ >>> test_del_inheritance()
+ start
+ del child
+ finish
+ """
+ print("start")
+ c = child()
+ c = None
+ gc.collect()
+ print("finish")
+
+
+cdef class cy_parent:
+ def __del__(self):
+ print("del cy_parent")
+
+ def __dealloc__(self):
+ print("dealloc cy_parent")
+
+class py_parent:
+ def __del__(self):
+ print("del py_parent")
+
+class multi_child(cy_parent, py_parent):
+ def __del__(self):
+ print("del child")
+
+def test_multiple_inheritance():
+ """
+ >>> test_multiple_inheritance()
+ start
+ del child
+ dealloc cy_parent
+ finish
+ """
+ print("start")
+ c = multi_child()
+ c = None
+ gc.collect()
+ print("finish")
+
+
+cdef class zombie_object:
+ def __del__(self):
+ global global_zombie_object
+ print("del")
+ global_zombie_object = self
+
+ def __dealloc__(self):
+ print("dealloc")
+
+def test_zombie_object():
+ """
+ >>> test_zombie_object()
+ start
+ del
+ del global
+ del
+ finish
+ """
+ global global_zombie_object
+ print("start")
+ i = zombie_object()
+ i = None
+ print("del global")
+ del global_zombie_object
+ gc.collect()
+ print("finish")
+
+
+# Same as above, but the member
+# makes the class GC, so it
+# is deallocated
+cdef class gc_zombie_object:
+ cdef object x
+
+ def __del__(self):
+ global global_gc_zombie_object
+ print("del")
+ global_gc_zombie_object = self
+
+ def __dealloc__(self):
+ print("dealloc")
+
+def test_gc_zombie_object():
+ """
+ >>> test_gc_zombie_object()
+ start
+ del
+ del global
+ dealloc
+ finish
+ """
+ global global_gc_zombie_object
+ print("start")
+ i = gc_zombie_object()
+ i = None
+ print("del global")
+ del global_gc_zombie_object
+ gc.collect()
+ print("finish")
+
+
+cdef class cdef_parent:
+ pass
+
+cdef class cdef_child(cdef_parent):
+ def __del__(self):
+ print("del")
+ def __dealloc__(self):
+ print("dealloc")
+
+def test_cdef_parent_object():
+ """
+ >>> test_cdef_parent_object()
+ start
+ del
+ dealloc
+ finish
+ """
+ print("start")
+ i = cdef_child()
+ i = None
+ gc.collect()
+ print("finish")
+
+
+cdef class cdef_nontrivial_parent:
+ def __del__(self):
+ print("del parent")
+ def __dealloc__(self):
+ print("dealloc parent")
+
+cdef class cdef_nontrivial_child(cdef_nontrivial_parent):
+ def __del__(self):
+ print("del child")
+ def __dealloc__(self):
+ print("dealloc child")
+
+def test_cdef_nontrivial_parent_object():
+ """
+ >>> test_cdef_nontrivial_parent_object()
+ start
+ del child
+ dealloc child
+ dealloc parent
+ finish
+ """
+ print("start")
+ i = cdef_nontrivial_child()
+ i = None
+ gc.collect()
+ print("finish")
+
+
+class python_child(cdef_nontrivial_parent):
+ def __del__(self):
+ print("del python child")
+ super().__del__()
+
+def test_python_child_object():
+ """
+ >>> test_python_child_object()
+ Traceback (most recent call last):
+ ...
+ RuntimeError: End function
+ """
+
+ def func(tp):
+ inst = tp()
+ raise RuntimeError("End function")
+
+ func(python_child)
+
+def test_python_child_fancy_inherit():
+ """
+ >>> test_python_child_fancy_inherit()
+ Traceback (most recent call last):
+ ...
+ RuntimeError: End function
+ """
+
+ # inherit using "true python" rather than Cython
+ globs = { 'cdef_nontrivial_parent': cdef_nontrivial_parent }
+
+ exec("""
+class derived_python_child(cdef_nontrivial_parent):
+ pass
+""", globs)
+
+ derived_python_child = globs['derived_python_child']
+
+ def func(tp):
+ inst = tp()
+ raise RuntimeError("End function")
+
+ func(derived_python_child)
+