diff options
Diffstat (limited to 'contrib/tools')
| -rw-r--r-- | contrib/tools/cython/.dist-info/METADATA | 83 | ||||
| -rw-r--r-- | contrib/tools/cython/.yandex_meta/override.nix | 4 | ||||
| -rw-r--r-- | contrib/tools/cython/CHANGES.rst | 49 | ||||
| -rw-r--r-- | contrib/tools/cython/Cython/Build/Dependencies.py | 2 | ||||
| -rw-r--r-- | contrib/tools/cython/Cython/Build/SharedModule.py | 23 | ||||
| -rw-r--r-- | contrib/tools/cython/Cython/Compiler/Code.py | 11 | ||||
| -rw-r--r-- | contrib/tools/cython/Cython/Compiler/ModuleNode.py | 11 | ||||
| -rw-r--r-- | contrib/tools/cython/Cython/Compiler/Scanning.py | 9 | ||||
| -rw-r--r-- | contrib/tools/cython/Cython/Includes/libcpp/vector.pxd | 8 | ||||
| -rw-r--r-- | contrib/tools/cython/Cython/Shadow.py | 2 | ||||
| -rw-r--r-- | contrib/tools/cython/Cython/Utility/AsyncGen.c | 9 | ||||
| -rw-r--r-- | contrib/tools/cython/Cython/Utility/Coroutine.c | 4 | ||||
| -rw-r--r-- | contrib/tools/cython/Cython/Utility/CythonFunction.c | 147 | ||||
| -rw-r--r-- | contrib/tools/cython/Cython/Utility/ExtensionTypes.c | 28 | ||||
| -rw-r--r-- | contrib/tools/cython/Cython/Utility/TString.c | 2 | ||||
| -rwxr-xr-x | contrib/tools/cython/cython.py | 2 | ||||
| -rw-r--r-- | contrib/tools/cython/ya.make | 4 |
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() |
