Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-Cython for openSUSE:Factory 
checked in at 2026-08-01 18:28:24
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-Cython (Old)
 and      /work/SRC/openSUSE:Factory/.python-Cython.new.16738 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-Cython"

Sat Aug  1 18:28:24 2026 rev:93 rq:1368882 version:3.2.9

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-Cython/python-Cython.changes      
2026-07-22 19:01:00.664632027 +0200
+++ /work/SRC/openSUSE:Factory/.python-Cython.new.16738/python-Cython.changes   
2026-08-01 18:29:02.915196200 +0200
@@ -1,0 +2,23 @@
+Fri Jul 31 17:20:49 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 3.2.9:
+  * Indexing into freshly created lists with an out-of-bounds
+    index could crash. (Github issue :issue:`7793`)
+  * Function arguments with default values could end up
+    uninitialised in closures, leading to crashes. Patch by
+    Anthony Donlon.  (Github issue :issue:`7782`)
+  * bytearray.append(None) could crash. The optimised code was
+    also lacking concurrency guards. (Github issue :issue:`7796`)
+  * Some rare corner cases when concatenating text strings were
+    resolved. (Github issue :issue:`7799`)
+  * Assignments of builtin string types to typedefs of object
+    could erroneously be rejected. (Github issue :issue:`7789`)
+  * Subscripting type failed with a TypeError. (Github issue
+    :issue:`5563`)
+  * Manually disabling CYTHON_VECTORCALL in CPython could lead to
+    invalid C code. Patch by Florent Gallaire.  (Github issue
+    :issue:`7807`)
+  * Some internal Limited API version checks for Py3.12 were
+    corrected. (Github issue :issue:`7845`)
+
+-------------------------------------------------------------------

Old:
----
  cython-3.2.8.tar.gz

New:
----
  cython-3.2.9.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-Cython.spec ++++++
--- /var/tmp/diff_new_pack.sDJfc7/_old  2026-08-01 18:29:03.531217188 +0200
+++ /var/tmp/diff_new_pack.sDJfc7/_new  2026-08-01 18:29:03.531217188 +0200
@@ -24,7 +24,7 @@
 %endif
 %{?sle15_python_module_pythons}
 Name:           python-Cython
-Version:        3.2.8
+Version:        3.2.9
 Release:        0
 Summary:        The Cython compiler for writing C extensions for the Python 
language
 License:        Apache-2.0

++++++ cython-3.2.8.tar.gz -> cython-3.2.9.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cython-3.2.8/.gitrev new/cython-3.2.9/.gitrev
--- old/cython-3.2.8/.gitrev    2026-06-30 08:39:03.477812800 +0200
+++ new/cython-3.2.9/.gitrev    2026-07-24 06:49:25.742120500 +0200
@@ -1 +1 @@
-fee6fd61250fa0df1ff2ff9cd7f6f50d203391f8
+58b8e6adc51c99c8cd5dd75db720e4aa7c051cb6
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cython-3.2.8/CHANGES.rst new/cython-3.2.9/CHANGES.rst
--- old/cython-3.2.8/CHANGES.rst        2026-06-30 08:38:54.475277700 +0200
+++ new/cython-3.2.9/CHANGES.rst        2026-07-24 06:49:15.587098800 +0200
@@ -2,6 +2,37 @@
 Cython Changelog
 ================
 
+3.2.9 (2026-07-23)
+==================
+
+Bugs fixed
+----------
+
+* Indexing into freshly created lists with an out-of-bounds index could crash.
+  (Github issue :issue:`7793`)
+
+* Function arguments with default values could end up uninitialised in 
closures, leading to crashes.
+  Patch by Anthony Donlon.  (Github issue :issue:`7782`)
+
+* ``bytearray.append(None)`` could crash. The optimised code was also lacking 
concurrency guards.
+  (Github issue :issue:`7796`)
+
+* Some rare corner cases when concatenating text strings were resolved.
+  (Github issue :issue:`7799`)
+
+* Assignments of builtin string types to typedefs of `object` could 
erroneously be rejected.
+  (Github issue :issue:`7789`)
+
+* Subscripting ``type`` failed with a ``TypeError``.
+  (Github issue :issue:`5563`)
+
+* Manually disabling ``CYTHON_VECTORCALL`` in CPython could lead to invalid C 
code.
+  Patch by Florent Gallaire.  (Github issue :issue:`7807`)
+
+* Some internal Limited API version checks for Py3.12 were corrected.
+  (Github issue :issue:`7845`)
+
+
 3.2.8 (2026-06-30)
 ==================
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cython-3.2.8/Cython/Compiler/ExprNodes.py 
new/cython-3.2.9/Cython/Compiler/ExprNodes.py
--- old/cython-3.2.8/Cython/Compiler/ExprNodes.py       2026-06-30 
08:38:54.481277700 +0200
+++ new/cython-3.2.9/Cython/Compiler/ExprNodes.py       2026-07-24 
06:49:15.593098900 +0200
@@ -640,15 +640,16 @@
             # If it's a refcounted variable, we hold a reference to it. 
Therefore, if
             # the reference count is 1, we trust that we're the unique owner.
             return "__Pyx_ReferenceSharing_OwnStrongReference"
-        if not hasattr(self, "entry") or self.entry is None:
+        entry = getattr(self, "entry", None)
+        if entry is None:
             return "__Pyx_ReferenceSharing_SharedReference"  # Not sure if we 
can reason about it
-        if self.entry.is_arg:
+        if entry.is_arg:
             # Arguments are a little hard to reason about so need an extra 
level of check
             return "__Pyx_ReferenceSharing_FunctionArgument"
-        if (self.entry.scope.is_local_scope and
+        if (entry.scope.is_local_scope and
                 # TODO - in principle a generator closure should be "non 
shared" because
                 # only one thread can run the generator at once.
-                not self.entry.in_closure and not self.entry.from_closure):
+                not entry.in_closure and not entry.from_closure):
             return "__Pyx_ReferenceSharing_OwnStrongReference"
         # Most likely a global, or a class attribute
         return "__Pyx_ReferenceSharing_SharedReference"
@@ -1804,7 +1805,7 @@
 
         node = BytesNode(self.pos, value=self.value, 
constant_result=self.constant_result)
         if dst_type.is_pyobject:
