Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build/pkgs/cython: Update to 0.29.36 #35084

Merged
merged 6 commits into from
Aug 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 3 additions & 3 deletions build/pkgs/cython/checksums.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
tarball=Cython-VERSION.tar.gz
sha1=015b737107304a5777f5c6552ffb12713684c924
md5=91c36ea86c00adcc5c1c11cf48b733c0
cksum=1793363471
sha1=762987c737acfe7532cb3da38b450fb6e0cf1d7b
md5=a4d0f9fbc9c137f1a88937cd40e8c5ee
cksum=2260471737
upstream_url=https://pypi.io/packages/source/C/Cython/Cython-VERSION.tar.gz
2 changes: 1 addition & 1 deletion build/pkgs/cython/package-version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.29.32.p2
0.29.36
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ Date: Thu Feb 14 10:02:41 2019 +0100
@cython.trashcan directive to enable the Python trashcan for deallocations

diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py
index d5742de..27fcad6 100644
index 56845330d..3a3e8a956 100644
--- a/Cython/Compiler/ModuleNode.py
+++ b/Cython/Compiler/ModuleNode.py
@@ -1426,6 +1426,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
@@ -1443,6 +1443,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):

is_final_type = scope.parent_type.is_final_type
needs_gc = scope.needs_gc()
+ needs_trashcan = scope.needs_trashcan()

weakref_slot = scope.lookup_here("__weakref__") if not scope.is_closure_class_scope else None
if weakref_slot not in scope.var_entries:
@@ -1464,6 +1465,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
@@ -1481,6 +1482,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
# running this destructor.
code.putln("PyObject_GC_UnTrack(o);")

Expand All @@ -32,7 +32,7 @@ index d5742de..27fcad6 100644
# call the user's __dealloc__
self.generate_usr_dealloc_call(scope, code)

@@ -1537,6 +1543,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
@@ -1554,6 +1560,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("(*Py_TYPE(o)->tp_free)(o);")
if freelist_size:
code.putln("}")
Expand All @@ -44,18 +44,20 @@ index d5742de..27fcad6 100644
"}")

