From cf1624ebc4f4bbeb72956435ebe48c44192ad90d Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 16 Jan 2019 08:21:00 +0000 Subject: [PATCH] Python static method wrapper changes - Static method wrappers were using the 'fastproxy' approach by default. This is inconsistent with instance method wrappers. The fastproxy approach is now turned off by default to be consistent with instance methods. Static method wrappers can now also be controlled using the -fastproxy and -olddefs options. Example: struct Klass { static int statmethod(int a = 2); }; generates: class Klass(object): ... @staticmethod def statmethod(a=2): return _example.Klass_statmethod(a) instead of: class Klass(object): ... statmethod = staticmethod(_example.Klass_statmethod) - Modernise wrappers for static methods to use decorator syntax - @staticmethod. - Add missing runtime test for static class methods and using the actual class method. --- CHANGES.current | 35 ++++++++++++++++++++ Examples/test-suite/python/callback_runme.py | 3 ++ Source/Modules/python.cxx | 14 +++++--- 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index b9363f7d8..c81bdebde 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,41 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.0.0 (in progress) =========================== +2019-01-16: wsfulton + Python static method wrapper changes + + - Static method wrappers were using the 'fastproxy' approach by default. + This is inconsistent with instance method wrappers. The fastproxy approach + is now turned off by default to be consistent with instance methods. + Static method wrappers can now also be controlled using the -fastproxy and + -olddefs options. + + Example: + + struct Klass { + static int statmethod(int a = 2); + }; + + generates by default: + + class Klass(object): + ... + @staticmethod + def statmethod(a=2): + return _example.Klass_statmethod(a) + + instead of the following (which can be restored by using -fastproxy): + + class Klass(object): + ... + statmethod = staticmethod(_example.Klass_statmethod) + + +- Modernise wrappers for static methods to use decorator syntax - @staticmethod. + +- Add missing runtime test for static class methods and using the actual class method. + + 2019-01-12: ZackerySpytz [OCaml] #1403 #1194 Fix compilation problems for OCaml >= 4.03.0 due to OCaml using int64_t instead of int64. diff --git a/Examples/test-suite/python/callback_runme.py b/Examples/test-suite/python/callback_runme.py index ef7baad4e..91518fbf2 100644 --- a/Examples/test-suite/python/callback_runme.py +++ b/Examples/test-suite/python/callback_runme.py @@ -13,6 +13,9 @@ if foobar(3, _callback.foo) != foo(3): if foobar(3, foo) != foo(3): raise RuntimeError +if foobar(3, A.bar) != A.bar(3): + raise RuntimeError + if foobar(3, A_bar) != A_bar(3): raise RuntimeError diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 83858d44c..d3d157ddf 100755 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -4637,10 +4637,12 @@ public: } if (shadow) { - if (!Getattr(n, "feature:python:callback") && have_addtofunc(n)) { + bool fast = (fastproxy && !have_addtofunc(n)) || Getattr(n, "feature:callback"); + if (!fast || olddefs) { int kw = (check_kwargs(n) && !Getattr(n, "sym:overloaded")) ? 1 : 0; String *parms = make_pyParmList(n, false, false, kw); String *callParms = make_pyParmList(n, false, true, kw); + Printv(f_shadow, "\n", tab4, "@staticmethod", NIL); Printv(f_shadow, "\n", tab4, "def ", symname, "(", parms, ")", returnTypeAnnotation(n), ":\n", NIL); if (have_docstring(n)) Printv(f_shadow, tab8, docstring(n, AUTODOC_STATICFUNC, tab8), "\n", NIL); @@ -4649,12 +4651,14 @@ public: if (have_pythonappend(n)) { Printv(f_shadow, tab8, "val = ", funcCall(Swig_name_member(NSPACE_TODO, class_name, symname), callParms), "\n", NIL); Printv(f_shadow, indent_pythoncode(pythonappend(n), tab8, Getfile(n), Getline(n), "%pythonappend or %feature(\"pythonappend\")"), "\n", NIL); - Printv(f_shadow, tab8, "return val\n\n", NIL); + Printv(f_shadow, tab8, "return val\n", NIL); } else { - Printv(f_shadow, tab8, "return ", funcCall(Swig_name_member(NSPACE_TODO, class_name, symname), callParms), "\n\n", NIL); + Printv(f_shadow, tab8, "return ", funcCall(Swig_name_member(NSPACE_TODO, class_name, symname), callParms), "\n", NIL); } - Printv(f_shadow, tab4, symname, " = staticmethod(", symname, ")\n", NIL); - } else { + } + + // Below may result in a 2nd definition of the method when -olddefs is used. The Python interpreter will use the second definition as it overwrites the first. + if (fast) { Printv(f_shadow, tab4, symname, " = staticmethod(", module, ".", Swig_name_member(NSPACE_TODO, class_name, symname), ")\n", NIL); }