-            if dst_type in (py_object_type, Builtin.bytes_type):
+            if dst_type.resolve() in (py_object_type, Builtin.bytes_type):
                 node.type = Builtin.bytes_type
             else:
                 self.check_for_coercion_error(dst_type, env, fail=True)
@@ -1918,7 +1919,7 @@
                   "Unicode literals do not support coercion to C types other "
                   "than Py_UCS4/Py_UNICODE (for characters), Py_UNICODE* "
                   "(for strings) or char*/void* (for auto-encoded strings).")
-        elif dst_type is not py_object_type:
+        elif dst_type.resolve() is not py_object_type:
             self.check_for_coercion_error(dst_type, env, fail=True)
         return self
 
@@ -3249,7 +3250,7 @@
 
         if test_name == 'List':
             code.putln(
-                f"{result_name} = __Pyx_PyList_GetItemRefFast("
+                f"{result_name} = __Pyx_PyList_GET_ITEM_REF("
                 f"{self.py_result()}, {self.counter_cname}, 
{self.may_be_unsafe_shared()});")
         else:  # Tuple
             code.putln("#if CYTHON_ASSUME_SAFE_MACROS && 
!CYTHON_AVOID_BORROWED_REFS")
@@ -8719,10 +8720,10 @@
         # unpack items from list/tuple in unrolled loop (can't fail)
         if len(sequence_types) == 2:
             code.putln("if (likely(Py%s_CheckExact(sequence))) {" % 
sequence_types[0])
+        sequence_sharing_status = self.may_be_unsafe_shared() if 'List' in 
sequence_types else 'UNUSED'
         for i, item in enumerate(self.unpacked_items):
             if sequence_types[0] == "List":
-                code.putln(f"{item.result()} = __Pyx_PyList_GetItemRefFast"
-                           f"(sequence, {i}, {self.may_be_unsafe_shared()});")
+                code.putln(f"{item.result()} = 
__Pyx_PyList_GET_ITEM_REF(sequence, {i}, {sequence_sharing_status});")
                 code.putln(code.error_goto_if_null(item.result(), self.pos))
                 code.put_xgotref(item.result(), item.ctype())
             else:  # Tuple
@@ -8730,14 +8731,11 @@
                 code.put_incref(item.result(), item.ctype())
         if len(sequence_types) == 2:
             code.putln("} else {")
+            assert sequence_types[1] == 'List', sequence_types
             for i, item in enumerate(self.unpacked_items):
-                if sequence_types[1] == "List":
-                    code.putln(f"{item.result()} = 
__Pyx_PyList_GetItemRefFast(sequence, {i}, {self.may_be_unsafe_shared()});")
-                    code.putln(code.error_goto_if_null(item.result(), 
self.pos))
-                    code.put_xgotref(item.result(), item.ctype())
-                else:  # Tuple
-                    code.putln(f"{item.result()} = PyTuple_GET_ITEM(sequence, 
{i});")
-                    code.put_incref(item.result(), item.ctype())
+                code.putln(f"{item.result()} = 
__Pyx_PyList_GET_ITEM_REF(sequence, {i}, {sequence_sharing_status});")
+                code.putln(code.error_goto_if_null(item.result(), self.pos))
+                code.put_xgotref(item.result(), item.ctype())
             code.putln("}")
 
         code.putln("#else")
@@ -12665,7 +12663,7 @@
                 if self.inplace or self.operand1.result_in_temp():
                     code.globalstate.use_utility_code(
                         UtilityCode.load_cached("UnicodeConcatInPlace", 
"ObjectHandling.c"))
-                    func += self.may_be_unsafe_shared()
+                    func += self.operand1.may_be_unsafe_shared()
 
         if func:
             # any necessary utility code will be got by "NumberAdd" in 
generate_evaluation_code
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cython-3.2.8/Cython/Compiler/Nodes.py 
new/cython-3.2.9/Cython/Compiler/Nodes.py
--- old/cython-3.2.8/Cython/Compiler/Nodes.py   2026-06-30 08:38:54.484277700 
+0200
+++ new/cython-3.2.9/Cython/Compiler/Nodes.py   2026-07-24 06:49:15.596099000 
+0200
@@ -3039,7 +3039,7 @@
 
         # Move arguments into closure if required
         def put_into_closure(entry):
-            if entry.in_closure and not arg.default:
+            if entry.in_closure:
                 code.putln('%s = %s;' % (entry.cname, entry.original_cname))
                 if entry.type.is_memoryviewslice:
                     entry.type.generate_incref_memoryviewslice(code, 
entry.cname, True)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cython-3.2.8/Cython/Compiler/Optimize.py 
new/cython-3.2.9/Cython/Compiler/Optimize.py
--- old/cython-3.2.8/Cython/Compiler/Optimize.py        2026-06-30 
08:38:54.485277700 +0200
+++ new/cython-3.2.9/Cython/Compiler/Optimize.py        2026-07-24 
06:49:15.596099000 +0200
@@ -3183,9 +3183,14 @@
         else:
             return node
 
+        ba_obj = args[0].as_none_safe_node(
+            "'NoneType' object has no attribute '%.30s'",
+            error="PyExc_AttributeError",
+            format_args=['append'])
+
         new_node = ExprNodes.PythonCapiCallNode(
             node.pos, func_name, func_type,
-            args=[args[0], value],
+            args=[ba_obj, value],
             may_return_none=False,
             is_temp=node.is_temp,
             utility_code=utility_code,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cython-3.2.8/Cython/Shadow.py 
new/cython-3.2.9/Cython/Shadow.py
--- old/cython-3.2.8/Cython/Shadow.py   2026-06-30 08:38:54.498816500 +0200
+++ new/cython-3.2.9/Cython/Shadow.py   2026-07-24 06:49:15.611288500 +0200
@@ -1,7 +1,7 @@
 # cython.* namespace for pure mode.
 
 # Possible version formats: "3.1.0", "3.1.0a1", "3.1.0a1.dev0"
-__version__ = "3.2.8"
+__version__ = "3.2.9"
 
 
 # BEGIN shameless copy from Cython/minivect/minitypes.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cython-3.2.8/Cython/Utility/Exceptions.c 
new/cython-3.2.9/Cython/Utility/Exceptions.c
--- old/cython-3.2.8/Cython/Utility/Exceptions.c        2026-06-30 
08:38:54.501277700 +0200
+++ new/cython-3.2.9/Cython/Utility/Exceptions.c        2026-07-24 
06:49:15.612570300 +0200
@@ -419,13 +419,13 @@
     tstate->curexc_value = 0;
     tstate->curexc_traceback = 0;
   #endif
-#elif __PYX_LIMITED_VERSION_HEX > 0x030C0000
+#elif __PYX_LIMITED_VERSION_HEX >= 0x030C0000
     local_value = PyErr_GetRaisedException();
 #else
     PyErr_Fetch(&local_type, &local_value, &local_tb);
 #endif
 
-#if __PYX_LIMITED_VERSION_HEX > 0x030C0000
+#if __PYX_LIMITED_VERSION_HEX >= 0x030C0000
     if (likely(local_value)) {
         local_type = (PyObject*) Py_TYPE(local_value);
         Py_INCREF(local_type);
@@ -446,7 +446,7 @@
         if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0))
             goto bad;
     }
-#endif // __PYX_LIMITED_VERSION_HEX > 0x030C0000
+#endif // __PYX_LIMITED_VERSION_HEX >= 0x030C0000
 
     // traceback may be NULL for freshly raised exceptions
     Py_XINCREF(local_tb);
@@ -503,7 +503,7 @@
 
     return 0;
 
-#if __PYX_LIMITED_VERSION_HEX <= 0x030C0000
+#if __PYX_LIMITED_VERSION_HEX < 0x030C0000
 bad:
     *type = 0;
     *value = 0;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cython-3.2.8/Cython/Utility/FunctionArguments.c 
new/cython-3.2.9/Cython/Utility/FunctionArguments.c
--- old/cython-3.2.8/Cython/Utility/FunctionArguments.c 2026-06-30 
08:38:54.501277700 +0200
+++ new/cython-3.2.9/Cython/Utility/FunctionArguments.c 2026-07-24 
06:49:15.613098900 +0200
@@ -960,10 +960,10 @@
 
 #define __Pyx_ArgsSlice_VARARGS(args, start, stop) PyTuple_GetSlice(args, 
start, stop)
 
-#if CYTHON_METH_FASTCALL || (CYTHON_COMPILING_IN_CPYTHON && 
CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS)
+#if CYTHON_METH_FASTCALL
 #define __Pyx_ArgsSlice_FASTCALL(args, start, stop) 
__Pyx_PyTuple_FromArray(args + start, stop - start)
 #else
-#define __Pyx_ArgsSlice_FASTCALL(args, start, stop) PyTuple_GetSlice(args, 
start, stop)
+#define __Pyx_ArgsSlice_FASTCALL __Pyx_ArgsSlice_VARARGS
 #endif
 
 /////////////// fastcall ///////////////
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cython-3.2.8/Cython/Utility/ModuleSetupCode.c 
new/cython-3.2.9/Cython/Utility/ModuleSetupCode.c
--- old/cython-3.2.8/Cython/Utility/ModuleSetupCode.c   2026-06-30 
08:38:54.502277600 +0200
+++ new/cython-3.2.9/Cython/Utility/ModuleSetupCode.c   2026-07-24 
06:49:15.614099000 +0200
@@ -1092,30 +1092,42 @@
 #endif
 
 