diff --git a/Cython/Compiler/Options.py b/Cython/Compiler/Options.py
index d859c19..19d96f1 100644
index d03119fca..539629926 100644
--- a/Cython/Compiler/Options.py
+++ b/Cython/Compiler/Options.py
@@ -313,6 +313,7 @@ directive_types = {
@@ -319,7 +319,8 @@ directive_types = {
'freelist': int,
'c_string_type': one_of('bytes', 'bytearray', 'str', 'unicode'),
'c_string_encoding': normalise_encoding_name,
- 'cpow': bool
+ 'cpow': bool,
+ 'trashcan': bool,
}

for key, val in _directive_defaults.items():
@@ -355,6 +356,7 @@ directive_scopes = { # defaults to available everywhere
@@ -362,6 +363,7 @@ directive_scopes = { # defaults to available everywhere
'np_pythran': ('module',),
'fast_gil': ('module',),
'iterable_coroutine': ('module', 'function'),
Expand All @@ -64,18 +66,18 @@ index d859c19..19d96f1 100644


diff --git a/Cython/Compiler/PyrexTypes.py b/Cython/Compiler/PyrexTypes.py
index 3b572d6..f200c5f 100644
index c309bd04b..9231130b5 100644
--- a/Cython/Compiler/PyrexTypes.py
+++ b/Cython/Compiler/PyrexTypes.py
@@ -1136,6 +1136,7 @@ class PyObjectType(PyrexType):
@@ -1129,6 +1129,7 @@ class PyObjectType(PyrexType):
is_extern = False
is_subclassed = False
is_gc_simple = False
+ builtin_trashcan = False # builtin type using trashcan

def __str__(self):
return "Python object"
@@ -1190,10 +1191,14 @@ class PyObjectType(PyrexType):
@@ -1183,10 +1184,14 @@ class PyObjectType(PyrexType):


builtin_types_that_cannot_create_refcycles = set([
Expand All @@ -91,7 +93,7 @@ index 3b572d6..f200c5f 100644

class BuiltinObjectType(PyObjectType):
# objstruct_cname string Name of PyObject struct
@@ -1218,6 +1223,7 @@ class BuiltinObjectType(PyObjectType):
@@ -1211,6 +1216,7 @@ class BuiltinObjectType(PyObjectType):
self.typeptr_cname = "(&%s)" % cname
self.objstruct_cname = objstruct_cname
self.is_gc_simple = name in builtin_types_that_cannot_create_refcycles
Expand All @@ -100,10 +102,19 @@ index 3b572d6..f200c5f 100644
# Special case the type type, as many C API calls (and other
# libraries) actually expect a PyTypeObject* for type arguments.
diff --git a/Cython/Compiler/Symtab.py b/Cython/Compiler/Symtab.py
index f7443cb..d44484d 100644
index 7361a55ae..f0c311ba6 100644
--- a/Cython/Compiler/Symtab.py
+++ b/Cython/Compiler/Symtab.py
@@ -2085,6 +2085,22 @@ class CClassScope(ClassScope):
@@ -2043,7 +2043,7 @@ class PyClassScope(ClassScope):
class CClassScope(ClassScope):
# Namespace of an extension type.
#
- # parent_type CClassType
+ # parent_type PyExtensionType
# #typeobj_cname string or None
# #objstruct_cname string
# method_table_cname string
@@ -2087,6 +2087,22 @@ class CClassScope(ClassScope):
return not self.parent_type.is_gc_simple
return False

Expand All @@ -127,10 +138,10 @@ index f7443cb..d44484d 100644
"""
Do we need to generate an implementation for the tp_clear slot? Can
diff --git a/Cython/Utility/ExtensionTypes.c b/Cython/Utility/ExtensionTypes.c
index 50d0e21..ca2adbe 100644
index dc187ab49..f359165df 100644
--- a/Cython/Utility/ExtensionTypes.c
+++ b/Cython/Utility/ExtensionTypes.c
@@ -74,6 +74,54 @@ static int __Pyx_PyType_Ready(PyTypeObject *t) {
@@ -119,6 +119,54 @@ static int __Pyx_PyType_Ready(PyTypeObject *t) {
return r;
}

Expand Down Expand Up @@ -185,3 +196,160 @@ index 50d0e21..ca2adbe 100644
/////////////// CallNextTpDealloc.proto ///////////////

static void __Pyx_call_next_tp_dealloc(PyObject* obj, destructor current_tp_dealloc);
diff --git a/tests/run/trashcan.pyx b/tests/run/trashcan.pyx
new file mode 100644
index 000000000..93a501ff8
--- /dev/null
+++ b/tests/run/trashcan.pyx
@@ -0,0 +1,148 @@
+# mode: run
+
+cimport cython
+
+
+# Count number of times an object was deallocated twice. This should remain 0.
+cdef int double_deallocations = 0
+def assert_no_double_deallocations():
+ global double_deallocations
+ err = double_deallocations
+ double_deallocations = 0
+ assert not err
+
+
+# Compute x = f(f(f(...(None)...))) nested n times and throw away the result.
+# The real test happens when exiting this function: then a big recursive
+# deallocation of x happens. We are testing two things in the tests below:
+# that Python does not crash and that no double deallocation happens.
+# See also https://github.com/python/cpython/pull/11841
+def recursion_test(f, int n=2**20):
+ x = None
+ cdef int i
+ for i in range(n):
+ x = f(x)
+
+
+@cython.trashcan(True)
+cdef class Recurse:
+ """
+ >>> recursion_test(Recurse)
+ >>> assert_no_double_deallocations()
+ """
+ cdef public attr
+ cdef int deallocated
+
+ def __init__(self, x):
+ self.attr = x
+
+ def __dealloc__(self):
+ # Check that we're not being deallocated twice
+ global double_deallocations
+ double_deallocations += self.deallocated
+ self.deallocated = 1
+
+
+cdef class RecurseSub(Recurse):
+ """
+ >>> recursion_test(RecurseSub)
+ >>> assert_no_double_deallocations()
+ """
+ cdef int subdeallocated
+
+ def __dealloc__(self):
+ # Check that we're not being deallocated twice
+ global double_deallocations
+ double_deallocations += self.subdeallocated
+ self.subdeallocated = 1
+
+
+@cython.freelist(4)
+@cython.trashcan(True)
+cdef class RecurseFreelist:
+ """
+ >>> recursion_test(RecurseFreelist)
+ >>> recursion_test(RecurseFreelist, 1000)
+ >>> assert_no_double_deallocations()
+ """
+ cdef public attr
+ cdef int deallocated
+
+ def __init__(self, x):
+ self.attr = x
+
+ def __dealloc__(self):
+ # Check that we're not being deallocated twice
+ global double_deallocations
+ double_deallocations += self.deallocated
+ self.deallocated = 1
+
+
+# Subclass of list => uses trashcan by default
+# As long as https://github.com/python/cpython/pull/11841 is not fixed,
+# this does lead to double deallocations, so we skip that check.
+cdef class RecurseList(list):
+ """
+ >>> RecurseList(42)
+ [42]
+ >>> recursion_test(RecurseList)
+ """
+ def __init__(self, x):
+ super().__init__((x,))
+
+
+# Some tests where the trashcan is NOT used. When the trashcan is not used
+# in a big recursive deallocation, the __dealloc__s of the base classs are
+# only run after the __dealloc__s of the subclasses.
+# We use this to detect trashcan usage.
+cdef int base_deallocated = 0
+cdef int trashcan_used = 0
+def assert_no_trashcan_used():
+ global base_deallocated, trashcan_used
+ err = trashcan_used
+ trashcan_used = base_deallocated = 0
+ assert not err
+
+
+cdef class Base:
+ def __dealloc__(self):
+ global base_deallocated
+ base_deallocated = 1
+
+
+# Trashcan disabled by default
+cdef class Sub1(Base):
+ """
+ >>> recursion_test(Sub1, 100)
+ >>> assert_no_trashcan_used()
+ """
+ cdef public attr
+
+ def __init__(self, x):
+ self.attr = x
+
+ def __dealloc__(self):
+ global base_deallocated, trashcan_used
+ trashcan_used += base_deallocated
+
+
+@cython.trashcan(True)
+cdef class Middle(Base):
+ cdef public foo
+
+
+# Trashcan disabled explicitly
+@cython.trashcan(False)
+cdef class Sub2(Middle):
+ """
+ >>> recursion_test(Sub2, 1000)
+ >>> assert_no_trashcan_used()
+ """
+ cdef public attr
+
+ def __init__(self, x):
+ self.attr = x
+
+ def __dealloc__(self):
+ global base_deallocated, trashcan_used
+ trashcan_used += base_deallocated
--
2.37.1 (Apple Git-137.1)