#18 Partially work around issues with class and static methods
Closed 4 years ago by churchyard. Opened 4 years ago by pviktori.

file modified
+18 -1
@@ -6,13 +6,26 @@ 

  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

+ 

+ # Small templating library bundled in Cython/Tempita

+ # Upstream: https://pypi.org/project/Tempita

+ Provides:       bundled(python3dist(tempita))

+ 

  BuildRequires:  gcc

  %if %{with tests}

  BuildRequires:  gcc-c++
@@ -103,6 +116,10 @@ 

  %{_emacs_sitestartdir}/cython*.el*

  

  %changelog

+ * Wed May 13 2020 Petr Viktorin <pviktori@redhat.com> - 0.29.17-2

+ - Backport classmethod fixes

+   Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1788506

+ 

  * Tue Apr 28 2020 Marcel Plch <mplch@redhat.com> - 0.29.17-1

  - Update to 0.29.17

  

@@ -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

+      <class 'fused_def.SubClass'> long 14

+      <class 'fused_def.SubClass'> long 15

+      <class 'fused_def.SubClass'> 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)

I am still working on the problem, but this patch should help with BZ#1788506.
Tests still fail, though.

The PR contains #17; I can separate it if needed.

Please rebase this and open it from your fork.

Pull-Request has been closed by churchyard

4 years ago