-#if CYTHON_AVOID_BORROWED_REFS || CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS
-  #if __PYX_LIMITED_VERSION_HEX >= 0x030d0000
-    #define __Pyx_PyList_GetItemRef(o, i) PyList_GetItemRef(o, i)
-  #elif CYTHON_COMPILING_IN_LIMITED_API || !CYTHON_ASSUME_SAFE_MACROS
+// __Pyx_PyList_GetItemRef(): return safely owned reference, bounds checking, 
no wraparound
+#if __PYX_LIMITED_VERSION_HEX >= 0x030d0000
+  #define __Pyx_PyList_GetItemRef(o, i) PyList_GetItemRef(o, i)
+#elif CYTHON_AVOID_BORROWED_REFS || CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS
+  #if CYTHON_COMPILING_IN_LIMITED_API || !CYTHON_ASSUME_SAFE_MACROS
     #define __Pyx_PyList_GetItemRef(o, i) (likely((i) >= 0) ? 
PySequence_GetItem(o, i) : (PyErr_SetString(PyExc_IndexError, "list index out 
of range"), (PyObject*)NULL))
   #else
     #define __Pyx_PyList_GetItemRef(o, i) PySequence_ITEM(o, i)
   #endif
-#elif CYTHON_COMPILING_IN_LIMITED_API || !CYTHON_ASSUME_SAFE_MACROS
-  #if __PYX_LIMITED_VERSION_HEX >= 0x030d0000
-    #define __Pyx_PyList_GetItemRef(o, i) PyList_GetItemRef(o, i)
-  #else
-    #define __Pyx_PyList_GetItemRef(o, i) __Pyx_XNewRef(PyList_GetItem(o, i))
-  #endif
+#elif CYTHON_COMPILING_IN_LIMITED_API || !(CYTHON_ASSUME_SAFE_MACROS && 
CYTHON_ASSUME_SAFE_SIZE)
+  #define __Pyx_PyList_GetItemRef(o, i) __Pyx_XNewRef(PyList_GetItem(o, i))
 #else
-  #define __Pyx_PyList_GetItemRef(o, i) __Pyx_NewRef(PyList_GET_ITEM(o, i))
+  #define __Pyx_PyList_GetItemRef(o, i) (likely(__Pyx_is_valid_index(i, 
PyList_GET_SIZE(o))) ? \
+    __Pyx_NewRef(PyList_GET_ITEM(o, i)) : (PyErr_SetString(PyExc_IndexError, 
"list index out of range"), (PyObject*)NULL))
 #endif
 
