From 5f0bd3ad0549b6464326920e29663516d5ec5969 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: May 21 2020 13:45:00 +0000 Subject: Work around class- and staticmethod breakage Note that staticmethod fused functions are still broken. --- diff --git a/Cython.spec b/Cython.spec index 58b7ce7..3df6edf 100644 --- a/Cython.spec +++ b/Cython.spec @@ -6,13 +6,22 @@ Name: Cython Version: 0.29.17 %global upver %{version_no_tilde %{nil}} -Release: 1%{?dist} +Release: 2%{?dist} Summary: Language for writing Python extension modules License: ASL 2.0 URL: http://www.cython.org Source: https://github.com/cython/cython/archive/%{upver}/%{srcname}-%{version}.tar.gz +# Partially work around issues with class and static methods +# See https://bugzilla.redhat.com/show_bug.cgi?id=1788506 +# Mostly backported from upstream: https://github.com/cython/cython/pull/3106 +# This also: +# - Removes staticmethod optimizations for normal functions +# - Removes failing test for staticmethod fused functions, which still fail +# See also: https://github.com/cython/cython/issues/3614 +Patch3106: class-static-method-workaround.patch + BuildRequires: gcc %if %{with tests} BuildRequires: gcc-c++ @@ -109,6 +118,10 @@ cp -p cython-mode-init.el cython-mode-init.elc %{buildroot}%{_emacs_sitestartdir %{_emacs_sitestartdir}/cython*.el* %changelog +* Wed May 13 2020 Petr Viktorin - 0.29.17-2 +- Backport classmethod fixes + Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1788506 + * Tue Apr 28 2020 Marcel Plch - 0.29.17-1 - Update to 0.29.17 diff --git a/class-static-method-workaround.patch b/class-static-method-workaround.patch new file mode 100644 index 0000000..4f854e0 --- /dev/null +++ b/class-static-method-workaround.patch @@ -0,0 +1,139 @@ +diff -U3 -r cython-0.29.17.orig/Cython/Compiler/ExprNodes.py cython-0.29.17/Cython/Compiler/ExprNodes.py +--- cython-0.29.17.orig/Cython/Compiler/ExprNodes.py 2020-04-26 13:48:48.000000000 +0200 ++++ cython-0.29.17/Cython/Compiler/ExprNodes.py 2020-05-15 17:44:55.157172257 +0200 +@@ -2295,8 +2295,10 @@ + setter = 'PyDict_SetItem' + namespace = Naming.moddict_cname + elif entry.is_pyclass_attr: +- code.globalstate.use_utility_code(UtilityCode.load_cached("SetNameInClass", "ObjectHandling.c")) +- setter = '__Pyx_SetNameInClass' ++ # Special-case setting __new__ ++ n = "SetNewInClass" if self.name == "__new__" else "SetNameInClass" ++ code.globalstate.use_utility_code(UtilityCode.load_cached(n, "ObjectHandling.c")) ++ setter = '__Pyx_' + n + else: + assert False, repr(entry) + code.put_error_if_neg( +diff -U3 -r cython-0.29.17.orig/Cython/Compiler/Nodes.py cython-0.29.17/Cython/Compiler/Nodes.py +--- cython-0.29.17.orig/Cython/Compiler/Nodes.py 2020-04-26 13:48:48.000000000 +0200 ++++ cython-0.29.17/Cython/Compiler/Nodes.py 2020-05-15 17:44:55.159172253 +0200 +@@ -2872,7 +2872,6 @@ + func = decorator.decorator + if func.is_name: + self.is_classmethod |= func.name == 'classmethod' +- self.is_staticmethod |= func.name == 'staticmethod' + + if self.is_classmethod and env.lookup_here('classmethod'): + # classmethod() was overridden - not much we can do here ... +diff -U3 -r cython-0.29.17.orig/Cython/Utility/CythonFunction.c cython-0.29.17/Cython/Utility/CythonFunction.c +--- cython-0.29.17.orig/Cython/Utility/CythonFunction.c 2020-04-26 13:48:48.000000000 +0200 ++++ cython-0.29.17/Cython/Utility/CythonFunction.c 2020-05-15 17:44:55.160172251 +0200 +@@ -548,21 +548,6 @@ + + static PyObject *__Pyx_CyFunction_descr_get(PyObject *func, PyObject *obj, PyObject *type) + { +- __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func; +- +- if (m->flags & __Pyx_CYFUNCTION_STATICMETHOD) { +- Py_INCREF(func); +- return func; +- } +- +- if (m->flags & __Pyx_CYFUNCTION_CLASSMETHOD) { +- if (type == NULL) +- type = (PyObject *)(Py_TYPE(obj)); +- return __Pyx_PyMethod_New(func, type, (PyObject *)(Py_TYPE(type))); +- } +- +- if (obj == Py_None) +- obj = NULL; + return __Pyx_PyMethod_New(func, obj, type); + } + +diff -U3 -r cython-0.29.17.orig/Cython/Utility/ObjectHandling.c cython-0.29.17/Cython/Utility/ObjectHandling.c +--- cython-0.29.17.orig/Cython/Utility/ObjectHandling.c 2020-04-26 13:48:48.000000000 +0200 ++++ cython-0.29.17/Cython/Utility/ObjectHandling.c 2020-05-15 17:44:55.160172251 +0200 +@@ -1163,6 +1163,30 @@ + #define __Pyx_SetNameInClass(ns, name, value) PyObject_SetItem(ns, name, value) + #endif + ++/////////////// SetNewInClass.proto /////////////// ++ ++static int __Pyx_SetNewInClass(PyObject *ns, PyObject *name, PyObject *value); ++ ++/////////////// SetNewInClass /////////////// ++//@requires: SetNameInClass ++ ++// Special-case setting __new__: if it's a Cython function, wrap it in a ++// staticmethod. This is similar to what Python does for a Python function ++// called __new__. ++static int __Pyx_SetNewInClass(PyObject *ns, PyObject *name, PyObject *value) { ++#ifdef __Pyx_CyFunction_USED ++ int ret; ++ if (__Pyx_CyFunction_Check(value)) { ++ PyObject *staticnew = PyStaticMethod_New(value); ++ if (unlikely(!staticnew)) return -1; ++ ret = __Pyx_SetNameInClass(ns, name, staticnew); ++ Py_DECREF(staticnew); ++ return ret; ++ } ++#endif ++ return __Pyx_SetNameInClass(ns, name, value); ++} ++ + + /////////////// GetModuleGlobalName.proto /////////////// + //@requires: PyDictVersioning +Only in cython-0.29.17.orig: cython-0.29.17 +diff -U3 -r cython-0.29.17.orig/tests/run/cyfunction.pyx cython-0.29.17/tests/run/cyfunction.pyx +--- cython-0.29.17.orig/tests/run/cyfunction.pyx 2020-04-26 13:48:48.000000000 +0200 ++++ cython-0.29.17/tests/run/cyfunction.pyx 2020-05-15 17:44:55.160172251 +0200 +@@ -376,6 +376,18 @@ + def meth(self): pass + + ++class TestStaticmethod(object): ++ """ ++ >>> x = TestStaticmethod() ++ >>> x.staticmeth(42) ++ 42 ++ >>> x.staticmeth.__get__(42)() ++ 42 ++ """ ++ @staticmethod ++ def staticmeth(arg): return arg ++ ++ + cdef class TestOptimisedBuiltinMethod: + """ + >>> obj = TestOptimisedBuiltinMethod() +diff -U3 -r cython-0.29.17.orig/tests/run/fused_def.pyx cython-0.29.17/tests/run/fused_def.pyx +--- cython-0.29.17.orig/tests/run/fused_def.pyx 2020-04-26 13:48:48.000000000 +0200 ++++ cython-0.29.17/tests/run/fused_def.pyx 2020-05-15 18:03:39.436752174 +0200 +@@ -268,14 +268,6 @@ + def test_fused_def_super(): + """ + >>> test_fused_def_super() +- long 10 +- long 11 +- long 11 +- long 12 +- short 12 +- long 13 +- short 13 +- long 14 + long 14 + long 15 + long 15 +@@ -296,11 +288,6 @@ + obj = SubClass() + cls = SubClass + +- obj.mystaticmethod(obj, 10) +- cls.mystaticmethod(obj, 11) +- obj.mystaticmethod[cy.short](obj, 12) +- cls.mystaticmethod[cy.short](obj, 13) +- + obj.myclassmethod(14) + cls.myclassmethod(15) + obj.myclassmethod[cy.short](16)