summaryrefslogtreecommitdiffstats
path: root/contrib/tools
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/tools')
-rw-r--r--contrib/tools/cython/.dist-info/METADATA83
-rw-r--r--contrib/tools/cython/.yandex_meta/override.nix4
-rw-r--r--contrib/tools/cython/CHANGES.rst49
-rw-r--r--contrib/tools/cython/Cython/Build/Dependencies.py2
-rw-r--r--contrib/tools/cython/Cython/Build/SharedModule.py23
-rw-r--r--contrib/tools/cython/Cython/Compiler/Code.py11
-rw-r--r--contrib/tools/cython/Cython/Compiler/ModuleNode.py11
-rw-r--r--contrib/tools/cython/Cython/Compiler/Scanning.py9
-rw-r--r--contrib/tools/cython/Cython/Includes/libcpp/vector.pxd8
-rw-r--r--contrib/tools/cython/Cython/Shadow.py2
-rw-r--r--contrib/tools/cython/Cython/Utility/AsyncGen.c9
-rw-r--r--contrib/tools/cython/Cython/Utility/Coroutine.c4
-rw-r--r--contrib/tools/cython/Cython/Utility/CythonFunction.c147
-rw-r--r--contrib/tools/cython/Cython/Utility/ExtensionTypes.c28
-rw-r--r--contrib/tools/cython/Cython/Utility/TString.c2
-rwxr-xr-xcontrib/tools/cython/cython.py2
-rw-r--r--contrib/tools/cython/ya.make4
17 files changed, 287 insertions, 111 deletions
diff --git a/contrib/tools/cython/.dist-info/METADATA b/contrib/tools/cython/.dist-info/METADATA
index 7ee86c1f0ca..76194acc38d 100644
--- a/contrib/tools/cython/.dist-info/METADATA
+++ b/contrib/tools/cython/.dist-info/METADATA
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: Cython
-Version: 3.2.5
+Version: 3.2.8
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,82 +64,21 @@ to install an uncompiled (slower) version of Cython with::
.. _Pyrex: https://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/
-3.2.5 (2026-05-23)
+3.2.8 (2026-06-30)
==================
Bugs fixed
----------
-* A compile failure was fixed when using the walrus operator inside of try-except.
- (Github issue https://github.com/cython/cython/issues/7462)
+* 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)
-* Expressions with side-effects as object argument to ``isinstance()`` could get
- evaluated multiple times, e.g. when they use the walrus operator.
- (Github issue https://github.com/cython/cython/issues/7670)
+* 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)
-* Several problems generating the shared utility module were resolved, including
- a performance regression with memory views.
- (Github issues https://github.com/cython/cython/issues/7487, https://github.com/cython/cython/issues/7497, https://github.com/cython/cython/issues/7504, https://github.com/cython/cython/issues/7558)
+* The local function state used by ``sys.monitoring`` read from uninitialised memory.
+ (Github issue https://github.com/cython/cython/issues/7774)
-* Some GC and refcounting issues were resolved for Cython functions in the Limited API.
- (Github issue https://github.com/cython/cython/issues/7594)
-
-* Refcounting errors and error handling issues were resolved in some rare error handling cases.
- (Github issues https://github.com/cython/cython/issues/7597, https://github.com/cython/cython/issues/7599, https://github.com/cython/cython/issues/7612, https://github.com/cython/cython/issues/7673)
-
-* Using ``cython.pymutex`` in an extension type with ``cdef`` methods generated
- invalid C code missing the required ``PyMutex`` declarations.
- (Github issue https://github.com/cython/cython/issues/6995)
-
-* Calling ``.get_frame()`` on Cython coroutines could crash in freethreading Python.
- (Github issue https://github.com/cython/cython/issues/7632)
-
-* The vectorcall protocol was not used correctly in ``.throw()`` of Cython coroutines
- when raising the exception only by type (without value or traceback).
- (Github issue https://github.com/cython/cython/issues/7677)
-
-* A problem with cpdef enums in the Limited API of Python 3.11+ was resolved.
- (Github issue https://github.com/cython/cython/issues/7503)
-
-* Unicode predicates like ``.isdigit()`` are now allowed to fail in the Limited API.
- (Github issue https://github.com/cython/cython/issues/7602)
-
-* Conditional expressions mixing Python float and int object types could accidentally
- infer float as the common result type, instead of treating both independently.
-
-* Using ``sizeof()`` in the size declarations of ``extern`` arrays failed.
- (Github issue https://github.com/cython/cython/issues/7451)
-
-* Enabling profiling generated invalid C code for non-Python return tuples.
- (Github issue https://github.com/cython/cython/issues/7580)
-
-* ``abs()`` on C ``long long`` values could generate invalid C code.
-
-* When the ``CYTHON_AVOID_BORROWED_REFS`` C macro is enabled, e.g. in GraalPython,
- dict iteration could fail to compile.
- Patch by Michael Šimáček. (Github issue https://github.com/cython/cython/issues/7631)
-
-* A C compiler warning about unused functions was resolved.
- (Github issue https://github.com/cython/cython/issues/7560)
-
-* The ``py_safe_call_once()`` C++ mutex helper function in ``libcpp.mutex``
- failed to compile.
- (Github issue https://github.com/cython/cython/issues/7585)
-
-* The ``cpython.array`` declarations were adapted for Python 3.15. Direct access
- to the C struct of the ``array.array`` data type might require user code changes.
- (Github issue https://github.com/cython/cython/issues/7659)
-
-* Spaces in file paths written to the ``depfile`` were not escaped.
- Patch by Loïc Estève. (Github issue https://github.com/cython/cython/issues/7423)
-
-* Cython's cache failed to restore multi-file results.
- (Github issue https://github.com/cython/cython/issues/7559)
-
-* Using Tempita from its command line failed with a name error.
- (Github issue https://github.com/cython/cython/issues/7567)
-
-Other changes
--------------
-
-* The known builtin types were updated for Py3.15.
+* The ``.ag_running`` flag attribute of async generators was always false on big-endian systems.
diff --git a/contrib/tools/cython/.yandex_meta/override.nix b/contrib/tools/cython/.yandex_meta/override.nix
index aea78547bf9..fd901b25082 100644
--- a/contrib/tools/cython/.yandex_meta/override.nix
+++ b/contrib/tools/cython/.yandex_meta/override.nix
@@ -1,10 +1,10 @@
pkgs: attrs: with pkgs; with pkgs.python311.pkgs; with attrs; rec {
- version = "3.2.5";
+ version = "3.2.8";
src = fetchPypi {
pname = "cython";
inherit version;
- hash = "sha256-PdQuTPNq0V8mW9/sIzfMAMaIyOttN0/9E7sZQ3wnu6E=";
+ hash = "sha256-9PI6VrJSIaBvkYF/6PMRSri0ik+scxh9u2S8LEqHlh8=";
};
patches = [];
diff --git a/contrib/tools/cython/CHANGES.rst b/contrib/tools/cython/CHANGES.rst
index a495a987b4b..b97a2aeb4dc 100644
--- a/contrib/tools/cython/CHANGES.rst
+++ b/contrib/tools/cython/CHANGES.rst
@@ -2,6 +2,55 @@
Cython Changelog
================
+3.2.8 (2026-06-30)
+==================
+
+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 :issue:`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 :issue:`7769`)
+
+* The local function state used by ``sys.monitoring`` read from uninitialised memory.
+ (Github issue :issue:`7774`)
+
+* The ``.ag_running`` flag attribute of async generators was always false on big-endian systems.
+
+
+3.2.6 (2026-06-24)
+==================
+
+Bugs fixed
+----------
+
+* ``@functools.wraps()`` was broken in Py3.14+ for Cython compiled functions.
+ (Github issue :issue:`7675`)
+
+* A double-free in the t-string code was fixed.
+ (Github issue :issue:`7712`)
+
+* The ``-`` operator declarations for iterators in ``libcpp.vector`` we corrected.
+ Patch by Vadim Markovtsev. (Github issue :issue:`7717`)
+
+* The shared utility code module no longer uses a temporary file path that
+ changed the C code on each generation.
+ (Github issue :issue:`7723`)
+
+* On 32 bit platforms, cached constants are no longer made immortal during module import.
+ (Github issue :issue:`7744`)
+
+Other changes
+-------------
+
+* Binary wheels are now built with ``-DNDEBUG`` to discard runtime assertions from CPython's
+ inline functions.
+
+
3.2.5 (2026-05-23)
==================
diff --git a/contrib/tools/cython/Cython/Build/Dependencies.py b/contrib/tools/cython/Cython/Build/Dependencies.py
index 3726a72b529..d45e53d832b 100644
--- a/contrib/tools/cython/Cython/Build/Dependencies.py
+++ b/contrib/tools/cython/Cython/Build/Dependencies.py
@@ -52,7 +52,7 @@ def extended_iglob(pattern):
# because '/' is generally common for relative paths.
if '**/' in pattern or os.sep == '\\' and '**\\' in pattern:
seen = set()
- first, rest = re.split(r'\*\*[%s]' % ('/\\\\' if os.sep == '\\' else '/'), pattern, 1)
+ first, rest = re.split(r'\*\*[%s]' % ('/\\\\' if os.sep == '\\' else '/'), pattern, maxsplit=1)
if first:
first = iglob(first + os.sep)
else:
diff --git a/contrib/tools/cython/Cython/Build/SharedModule.py b/contrib/tools/cython/Cython/Build/SharedModule.py
index fed6263cd89..45da4b46238 100644
--- a/contrib/tools/cython/Cython/Build/SharedModule.py
+++ b/contrib/tools/cython/Cython/Build/SharedModule.py
@@ -1,13 +1,10 @@
import os
-import re
-import shutil
-import tempfile
from Cython.Compiler import (
MemoryView, Code, Options, Pipeline, Errors, Main, Symtab
)
from Cython.Compiler.StringEncoding import EncodedString
-from Cython.Compiler.Scanning import FileSourceDescriptor
+from Cython.Compiler.Scanning import SharedUtilitySourceDescriptor
def create_shared_library_pipeline(context, scope, options, result):
@@ -72,23 +69,17 @@ def generate_shared_module(options):
Errors.open_listing_file(None)
dest_c_file = options.shared_c_file_path
+ pyx_file = os.path.splitext(dest_c_file)[0] + '.pyx'
module_name = os.path.splitext(os.path.basename(dest_c_file))[0]
context = Main.Context.from_options(options)
scope = Symtab.ModuleScope('MemoryView', parent_module = None, context = context, is_package=False)
- with tempfile.TemporaryDirectory() as tmpdirname:
- pyx_file = os.path.join(tmpdirname, f'{module_name}.pyx')
- c_file = os.path.join(tmpdirname, f'{module_name}.c')
- with open(pyx_file, 'w'):
- pass
- source_desc = FileSourceDescriptor(pyx_file)
- comp_src = Main.CompilationSource(source_desc, EncodedString(module_name), os.getcwd())
- result = Main.create_default_resultobj(comp_src, options)
+ source_desc = SharedUtilitySourceDescriptor(pyx_file)
+ comp_src = Main.CompilationSource(source_desc, EncodedString(module_name), os.getcwd())
+ result = Main.create_default_resultobj(comp_src, options)
- pipeline = create_shared_library_pipeline(context, scope, options, result)
- err, enddata = Pipeline.run_pipeline(pipeline, comp_src)
- if err is None:
- shutil.copy(c_file, dest_c_file)
+ pipeline = create_shared_library_pipeline(context, scope, options, result)
+ err, enddata = Pipeline.run_pipeline(pipeline, comp_src)
return err, enddata
diff --git a/contrib/tools/cython/Cython/Compiler/Code.py b/contrib/tools/cython/Cython/Compiler/Code.py
index 630683bf166..ed783164ff8 100644
--- a/contrib/tools/cython/Cython/Compiler/Code.py
+++ b/contrib/tools/cython/Cython/Compiler/Code.py
@@ -2429,19 +2429,26 @@ class GlobalState:
writer.putln("{")
writer.putln(f"PyObject **table = {array_cname};")
writer.putln(f"for (Py_ssize_t i=0; i<{constant_count}; ++i) {{")
- writer.putln("#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING")
+ writer.putln("#if PY_VERSION_HEX >= 0x030F0000")
+ writer.putln("PyUnstable_SetImmortal(table[i]);")
+ writer.putln("#elif CYTHON_COMPILING_IN_CPYTHON_FREETHREADING")
# We don't want to set the refcount on shared constants (e.g. cached integers)
# because setting the refcount isn't thread-safe. The chances are that most of the constants
# that this applies to are already immortal though so that isn't a great loss.
+ # Overflow, e.g. on 32 bit systems.
+ writer.putln("if ((PY_SSIZE_T_MAX <= _Py_IMMORTAL_REFCNT_LOCAL)) break;")
writer.putln("#if PY_VERSION_HEX < 0x030E0000")
writer.putln("if (_Py_IsOwnedByCurrentThread(table[i]) && Py_REFCNT(table[i]) == 1)")
writer.putln("#else")
writer.putln("if (PyUnstable_Object_IsUniquelyReferenced(table[i]))")
writer.putln("#endif")
writer.putln("{")
- writer.putln("Py_SET_REFCNT(table[i], _Py_IMMORTAL_REFCNT_LOCAL);")
+ # Go one higher than we think we need to because of a bug in SET_REFCNT check in CPython
+ writer.putln("Py_SET_REFCNT(table[i], ((Py_ssize_t)_Py_IMMORTAL_REFCNT_LOCAL + 1));")
writer.putln("}")
writer.putln("#else")
+ # Overflow, e.g. on 32 bit systems.
+ writer.putln("if ((PY_SSIZE_T_MAX < _Py_IMMORTAL_INITIAL_REFCNT)) break;")
writer.putln("Py_SET_REFCNT(table[i], _Py_IMMORTAL_INITIAL_REFCNT);")
writer.putln("#endif")
writer.putln("}") # for()
diff --git a/contrib/tools/cython/Cython/Compiler/ModuleNode.py b/contrib/tools/cython/Cython/Compiler/ModuleNode.py
index eb683f8249d..a14f3e9e2ee 100644
--- a/contrib/tools/cython/Cython/Compiler/ModuleNode.py
+++ b/contrib/tools/cython/Cython/Compiler/ModuleNode.py
@@ -2020,14 +2020,17 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
if not entry or not entry.is_special:
return
+ code.globalstate.use_utility_code(
+ UtilityCode.load_cached("DeallocKeepAlive", "ExtensionTypes.c"))
code.putln("{")
code.putln("PyObject *etype, *eval, *etb;")
code.putln("PyErr_Fetch(&etype, &eval, &etb);")
- # increase the refcount while we are calling into user code
- # to prevent recursive deallocation
- code.putln("__Pyx_SET_REFCNT(o, Py_REFCNT(o) + 1);")
+ # Keep the object alive while we are calling into user code, to prevent
+ # the user code from triggering recursive deallocation. On free-threading
+ # this must not use Py_SET_REFCNT() (see DeallocKeepAlive in ExtensionTypes.c).
+ code.putln("__Pyx_DeallocKeepAliveBegin(o);")
code.putln("%s(o);" % entry.func_cname)
- code.putln("__Pyx_SET_REFCNT(o, Py_REFCNT(o) - 1);")
+ code.putln("__Pyx_DeallocKeepAliveEnd(o);")
code.putln("PyErr_Restore(etype, eval, etb);")
code.putln("}")
diff --git a/contrib/tools/cython/Cython/Compiler/Scanning.py b/contrib/tools/cython/Cython/Compiler/Scanning.py
index d63c1263f27..d843960dd17 100644
--- a/contrib/tools/cython/Cython/Compiler/Scanning.py
+++ b/contrib/tools/cython/Cython/Compiler/Scanning.py
@@ -278,6 +278,15 @@ class StringSourceDescriptor(SourceDescriptor):
return "<StringSourceDescriptor:%s>" % self.name
+class SharedUtilitySourceDescriptor(FileSourceDescriptor):
+ """
+ A specialized source descriptor for shared utility code only. Not part of public API.
+ """
+
+ def get_file_object(self, encoding=None, error_handling=None):
+ from io import StringIO
+ return StringIO('')
+
#------------------------------------------------------------------
class PyrexScanner(Scanner):
diff --git a/contrib/tools/cython/Cython/Includes/libcpp/vector.pxd b/contrib/tools/cython/Cython/Includes/libcpp/vector.pxd
index f7f75928640..14f453ba682 100644
--- a/contrib/tools/cython/Cython/Includes/libcpp/vector.pxd
+++ b/contrib/tools/cython/Cython/Includes/libcpp/vector.pxd
@@ -79,8 +79,8 @@ cdef extern from "<vector>" namespace "std" nogil:
reverse_iterator operator--(int)
reverse_iterator operator+(size_type)
reverse_iterator operator-(size_type)
- difference_type operator-(iterator)
- difference_type operator-(const_iterator)
+ difference_type operator-(reverse_iterator)
+ difference_type operator-(const_reverse_iterator)
bint operator==(reverse_iterator)
bint operator==(const_reverse_iterator)
bint operator!=(reverse_iterator)
@@ -104,8 +104,8 @@ cdef extern from "<vector>" namespace "std" nogil:
const_reverse_iterator operator--(int)
const_reverse_iterator operator+(size_type)
const_reverse_iterator operator-(size_type)
- difference_type operator-(iterator)
- difference_type operator-(const_iterator)
+ difference_type operator-(reverse_iterator)
+ difference_type operator-(const_reverse_iterator)
bint operator==(reverse_iterator)
bint operator==(const_reverse_iterator)
bint operator!=(reverse_iterator)
diff --git a/contrib/tools/cython/Cython/Shadow.py b/contrib/tools/cython/Cython/Shadow.py
index 8339642e91b..1ec77baac3a 100644
--- a/contrib/tools/cython/Cython/Shadow.py
+++ b/contrib/tools/cython/Cython/Shadow.py
@@ -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.5"
+__version__ = "3.2.8"
# BEGIN shameless copy from Cython/minivect/minitypes.py
diff --git a/contrib/tools/cython/Cython/Utility/AsyncGen.c b/contrib/tools/cython/Cython/Utility/AsyncGen.c
index 4999487d91d..c2b9fe1d449 100644
--- a/contrib/tools/cython/Cython/Utility/AsyncGen.c
+++ b/contrib/tools/cython/Cython/Utility/AsyncGen.c
@@ -346,11 +346,19 @@ __Pyx_async_gen_self_method(PyObject *g, PyObject *arg) {
}
+static PyObject *
+__Pyx_async_gen_get_running(__pyx_PyAsyncGenObject *o, void *context) {
+ CYTHON_UNUSED_VAR(context);
+ return __Pyx_NewRef(o->ag_running_async ? Py_True : Py_False);
+}
+
+
static PyGetSetDef __Pyx_async_gen_getsetlist[] = {
{"__name__", (getter)__Pyx_Coroutine_get_name, (setter)__Pyx_Coroutine_set_name,
PyDoc_STR("name of the async generator"), 0},
{"__qualname__", (getter)__Pyx_Coroutine_get_qualname, (setter)__Pyx_Coroutine_set_qualname,
PyDoc_STR("qualified name of the async generator"), 0},
+ {"ag_running", (getter)__Pyx_async_gen_get_running, NULL, NULL, 0},
//REMOVED: {(char*) "ag_await", (getter)coro_get_cr_await, NULL,
//REMOVED: (char*) PyDoc_STR("object being awaited on, or None")},
{0, 0, 0, 0, 0} /* Sentinel */
@@ -358,7 +366,6 @@ static PyGetSetDef __Pyx_async_gen_getsetlist[] = {
static PyMemberDef __Pyx_async_gen_memberlist[] = {
//REMOVED: {(char*) "ag_frame", T_OBJECT, offsetof(__pyx_PyAsyncGenObject, ag_frame), READONLY},
- {"ag_running", T_BOOL, offsetof(__pyx_PyAsyncGenObject, ag_running_async), READONLY, NULL},
//REMOVED: {(char*) "ag_code", T_OBJECT, offsetof(__pyx_PyAsyncGenObject, ag_code), READONLY},
//ADDED: "ag_await"
{"ag_await", T_OBJECT, offsetof(__pyx_CoroutineObject, yieldfrom), READONLY,
diff --git a/contrib/tools/cython/Cython/Utility/Coroutine.c b/contrib/tools/cython/Cython/Utility/Coroutine.c
index 7d65bc73fe9..a9ee81d4f38 100644
--- a/contrib/tools/cython/Cython/Utility/Coroutine.c
+++ b/contrib/tools/cython/Cython/Utility/Coroutine.c
@@ -1654,6 +1654,10 @@ static __pyx_CoroutineObject *__Pyx__Coroutine_NewInit(
Py_XINCREF(code);
gen->gi_code = code;
gen->gi_frame = NULL;
+#if CYTHON_USE_SYS_MONITORING && (CYTHON_PROFILE || CYTHON_TRACE)
+ memset(gen->$monitoring_states_cname, 0, sizeof(gen->$monitoring_states_cname));
+ gen->$monitoring_version_cname = 0;
+#endif
PyObject_GC_Track(gen);
return gen;
diff --git a/contrib/tools/cython/Cython/Utility/CythonFunction.c b/contrib/tools/cython/Cython/Utility/CythonFunction.c
index 38e2f1cfc75..cbb7f743197 100644
--- a/contrib/tools/cython/Cython/Utility/CythonFunction.c
+++ b/contrib/tools/cython/Cython/Utility/CythonFunction.c
@@ -134,6 +134,7 @@ static PyObject * __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS_METHOD(PyObject
//@requires: ModuleSetupCode.c::IncludeStructmemberH
//@requires: ObjectHandling.c::PyObjectGetAttrStr
//@requires: ObjectHandling.c::CachedMethodType
+//@requires: ObjectHandling.c::PyObjectCallOneArg
//@requires: ExtensionTypes.c::CallTypeTraverse
//@requires: Synchronization.c::CriticalSections
//@substitute: naming
@@ -461,6 +462,8 @@ __Pyx_CyFunction_get_kwdefaults(__pyx_CyFunctionObject *op, void *context) {
return result;
}
+static int __Pyx_CyFunction_set_annotate_in_dict_if_exists(PyObject *op_in, PyObject *value); /*proto*/
+
static int
__Pyx_CyFunction_set_annotations(__pyx_CyFunctionObject *op, PyObject* value, void *context) {
CYTHON_UNUSED_VAR(context);
@@ -475,9 +478,59 @@ __Pyx_CyFunction_set_annotations(__pyx_CyFunctionObject *op, PyObject* value, vo
__Pyx_BEGIN_CRITICAL_SECTION(op);
__Pyx_Py_XDECREF_SET(op->func_annotations, value);
__Pyx_END_CRITICAL_SECTION();
+ if (unlikely(__Pyx_CyFunction_set_annotate_in_dict_if_exists((PyObject*) op, Py_None) < 0)) return -1;
return 0;
}
+static int
+__Pyx_CyFunction_get_dict_if_exists(PyObject *op_in, PyObject **dict) {
+ /* Return 1 if the function dict exists, 0 otherwise. This cannot fail:
+ * _PyObject_GetDictPtr() may clear errors internally, but never reports them. */
+#if CYTHON_COMPILING_IN_PYPY
+ *dict = PyObject_GenericGetDict(op_in, NULL);
+#elif CYTHON_COMPILING_IN_LIMITED_API || PY_VERSION_HEX < 0x030C0000
+ *dict = ((__pyx_CyFunctionObject*) op_in)->func_dict;
+#else
+ PyObject **dictptr = _PyObject_GetDictPtr(op_in);
+ *dict = likely(dictptr) ? *dictptr : NULL;
+#endif
+ return *dict ? 1 : 0;
+}
+
+static int
+__Pyx_CyFunction_get_annotate_from_dict_if_exists(PyObject *op_in, PyObject **annotate) {
+ PyObject *dict;
+ int dict_found;
+ *annotate = NULL;
+ dict_found = __Pyx_CyFunction_get_dict_if_exists(op_in, &dict);
+ if (!dict_found) return 0;
+ return __Pyx_PyDict_GetItemRef(dict, PYIDENT("__annotate__"), annotate);
+}
+
+static int
+__Pyx_CyFunction_set_annotate_in_dict_if_exists(PyObject *op_in, PyObject *value) {
+ PyObject *dict;
+ int dict_found;
+ dict_found = __Pyx_CyFunction_get_dict_if_exists(op_in, &dict);
+ if (!dict_found) return 0;
+ return PyDict_SetItem(dict, PYIDENT("__annotate__"), value);
+}
+
+static int
+__Pyx_CyFunction_set_annotate_in_dict(PyObject *op_in, PyObject *value) {
+ PyObject *dict;
+ int result;
+#if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030A0000
+ dict = __Pyx_CyFunction_get_dict((__pyx_CyFunctionObject*) op_in, NULL);
+#else
+ dict = PyObject_GenericGetDict(op_in, NULL);
+#endif
+ if (unlikely(!dict)) return -1;
+ result = PyDict_SetItem(dict, PYIDENT("__annotate__"), value);
+ Py_DECREF(dict);
+ return result;
+}
+
static PyObject *
__Pyx_CyFunction_get_annotations_locked(__pyx_CyFunctionObject *op) {
PyObject* result = op->func_annotations;
@@ -491,15 +544,100 @@ __Pyx_CyFunction_get_annotations_locked(__pyx_CyFunctionObject *op) {
}
static PyObject *
-__Pyx_CyFunction_get_annotations(__pyx_CyFunctionObject *op, void *context) {
- PyObject *result;
+__Pyx_CyFunction_get_annotations(PyObject *op_in, void *context) {
+ PyObject *annotate = NULL;
+ PyObject *result = NULL;
+ __pyx_CyFunctionObject *op = (__pyx_CyFunctionObject*) op_in;
CYTHON_UNUSED_VAR(context);
- __Pyx_BEGIN_CRITICAL_SECTION(op);
- result = __Pyx_CyFunction_get_annotations_locked(op);
+ __Pyx_BEGIN_CRITICAL_SECTION(op_in);
+ result = __Pyx_XNewRef(op->func_annotations);
+ __Pyx_END_CRITICAL_SECTION();
+ if (result) return result;
+
+ if (unlikely(__Pyx_CyFunction_get_annotate_from_dict_if_exists(op_in, &annotate) < 0)) return NULL;
+ if (!annotate || annotate == Py_None) {
+ Py_XDECREF(annotate);
+ __Pyx_BEGIN_CRITICAL_SECTION(op_in);
+ result = __Pyx_CyFunction_get_annotations_locked(op);
+ __Pyx_END_CRITICAL_SECTION();
+ return result;
+ }
+
+ PyObject *format = PyLong_FromLong(1L); // annotationlib.Format.VALUE
+ if (likely(format)) {
+ result = __Pyx_PyObject_CallOneArg(annotate, format);
+ Py_DECREF(format);
+ }
+ Py_DECREF(annotate);
+ if (unlikely(!result)) return NULL;
+ if (unlikely(!PyDict_Check(result))) {
+ PyErr_SetString(PyExc_TypeError, "__annotate__ must return a dict");
+ Py_DECREF(result);
+ return NULL;
+ }
+ __Pyx_BEGIN_CRITICAL_SECTION(op_in);
+ __Pyx_Py_XDECREF_SET(op->func_annotations, __Pyx_NewRef(result));
__Pyx_END_CRITICAL_SECTION();
return result;
}
+static PyObject *__Pyx_CyFunction_annotate_impl(PyObject *self, PyObject *args) {
+ // The signature of this function is 0 or 1 args, where arg should be an int (if passed).
+ // However, for this basic placeholder implementation, we don't care and don't check it.
+ CYTHON_UNUSED_VAR(args);
+ if (unlikely(!self)) {
+ PyErr_SetString(PyExc_SystemError, "cython __annotate__ called without 'self' argument");
+ }
+ Py_XINCREF(self);
+ return self;
+}
+
+static PyMethodDef __Pyx_CyFunction_annotate_method = {
+ "__annotate__",
+ (PyCFunction)(void (*)(void))__Pyx_CyFunction_annotate_impl,
+ METH_VARARGS,
+ "Placeholder __annotate__ function to allow 'functools.wraps' to work "
+ "on Cython functions."
+};
+
+// We don't yet support PEP649 properly, so __annotate__ is
+// implemented in a minimal way, just so that functools.wraps works.
+static PyObject *
+__Pyx_CyFunction_get_annotate(PyObject *op_in, void *context) {
+ PyObject *annotate = NULL;
+ CYTHON_UNUSED_VAR(context);
+ if (unlikely(__Pyx_CyFunction_get_annotate_from_dict_if_exists(op_in, &annotate) < 0)) return NULL;
+ if (annotate) return annotate;
+
+ PyObject *annotations = __Pyx_CyFunction_get_annotations(op_in, NULL);
+ if (unlikely(!annotations)) return NULL;
+ PyObject *method = PyCFunction_New(
+ &__Pyx_CyFunction_annotate_method,
+ annotations);
+ Py_DECREF(annotations);
+ return method;
+}
+
+static int
+__Pyx_CyFunction_set_annotate(PyObject *op_in, PyObject* value, void *context) {
+ CYTHON_UNUSED_VAR(context);
+ if (value == NULL) {
+ PyErr_SetString(PyExc_TypeError, "__annotate__ cannot be deleted");
+ return -1;
+ }
+ if (unlikely(value != Py_None && !PyCallable_Check(value))) {
+ PyErr_SetString(PyExc_TypeError, "__annotate__ must be callable or None");
+ return -1;
+ }
+ if (value != Py_None) {
+ __pyx_CyFunctionObject *op = (__pyx_CyFunctionObject*) op_in;
+ __Pyx_BEGIN_CRITICAL_SECTION(op_in);
+ Py_CLEAR(op->func_annotations);
+ __Pyx_END_CRITICAL_SECTION();
+ }
+ return __Pyx_CyFunction_set_annotate_in_dict(op_in, value);
+}
+
static PyObject *
__Pyx_CyFunction_get_is_coroutine_value(__pyx_CyFunctionObject *op) {
int is_coroutine = op->flags & __Pyx_CYFUNCTION_COROUTINE;
@@ -649,6 +787,7 @@ static PyGetSetDef __pyx_CyFunction_getsets[] = {
{"__defaults__", (getter)__Pyx_CyFunction_get_defaults, (setter)__Pyx_CyFunction_set_defaults, 0, 0},
{"__kwdefaults__", (getter)__Pyx_CyFunction_get_kwdefaults, (setter)__Pyx_CyFunction_set_kwdefaults, 0, 0},
{"__annotations__", (getter)__Pyx_CyFunction_get_annotations, (setter)__Pyx_CyFunction_set_annotations, 0, 0},
+ {"__annotate__", (getter)__Pyx_CyFunction_get_annotate, (setter)__Pyx_CyFunction_set_annotate, 0, 0},
{"_is_coroutine", (getter)__Pyx_CyFunction_get_is_coroutine, 0, 0, 0},
// {"__signature__", (getter)__Pyx_CyFunction_get_signature, 0, 0, 0},
#if CYTHON_COMPILING_IN_LIMITED_API
diff --git a/contrib/tools/cython/Cython/Utility/ExtensionTypes.c b/contrib/tools/cython/Cython/Utility/ExtensionTypes.c
index 1e89372fd71..131adb6432c 100644
--- a/contrib/tools/cython/Cython/Utility/ExtensionTypes.c
+++ b/contrib/tools/cython/Cython/Utility/ExtensionTypes.c
@@ -402,6 +402,34 @@ static int __Pyx_PyType_Ready(PyTypeObject *t) {
#define __Pyx_TRASHCAN_END
#endif
+/////////////// DeallocKeepAlive.proto ///////////////
+
+// Keep `o` alive across a call into user __dealloc__ code, to prevent the user
+// code from triggering recursive deallocation, then drop the temporary reference.
+//
+// On the GIL build this is a plain refcount bump. On free-threading we must NOT
+// use Py_SET_REFCNT(o, 1): the object reaching tp_dealloc is unowned and merged
+// (ob_ref_shared == _Py_REF_MERGED), so Py_SET_REFCNT takes the unowned branch and
+// writes ob_ref_shared = _Py_REF_SHARED(1, _Py_REF_MERGED), i.e. "merged, shared
+// count 1" -- indistinguishable from a live object. A concurrent
+// PyUnstable_TryIncRef() would then succeed and resurrect the dying object
+// (use-after-free). Instead we mirror CPython's _PyObject_ResurrectStart/End:
+// re-take ownership and keep the *shared* refcount at the refuse sentinel (0), so
+// the bump is invisible to other threads and TryIncRef keeps refusing.
+
+#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING
+#define __Pyx_DeallocKeepAliveBegin(o) do { \
+ _Py_atomic_store_uintptr_relaxed(&(o)->ob_tid, _Py_ThreadId()); \
+ _Py_atomic_store_uint32_relaxed(&(o)->ob_ref_local, 1); \
+ _Py_atomic_store_ssize_relaxed(&(o)->ob_ref_shared, 0); \
+ } while (0)
+#define __Pyx_DeallocKeepAliveEnd(o) \
+ _Py_atomic_store_uint32_relaxed(&(o)->ob_ref_local, 0)
+#else
+#define __Pyx_DeallocKeepAliveBegin(o) __Pyx_SET_REFCNT(o, Py_REFCNT(o) + 1)
+#define __Pyx_DeallocKeepAliveEnd(o) __Pyx_SET_REFCNT(o, Py_REFCNT(o) - 1)
+#endif
+
/////////////// CallNextTpDealloc.proto ///////////////
static void __Pyx_call_next_tp_dealloc(PyObject* obj, destructor current_tp_dealloc);
diff --git a/contrib/tools/cython/Cython/Utility/TString.c b/contrib/tools/cython/Cython/Utility/TString.c
index a18cf4ac01c..e27c755d22f 100644
--- a/contrib/tools/cython/Cython/Utility/TString.c
+++ b/contrib/tools/cython/Cython/Utility/TString.c
@@ -301,8 +301,8 @@ static PyObject* __Pyx_MakeTemplateLibTemplate(PyObject *strings, PyObject *inte
if (unlikely(__Pyx_VectorcallBuilder_AddArg(PYIDENT("interpolations"), interpolations, kwargs_builder, args, 1)<0))
goto failed_shortcut;
result = __Pyx_Object_Vectorcall_CallFromBuilder(tp, args, 0, kwargs_builder);
- Py_DECREF(kwargs_builder);
if (result) {
+ Py_DECREF(kwargs_builder);
Py_DECREF(tp);
return result;
}
diff --git a/contrib/tools/cython/cython.py b/contrib/tools/cython/cython.py
index 6f4880a93cc..159014bd193 100755
--- a/contrib/tools/cython/cython.py
+++ b/contrib/tools/cython/cython.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
-# Change content of this file to change uids for cython programs - cython 3.2.5 r0
+# Change content of this file to change uids for cython programs - cython 3.2.8 r0
#
# Cython -- Main Program, generic
diff --git a/contrib/tools/cython/ya.make b/contrib/tools/cython/ya.make
index 61e66dbe8d3..fd08615635d 100644
--- a/contrib/tools/cython/ya.make
+++ b/contrib/tools/cython/ya.make
@@ -11,9 +11,9 @@ LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
SUBSCRIBER(g:python-contrib)
-VERSION(3.2.5)
+VERSION(3.2.8)
-ORIGINAL_SOURCE(mirror://pypi/c/cython/cython-3.2.5.tar.gz)
+ORIGINAL_SOURCE(mirror://pypi/c/cython/cython-3.2.8.tar.gz)
NO_LINT()