-
-#if CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS && 
!CYTHON_COMPILING_IN_LIMITED_API && CYTHON_ASSUME_SAFE_MACROS
-  #define __Pyx_PyList_GetItemRefFast(o, i, unsafe_shared) 
(__Pyx_IS_UNIQUELY_REFERENCED(o, unsafe_shared) ? \
-    __Pyx_NewRef(PyList_GET_ITEM(o, i)) : __Pyx_PyList_GetItemRef(o, i))
+// __Pyx_PyList_GET_ITEM_REF(): return safely owned reference, no bounds 
checking (if avoidable), no wraparound
+#if CYTHON_AVOID_BORROWED_REFS || CYTHON_COMPILING_IN_LIMITED_API
+  #define __Pyx_PyList_GET_ITEM_REF(o, i, unsafe_shared)  
((void)(unsafe_shared), \
+      __Pyx_PyList_GetItemRef(o, i))
+#elif CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS
+  #if CYTHON_ASSUME_SAFE_MACROS
+  #define __Pyx_PyList_GET_ITEM_REF(o, i, unsafe_shared) ( \
+      __Pyx_IS_UNIQUELY_REFERENCED(o, unsafe_shared) ? \
+      __Pyx_NewRef(PyList_GET_ITEM(o, i)) : __Pyx_PyList_GetItemRef(o, i))
+  #else
+  #define __Pyx_PyList_GET_ITEM_REF(o, i, unsafe_shared) ( \
+      __Pyx_IS_UNIQUELY_REFERENCED(o, unsafe_shared) ? \
+      __Pyx_XNewRef(PyList_GetItem(o, i)) : __Pyx_PyList_GetItemRef(o, i))
+  #endif
+#elif CYTHON_ASSUME_SAFE_MACROS
+  #define __Pyx_PyList_GET_ITEM_REF(o, i, unsafe_shared)  
((void)(unsafe_shared), \
+      __Pyx_NewRef(PyList_GET_ITEM(o, i)))
 #else
-  #define __Pyx_PyList_GetItemRefFast(o, i, unsafe_shared) 
__Pyx_PyList_GetItemRef(o, i)
+  #define __Pyx_PyList_GET_ITEM_REF(o, i, unsafe_shared)  
((void)(unsafe_shared), \
+      __Pyx_XNewRef(PyList_GetItem(o, i)))
 #endif
 
 #if __PYX_LIMITED_VERSION_HEX >= 0x030d0000
@@ -1159,6 +1171,7 @@
   #define __Pyx_PyList_SET_ITEM(o, i, v) (PyList_SET_ITEM(o, i, v), (0))
   #define __Pyx_PyList_GET_ITEM(o, i) PyList_GET_ITEM(o, i)
 #else
+  // NOTE: implements wrap-around
   #define __Pyx_PySequence_ITEM(o, i) PySequence_GetItem(o, i)
   // NOTE: might fail with exception => check for -1
   #define __Pyx_PySequence_SIZE(seq)  PySequence_Size(seq)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cython-3.2.8/Cython/Utility/ObjectHandling.c 
new/cython-3.2.9/Cython/Utility/ObjectHandling.c
--- old/cython-3.2.8/Cython/Utility/ObjectHandling.c    2026-06-30 
08:38:54.502277600 +0200
+++ new/cython-3.2.9/Cython/Utility/ObjectHandling.c    2026-07-24 
06:49:15.614099000 +0200
@@ -361,6 +361,12 @@
     __Pyx_TypeName obj_type_name;
     // Handles less common slow-path checks for GetItem
     if (likely(PyType_Check(obj))) {
+        #if __PYX_LIMITED_VERSION_HEX >= 0x03090000
+        if ((PyTypeObject*)obj == &PyType_Type) {
+            return Py_GenericAlias(obj, key);
+        }
+        #endif
+
         PyObject *meth = __Pyx_PyObject_GetAttrStrNoError(obj, 
PYIDENT("__class_getitem__"));
         if (!meth) {
             PyErr_Clear();
@@ -464,26 +470,57 @@
     return r;
 }
 
+static PyObject *__Pyx_GetItemInt_Generic_size(PyObject *o, Py_ssize_t i) {
+    return __Pyx_GetItemInt_Generic(o, PyLong_FromSsize_t(i));
+}
+
 {{for type in ['List', 'Tuple']}}
 static CYTHON_INLINE PyObject *__Pyx_GetItemInt_{{type}}_Fast(PyObject *o, 
Py_ssize_t i,
                                                               int wraparound, 
int boundscheck, int unsafe_shared) {
     CYTHON_MAYBE_UNUSED_VAR(unsafe_shared);
-#if CYTHON_ASSUME_SAFE_SIZE{{if type == 'Tuple'}} && CYTHON_ASSUME_SAFE_MACROS 
&& !CYTHON_AVOID_BORROWED_REFS{{endif}}
+#if CYTHON_AVOID_BORROWED_REFS
+    CYTHON_UNUSED_VAR(boundscheck);
     Py_ssize_t wrapped_i = i;
     if (wraparound & unlikely(i < 0)) {
-        wrapped_i += Py{{type}}_GET_SIZE(o);
+        Py_ssize_t size = __Pyx_Py{{type}}_GET_SIZE(o);
+        #if !CYTHON_ASSUME_SAFE_SIZE
+        if (unlikely(size < 0)) return NULL;
+        #endif
+        wrapped_i += size;
     }
     {{if type == 'List'}}
-    if ((CYTHON_AVOID_BORROWED_REFS || 
CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS || !CYTHON_ASSUME_SAFE_MACROS)) {
+    return __Pyx_PyList_GetItemRef(o, wrapped_i);
+
+    {{else}}
+    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_COMPILING_IN_LIMITED_API
+    return PySequence_ITEM(o, wrapped_i);
+    #else
+    // PySequence_GetItem() handles wrap-around, but we already did above.
+    if (unlikely(wrapped_i < 0)) {
+        PyErr_SetString(PyExc_IndexError, "tuple index out of range");
+        return NULL;
+    }
+    return PySequence_GetItem(o, wrapped_i);
+    #endif
+    {{endif}}
+
+#elif CYTHON_ASSUME_SAFE_SIZE && CYTHON_ASSUME_SAFE_MACROS
+    Py_ssize_t wrapped_i = i;
+    Py_ssize_t size = (wraparound | boundscheck) ? Py{{type}}_GET_SIZE(o) : -1;
+    if (wraparound & unlikely(i < 0)) {
+        wrapped_i += size;
+    }
+    if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, size))) {
+        {{if type == 'List'}}
         // Note that there's a minor thread-safety issue where the size for 
wraparound may change before we use it.
         // CPython doesn't worry about it and serious violations will be 
caught by boundschecking anyway.
-        return __Pyx_PyList_GetItemRefFast(o, wrapped_i, unsafe_shared);
-    } else
-    {{endif}}
-    if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, 
Py{{type}}_GET_SIZE(o)))) {
-        return __Pyx_NewRef(Py{{type}}_GET_ITEM(o, wrapped_i));
+        return __Pyx_PyList_GET_ITEM_REF(o, wrapped_i, unsafe_shared);
+        {{else}}
+        return __Pyx_NewRef(__Pyx_PyTuple_GET_ITEM(o, wrapped_i));
+        {{endif}}
     }
-    return __Pyx_GetItemInt_Generic(o, PyLong_FromSsize_t(i));
+    return __Pyx_GetItemInt_Generic_size(o, i);
+
 #else
     (void)wraparound;
     (void)boundscheck;
@@ -501,11 +538,7 @@
         // and using the size because Python itself doesn't either. If we have 
boundschecking on they'll
         // be caught eventually.
         Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + 
PyList_GET_SIZE(o);
-        if ((CYTHON_AVOID_BORROWED_REFS || 
CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS)) {
-            return __Pyx_PyList_GetItemRefFast(o, n, unsafe_shared);
-        } else if ((!boundscheck) || (likely(__Pyx_is_valid_index(n, 
PyList_GET_SIZE(o))))) {
-            return __Pyx_NewRef(PyList_GET_ITEM(o, n));
-        }
+        return boundscheck ? __Pyx_PyList_GetItemRef(o, n) : 
__Pyx_PyList_GET_ITEM_REF(o, n, unsafe_shared);
     } else
     #if !CYTHON_AVOID_BORROWED_REFS
     if (PyTuple_CheckExact(o)) {
@@ -515,6 +548,10 @@
         }
     } else
     #endif
+#else
+    if ((!wraparound || i >= 0) & PyList_CheckExact(o)) {
+        return boundscheck ? __Pyx_PyList_GetItemRef(o, i) : 
__Pyx_PyList_GET_ITEM_REF(o, i, unsafe_shared);
+    } else
 #endif
 #if CYTHON_USE_TYPE_SLOTS && !CYTHON_COMPILING_IN_PYPY
     {
@@ -552,7 +589,7 @@
 #endif
     (void)wraparound;
     (void)boundscheck;
-    return __Pyx_GetItemInt_Generic(o, PyLong_FromSsize_t(i));
+    return __Pyx_GetItemInt_Generic_size(o, i);
 }
 
 /////////////// SetItemInt.proto ///////////////
@@ -2180,7 +2217,7 @@
 static CYTHON_INLINE vectorcallfunc __Pyx_PyVectorcall_Function(PyObject 
*callable) {
     PyTypeObject *tp = Py_TYPE(callable);
 
-    #if defined(__Pyx_CyFunction_USED)
+    #if defined(__Pyx_CyFunction_USED) && CYTHON_METH_FASTCALL
     if (__Pyx_CyFunction_CheckExact(callable)) {
         return __Pyx_CyFunction_func_vectorcall(callable);
     }
@@ -2848,7 +2885,7 @@
     #endif
     #define 
__Pyx_PyUnicode_Concat__Pyx_ReferenceSharing_DefinitelyUniqueInPlace(left, 
right) __Pyx_PyUnicode_ConcatInPlace(left, right, 
__Pyx_ReferenceSharing_DefinitelyUnique)
     #define 
__Pyx_PyUnicode_Concat__Pyx_ReferenceSharing_OwnStrongReferenceInPlace(left, 
right) __Pyx_PyUnicode_ConcatInPlace(left, right, 
__Pyx_ReferenceSharing_OwnStrongReference)
-    #define 
__Pyx_PyUnicode_Concat__Pyx_ReferenceSharing_FunctionArgumentInPlace(left, 
right) __Pyx_PyUnicode_ConcatInPlace(left, right, 
__Pyx_ReferenceSharing_DefinitelyUnique)
+    #define 
__Pyx_PyUnicode_Concat__Pyx_ReferenceSharing_FunctionArgumentInPlace(left, 
right) __Pyx_PyUnicode_ConcatInPlace(left, right, 
__Pyx_ReferenceSharing_FunctionArgument)
     #define 
__Pyx_PyUnicode_Concat__Pyx_ReferenceSharing_SharedReferenceInPlace(left, 
right) __Pyx_PyUnicode_ConcatInPlace(left, right, 
__Pyx_ReferenceSharing_SharedReference)
     // __Pyx_PyUnicode_ConcatInPlace is slightly odd because it has the 
potential to modify the input
     // argument (but only in cases where no user should notice). Therefore, it 
needs to keep Cython's
@@ -2932,7 +2969,8 @@
     }
     new_len = left_len + right_len;
 
-    if (__Pyx_unicode_modifiable(left, unsafe_shared)
+    if (left != right
+            && __Pyx_unicode_modifiable(left, unsafe_shared)
             && PyUnicode_CheckExact(right)
             && PyUnicode_KIND(right) <= PyUnicode_KIND(left)
             // Don't resize for ascii += latin1. Convert ascii to latin1 
requires
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cython-3.2.8/Cython/Utility/Optimize.c 
new/cython-3.2.9/Cython/Utility/Optimize.c
--- old/cython-3.2.8/Cython/Utility/Optimize.c  2026-06-30 08:38:54.503277800 
+0200
+++ new/cython-3.2.9/Cython/Utility/Optimize.c  2026-07-24 06:49:15.614099000 
+0200
@@ -454,7 +454,7 @@
         #endif
         if (unlikely(pos >= list_size)) return 0;
         *ppos = pos + 1;
-        next_item = __Pyx_PyList_GetItemRef(iter_obj, pos);
+        next_item = __Pyx_PyList_GET_ITEM_REF(iter_obj, pos, 
__Pyx_ReferenceSharing_OwnStrongReference);
         if (unlikely(!next_item)) return -1;
     } else
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cython-3.2.8/Cython/Utility/StringTools.c 
new/cython-3.2.9/Cython/Utility/StringTools.c
--- old/cython-3.2.8/Cython/Utility/StringTools.c       2026-06-30 
08:38:54.503277800 +0200
+++ new/cython-3.2.9/Cython/Utility/StringTools.c       2026-07-24 
06:49:15.615099000 +0200
@@ -1232,6 +1232,7 @@
         }
     }
     return __Pyx_PyByteArray_Append(bytearray, (int) ival);
+
 bad_range:
     PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");
     return -1;
@@ -1244,31 +1245,42 @@
 //////////////////// ByteArrayAppend ////////////////////
 //@requires: ObjectHandling.c::PyObjectCallMethod1
 
-static CYTHON_INLINE int __Pyx_PyByteArray_Append(PyObject* bytearray, int 
value) {
+static int __Pyx_PyByteArray_Append_fallback(PyObject* bytearray, int value) {
     PyObject *pyval, *retval;
+    pyval = PyLong_FromLong(value);
+    if (unlikely(!pyval))
+        return -1;
+    retval = __Pyx_PyObject_CallMethod1(bytearray, PYIDENT("append"), pyval);
+    Py_DECREF(pyval);
+    if (unlikely(!retval))
+        return -1;
+    Py_DECREF(retval);
+    return 0;
+}
+
+static CYTHON_INLINE int __Pyx_PyByteArray_Append(PyObject* bytearray, int 
value) {
 #if CYTHON_COMPILING_IN_CPYTHON
     if (likely(__Pyx_is_valid_index(value, 256))) {
+        int retval = 1;
+        __Pyx_BEGIN_CRITICAL_SECTION(bytearray);
         Py_ssize_t n = Py_SIZE(bytearray);
         if (likely(n != PY_SSIZE_T_MAX)) {
-            if (unlikely(PyByteArray_Resize(bytearray, n + 1) < 0))
-                return -1;
-            PyByteArray_AS_STRING(bytearray)[n] = (char) (unsigned char) value;
-            return 0;
+            retval = PyByteArray_Resize(bytearray, n + 1);
+            if (likely(retval == 0)) {
+                PyByteArray_AS_STRING(bytearray)[n] = (char) (unsigned char) 
value;
+            }
+        }
+        __Pyx_END_CRITICAL_SECTION();
+        if (likely(retval != 1)) {
+            return retval;
         }
     } else {
         PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");
         return -1;
     }
 #endif
-    pyval = PyLong_FromLong(value);
-    if (unlikely(!pyval))
-        return -1;
-    retval = __Pyx_PyObject_CallMethod1(bytearray, PYIDENT("append"), pyval);
-    Py_DECREF(pyval);
-    if (unlikely(!retval))
-        return -1;
-    Py_DECREF(retval);
-    return 0;
+
+    return __Pyx_PyByteArray_Append_fallback(bytearray, value);
 }
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cython-3.2.8/PKG-INFO new/cython-3.2.9/PKG-INFO
--- old/cython-3.2.8/PKG-INFO   2026-06-30 08:39:03.858988500 +0200
+++ new/cython-3.2.9/PKG-INFO   2026-07-24 06:49:26.189941600 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: Cython
-Version: 3.2.8
+Version: 3.2.9
 Summary: The Cython compiler for writing C extensions in the Python language.
 Home-page: https://cython.org/
 Author: Robert Bradshaw, Stefan Behnel, David Woods, Greg Ewing, et al.
@@ -64,21 +64,32 @@
 
 .. _Pyrex: https://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/
 
-3.2.8 (2026-06-30)
+3.2.9 (2026-07-23)
 ==================
 
 Bugs fixed
 ----------
 
-* Assigning a Python 3.14+ ``.__annotate__`` function to a Cython compiled 
function no longer
-  evaluates annotations eagerly.  Fixes a regression with 
``@functools.wraps()`` in Cython 3.2.6.
-  Patch by Jelle Zijlstra.  (Github issue 
https://github.com/cython/cython/issues/7767)
-
-* In freethreading Python, the necessary object keep-alive while executing 
user code in
-  ``.__dealloc__()`` uses a safer scheme.
-  Patch by Yaxing Cai.  (Github issue 
https://github.com/cython/cython/issues/7769)
+* Indexing into freshly created lists with an out-of-bounds index could crash.
+  (Github issue https://github.com/cython/cython/issues/7793)
 
-* The local function state used by ``sys.monitoring`` read from uninitialised 
memory.
-  (Github issue https://github.com/cython/cython/issues/7774)
+* Function arguments with default values could end up uninitialised in 
closures, leading to crashes.
+  Patch by Anthony Donlon.  (Github issue 
https://github.com/cython/cython/issues/7782)
 
-* The ``.ag_running`` flag attribute of async generators was always false on 
big-endian systems.
+* ``bytearray.append(None)`` could crash. The optimised code was also lacking 
concurrency guards.
+  (Github issue https://github.com/cython/cython/issues/7796)
+
+* Some rare corner cases when concatenating text strings were resolved.
+  (Github issue https://github.com/cython/cython/issues/7799)
+
+* Assignments of builtin string types to typedefs of `object` could 
erroneously be rejected.
+  (Github issue https://github.com/cython/cython/issues/7789)
+
+* Subscripting ``type`` failed with a ``TypeError``.
+  (Github issue https://github.com/cython/cython/issues/5563)
+
+* Manually disabling ``CYTHON_VECTORCALL`` in CPython could lead to invalid C 
code.
+  Patch by Florent Gallaire.  (Github issue 
https://github.com/cython/cython/issues/7807)
+
+* Some internal Limited API version checks for Py3.12 were corrected.
+  (Github issue https://github.com/cython/cython/issues/7845)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cython-3.2.8/tests/errors/string_assignments.pyx 
new/cython-3.2.9/tests/errors/string_assignments.pyx
--- old/cython-3.2.8/tests/errors/string_assignments.pyx        2026-06-30 
08:38:54.552277600 +0200
+++ new/cython-3.2.9/tests/errors/string_assignments.pyx        2026-07-24 
06:49:15.668099000 +0200
@@ -89,6 +89,12 @@
 voidptr_func(b"abc")
 voidptr_func(u"abc")
 
+ctypedef object MyObject
+
+cdef MyObject my_obj1 =  "abc"
+cdef MyObject my_obj2 = b"abc"
+cdef MyObject my_obj3 = u"abc"
+
 
 _ERRORS = u"""
 36:20: Unicode literals do not support coercion to C types other than 
Py_UCS4/Py_UNICODE (for characters), Py_UNICODE* (for strings) or char*/void* 
(for auto-encoded strings).
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cython-3.2.8/tests/run/builtin_type.pyx 
new/cython-3.2.9/tests/run/builtin_type.pyx
--- old/cython-3.2.8/tests/run/builtin_type.pyx 2026-06-30 08:38:54.559277500 
+0200
+++ new/cython-3.2.9/tests/run/builtin_type.pyx 2026-07-24 06:49:15.675099000 
+0200
@@ -1,5 +1,8 @@
 cimport cython
 
+import sys
+
+
 @cython.test_assert_path_exists(
     '//PythonCapiCallNode/PythonCapiFunctionNode[@cname="Py_TYPE"]')
 def get_type_of(a):
@@ -51,3 +54,86 @@
     TypeError: Argument 'x' has incorrect type (expected type, got object)
     """
     return x
+
+
+def test_exact_type_getitem(val):
+    """
+    >>> test_exact_type_getitem(int)
+    type[int]
+    >>> test_exact_type_getitem(float)
+    type[float]
+    >>> test_exact_type_getitem(1)
+    type[1]
+    """
+    return type[val]
+
+if sys.version_info < (3,9):
+    test_exact_type_getitem.__doc__ = None
+
+
+def test_exact_type_instance_getitem1(val):
+    """
+    >>> test_exact_type_instance_getitem1(int)  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+        ...
+    TypeError: ... is not subscriptable
+    """
+    return str[val]
+
+if sys.version_info < (3,9):
+    test_exact_type_instance_getitem1.__doc__ = None
+
+
+def test_exact_type_instance_getitem2(val):
+    """
+    >>> test_exact_type_instance_getitem2(int)
+    list[int]
+    >>> test_exact_type_instance_getitem2(1)
+    list[1]
+    """
+    return list[val]
+
+if sys.version_info < (3,9):
+    test_exact_type_instance_getitem2.__doc__ = None
+
+
+def test_maybe_type_getitem(tp, val):
+    """
+    >>> test_maybe_type_getitem(type, int)
+    type[int]
+    >>> test_maybe_type_getitem(type, float)
+    type[float]
+    >>> test_maybe_type_getitem(type, 1)
+    type[1]
+    >>> test_maybe_type_getitem(list, int)
+    list[int]
+    >>> test_maybe_type_getitem(str, int)  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+        ...
+    TypeError: ... is not subscriptable
+    """
+    return tp[val]
+
+if sys.version_info < (3,9):
+    test_maybe_type_getitem.__doc__ = None
+
+
+def test_typed_type_getitem(tp: type, val):
+    """
+    >>> test_typed_type_getitem(type, int)
+    type[int]
+    >>> test_typed_type_getitem(type, float)
+    type[float]
+    >>> test_typed_type_getitem(type, 1)
+    type[1]
+    >>> test_typed_type_getitem(list, int)
+    list[int]
+    >>> test_typed_type_getitem(str, int)  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+        ...
+    TypeError: ... is not subscriptable
+    """
+    return tp[val]
+
+if sys.version_info < (3,9):
+    test_typed_type_getitem.__doc__ = None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cython-3.2.8/tests/run/bytearraymethods.pyx 
new/cython-3.2.9/tests/run/bytearraymethods.pyx
--- old/cython-3.2.8/tests/run/bytearraymethods.pyx     2026-06-30 
08:38:54.559277500 +0200
+++ new/cython-3.2.9/tests/run/bytearraymethods.pyx     2026-07-24 
06:49:15.676098800 +0200
@@ -269,6 +269,17 @@
     ValueError: ...
     >>> print(b.decode('ascii'))
     abcX@xy
+
+    >>> b = bytearray(b'abc')
+    >>> b = bytearray_append(b, ord('x'), ord('y'), None)  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    TypeError: ...
+    >>> print(b.decode('ascii'))
+    abcX@xy
+
+    >>> b = bytearray_append(None, ord('x'), ord('y'), b'x')  # doctest: 
+ELLIPSIS
+    Traceback (most recent call last):
+    AttributeError: 'NoneType' object has no attribute 'append'
     """
     assert b.append('X') is None
     b.append(64)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cython-3.2.8/tests/run/cdef_optional_arg_closure.pyx 
new/cython-3.2.9/tests/run/cdef_optional_arg_closure.pyx
--- old/cython-3.2.8/tests/run/cdef_optional_arg_closure.pyx    1970-01-01 
01:00:00.000000000 +0100
+++ new/cython-3.2.9/tests/run/cdef_optional_arg_closure.pyx    2026-07-24 
06:49:15.678099000 +0200
@@ -0,0 +1,83 @@
+# mode: run
+# tag: closures, optional_args
+
+# An optional (defaulted) argument of a cdef function that is captured by an
+# inner function (closure) must be moved into the closure scope, just like a
+# non-optional argument. Previously it was unpacked only into a C local while
+# the body and the closure read the (uninitialised) scope field, which returned
+# the wrong value or crashed (NULL dereference on the freelist allocation 
path).
+
+
+cdef test(object register=None, object length=None):
+    # `length` is captured by `_on_done`, so it lives in the closure scope.
+    def _on_done():
+        return length
+    return length, _on_done()
+
+
+def run_default():
+    """
+    >>> run_default()
+    (None, None)
+    """
+    return test(0)
+
+
+def run_passed():
+    """
+    >>> run_passed()
+    (196883, 196883)
+    """
+    return test(0, 196883)
+
+
+cdef test_ctype(int register=7):
+    def inner():
+        return (register)
+    return register, inner()
+
+
+def run_ctype_default():
+    """
+    >>> run_ctype_default()
+    (7, 7)
+    """
+    return test_ctype(7)
+
+
+def run_ctype_passed():
+    """
+    >>> run_ctype_passed()
+    (17, 17)
+    """
+    return test_ctype(17)
+
+
+cdef test_multi(object device_index, object register=2, object tdi_data=3):
+    def inner():
+        return (device_index, register, tdi_data)
+    return inner()
+
+
+def run_multi_defaults():
+    """
+    >>> run_multi_defaults()
+    (1, 2, 3)
+    """
+    return test_multi(1)
+
+
+def run_multi_partial():
+    """
+    >>> run_multi_partial()
+    (1, 20, 3)
+    """
+    return test_multi(1, 20)
+
+
+def run_multi_all():
+    """
+    >>> run_multi_all()
+    (1, 20, 30)
+    """
+    return test_multi(1, 20, 30)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cython-3.2.8/tests/run/freethreaded_list_indexing.pyx 
new/cython-3.2.9/tests/run/freethreaded_list_indexing.pyx
--- old/cython-3.2.8/tests/run/freethreaded_list_indexing.pyx   2026-06-30 
08:38:54.578277600 +0200
+++ new/cython-3.2.9/tests/run/freethreaded_list_indexing.pyx   2026-07-24 
06:49:15.695098900 +0200
@@ -16,7 +16,7 @@
                                                 int wraparound, int 
boundscheck, int unsafe_shared);
     static PyObject *Call_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i,
                                                 int wraparound, int 
boundscheck, int unsafe_shared) {
-        int unique = (unsafe_shared == 
__Pyx_ReferenceSharing_DefinitelyUnique) || 
+        int unique = (unsafe_shared == 
__Pyx_ReferenceSharing_DefinitelyUnique) ||
                      (unsafe_shared == 
__Pyx_ReferenceSharing_OwnStrongReference);
         unsafe_shared_set = !unique;
         return __Pyx_GetItemInt_List_Fast(o, i, wraparound, boundscheck, 
unsafe_shared);
@@ -105,3 +105,27 @@
 def dummy_func2():
     # abuse cname feature to undefine our override to allow the utility code 
to be generated
     undef_getitemint_list_fast()
+
+
+def temp_list_subscript(create):
+    """
+    >>> temp_list_subscript([1,2,3].copy)
+    2
+
+    >>> temp_list_subscript(list)  # empty list, out of range
+    Traceback (most recent call last):
+    IndexError: list index out of range
+    """
+    return create()[1]
+
+
+def temp_list_subscript_wraparound(create):
+    """
+    >>> temp_list_subscript_wraparound([1,2,3].copy)
+    3
+
+    >>> temp_list_subscript_wraparound(list)  # empty list, out of range
+    Traceback (most recent call last):
+    IndexError: list index out of range
+    """
+    return create()[-1]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cython-3.2.8/tests/run/inplace.pyx 
new/cython-3.2.9/tests/run/inplace.pyx
--- old/cython-3.2.8/tests/run/inplace.pyx      2026-06-30 08:38:54.582277500 
+0200
+++ new/cython-3.2.9/tests/run/inplace.pyx      2026-07-24 06:49:15.699686300 
+0200
@@ -254,3 +254,143 @@
     """
     value += a if condition else b
     return value
+
+
+# Unicode inplace concatenation is special because it attempts to do a
+# resize for uniquely referenced objects
+
+def unicode_concat_local(a: unicode):
+    """
+    >>> s = "123"
+    >>> unicode_concat_local(s)
+    '123abc'
+    >>> s
+    '123'
+    >>> unicode_concat_local("123456")
+    '123456abc'
+    """
+    local = a
+    local += 'abc'
+    return local
+
+def unicode_concat_unique_local(deuniquify):
+    """
+    >>> unicode_concat_unique_local(True)
+    'some string?'
+    >>> unicode_concat_unique_local(False)
+    'some string?'
+    """
+    a = "some string"
+    if deuniquify:
+        b = a
+    a += "?"
+    return a
+
+
+def unicode_concat_arg(a: unicode):
+    """
+    >>> s = "an argument"
+    >>> unicode_concat_arg(s)
+    'an argument with some extra stuff'
+    >>> s
+    'an argument'
+    >>> unicode_concat_arg('another argument')
+    'another argument with some extra stuff'
+    """
+    a += ' with some extra stuff'
+    return a
+
+def unicode_concat_arg_self(a: unicode):
+    """
+    >>> unicode_concat_arg_self('babababababa')
+    'babababababababababababa'
+    >>> s = '0987654321'
+    >>> unicode_concat_arg_self(s)
+    '09876543210987654321'
+    >>> s
+    '0987654321'
+    """
+    a += a
+    return a
+
+cdef unicode global_unicode = "glglgl"
+
+def get_global_unicode():
+    return global_unicode
+
+def reset_global_unicode():
+    global global_unicode
+    global_unicode = "glglgl"
+
+def unicode_concat_global():
+    """
+    >>> unicode_concat_global()
+    'glglgl xxxx'
+    >>> get_global_unicode()
+    'glglgl xxxx'
+    """
+    global global_unicode
+    global_unicode += ' xxxx'
+    return global_unicode
+
+cdef class UnicodeAttr:
+    cdef public unicode u
+    def do_concat(self):
+        """
+        >>> inst = UnicodeAttr()
+        >>> inst.u = 'attr_string'
+        >>> inst.do_concat()
+        >>> inst.u
+        'attr_string!'
+        >>> old = inst.u
+        >>> inst.do_concat()
+        >>> inst.u
+        'attr_string!!'
+        >>> old
+        'attr_string!'
+        """
+        self.u += "!"
+
+    def do_concat_self(self):
+        """
+        >>> inst = UnicodeAttr()
+        >>> inst.u = 'attr_string'
+        >>> inst.do_concat_self()
+        >>> inst.u
+        'attr_stringattr_string'
+        >>> old = inst.u
+        >>> inst.do_concat_self()
+        >>> inst.u
+        'attr_stringattr_stringattr_stringattr_string'
+        >>> old
+        'attr_stringattr_string'
+        """
+        self.u += self.u
+
+def unicode_concat_closure():
+    """
+    >>> reset_global_unicode()
+    >>> f = unicode_concat_closure()
+    >>> f('get')
+    'hmmmmm'
+    >>> f('concat')
+    'hmmmmm?'
+    >>> f('concat')
+    'hmmmmm??'
+    >>> f('get')
+    'hmmmmm??'
+    >>> f = unicode_concat_closure()
+    >>> (old := f('get'))
+    'hmmmmm'
+    >>> f('concat')
+    'hmmmmm?'
+    >>> old
+    'hmmmmm'
+    """
+    s = "hmmmmm"
+    def cl(op):
+        nonlocal s
+        if op == 'concat':
+            s += '?'
+        return s
+    return cl

Reply via email to