From 2e1595a4d07eaa3434f7e1a451bcf01cfad6f0e1 Mon Sep 17 00:00:00 2001 From: Alec Cooper Date: Sun, 24 Jan 2016 19:18:00 -0500 Subject: [PATCH 1/8] When possible, use PyInt rather than PyLong This is especially important for the unsigned long typemap, which is used by the size_t typemap, which is in turn used for lengths of std containers etc. In Python2, len requires old-style classes' __len__ method return a PyIntObject rather than a PyLongObject, so this supports that requirement. --- Lib/python/pyprimtypes.swg | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/python/pyprimtypes.swg b/Lib/python/pyprimtypes.swg index 2ef09a1ba..fb5bbf6df 100644 --- a/Lib/python/pyprimtypes.swg +++ b/Lib/python/pyprimtypes.swg @@ -67,7 +67,7 @@ SWIGINTERNINLINE PyObject* /* long */ %fragment(SWIG_From_frag(long),"header") { - %define_as(SWIG_From_dec(long), PyLong_FromLong) + %define_as(SWIG_From_dec(long), PyInt_FromLong) } %fragment(SWIG_AsVal_frag(long),"header", @@ -123,7 +123,7 @@ SWIGINTERNINLINE PyObject* SWIG_From_dec(unsigned long)(unsigned long value) { return (value > LONG_MAX) ? - PyLong_FromUnsignedLong(value) : PyLong_FromLong(%numeric_cast(value,long)); + PyLong_FromUnsignedLong(value) : PyInt_FromLong(%numeric_cast(value,long)); } } @@ -186,7 +186,7 @@ SWIGINTERNINLINE PyObject* SWIG_From_dec(long long)(long long value) { return ((value < LONG_MIN) || (value > LONG_MAX)) ? - PyLong_FromLongLong(value) : PyLong_FromLong(%numeric_cast(value,long)); + PyLong_FromLongLong(value) : PyInt_FromLong(%numeric_cast(value,long)); } %#endif } @@ -244,7 +244,7 @@ SWIGINTERNINLINE PyObject* SWIG_From_dec(unsigned long long)(unsigned long long value) { return (value > LONG_MAX) ? - PyLong_FromUnsignedLongLong(value) : PyLong_FromLong(%numeric_cast(value,long)); + PyLong_FromUnsignedLongLong(value) : PyInt_FromLong(%numeric_cast(value,long)); } %#endif } From d91064aa6af3fcb21d338617dcd56e18b7675337 Mon Sep 17 00:00:00 2001 From: Alec Cooper Date: Mon, 25 Jan 2016 11:43:35 -0500 Subject: [PATCH 2/8] Add support for static methods in classic mode --- Source/Modules/python.cxx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 43c296306..7526a80fa 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -4745,6 +4745,11 @@ public: Printv(f_shadow, tab4, symname, " = staticmethod(", module, ".", Swig_name_member(NSPACE_TODO, class_name, symname), ")\n", NIL); } + if (classic || !modern) { + if (!classic) + Printv(f_shadow, tab4, "else:\n", tab4, NIL); + Printv(f_shadow, tab4, symname, " = ", module, ".", Swig_name_member(NSPACE_TODO, class_name, symname), "\n", NIL); + } } } return SWIG_OK; From b45164e098aa8836601364b9a4c9c6e44b21b2de Mon Sep 17 00:00:00 2001 From: Alec Cooper Date: Mon, 25 Jan 2016 12:28:36 -0500 Subject: [PATCH 3/8] Support python(pre|ap)pend on static methods in classic mode Adding a test that covers this case to the python_append test-suite Note: staticmethod function has been available since Python 2.2 --- Examples/test-suite/python/python_append_runme.py | 7 +++++++ Examples/test-suite/python_append.i | 3 +++ Source/Modules/python.cxx | 4 +--- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Examples/test-suite/python/python_append_runme.py b/Examples/test-suite/python/python_append_runme.py index 2f6d94d9c..6675f3509 100644 --- a/Examples/test-suite/python/python_append_runme.py +++ b/Examples/test-suite/python/python_append_runme.py @@ -20,3 +20,10 @@ if grabpath() != os.path.dirname(mypath): if grabstaticpath() != os.path.basename(mypath): raise RuntimeError("grabstaticpath failed") + +clearstaticpath() +if grabstaticpath() != None: + raise RuntimeError("Resetting staticfuncpath failed") +Test.static_func() +if grabstaticpath() != os.path.basename(mypath): + raise RuntimeError("grabstaticpath failed") diff --git a/Examples/test-suite/python_append.i b/Examples/test-suite/python_append.i index f37a6c199..2a71b5784 100644 --- a/Examples/test-suite/python_append.i +++ b/Examples/test-suite/python_append.i @@ -12,6 +12,9 @@ def grabpath(): return funcpath def grabstaticpath(): return staticfuncpath +def clearstaticpath(): + global staticfuncpath + staticfuncpath = None %} %pythonappend Test::func %{ diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 7526a80fa..1c8169a36 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -4710,7 +4710,7 @@ public: } if (shadow) { - if (!classic && !Getattr(n, "feature:python:callback") && have_addtofunc(n)) { + if (!Getattr(n, "feature:python:callback") && have_addtofunc(n)) { 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); @@ -4726,8 +4726,6 @@ public: } else { Printv(f_shadow, tab8, "return ", funcCall(Swig_name_member(NSPACE_TODO, class_name, symname), callParms), "\n\n", NIL); } - if (!modern) - Printv(f_shadow, tab4, "if _newclass:\n", tab4, NIL); Printv(f_shadow, tab4, symname, " = staticmethod(", symname, ")\n", NIL); if (!modern) { From 866429d0f7df5068f78951e3280fddbfaa7f462a Mon Sep 17 00:00:00 2001 From: Alec Cooper Date: Mon, 25 Jan 2016 11:45:07 -0500 Subject: [PATCH 4/8] Removing __swig_getmethods__ for static methods Static methods will always be found by normal attribute lookup, so there's no need to check for them during __getattr__ (aka _swig_getattr_nondynamic) --- Source/Modules/python.cxx | 9 --------- 1 file changed, 9 deletions(-) diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 1c8169a36..56f4c321e 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -4727,16 +4727,7 @@ public: Printv(f_shadow, tab8, "return ", funcCall(Swig_name_member(NSPACE_TODO, class_name, symname), callParms), "\n\n", NIL); } Printv(f_shadow, tab4, symname, " = staticmethod(", symname, ")\n", NIL); - - if (!modern) { - Printv(f_shadow, tab4, "__swig_getmethods__[\"", symname, "\"] = lambda x: ", symname, "\n", NIL); - } - } else { - if (!modern) { - Printv(f_shadow, tab4, "__swig_getmethods__[\"", symname, "\"] = lambda x: ", module, ".", Swig_name_member(NSPACE_TODO, class_name, symname), "\n", - NIL); - } if (!classic) { if (!modern) Printv(f_shadow, tab4, "if _newclass:\n", tab4, NIL); From 475d03f19560dfc1602afdf863478e807cd0f7c1 Mon Sep 17 00:00:00 2001 From: Alec Cooper Date: Mon, 25 Jan 2016 12:03:13 -0500 Subject: [PATCH 5/8] Clean up setting _object Don't bother setting _object in modern mode since it isn't used Catch __builtin__.Exception rather than AttributeError since the check for object hasn't been through something that would raise an AttributeError since 3d8ddfc4 in 2008 --- Source/Modules/python.cxx | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 56f4c321e..e0102a1a8 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -912,17 +912,12 @@ public: tab4, "try:\n", tab8, "strthis = \"proxy of \" + self.this.__repr__()\n", tab4, "except __builtin__.Exception:\n", tab8, "strthis = \"\"\n", tab4, "return \"<%s.%s; %s >\" % (self.__class__.__module__, self.__class__.__name__, strthis,)\n\n", NIL); - if (!classic) { - /* Usage of types.ObjectType is deprecated. - * But don't sure wether this would broken old Python? - */ + if (!classic && !modern) { Printv(f_shadow, -// "import types\n", "try:\n", -// " _object = types.ObjectType\n", - tab4, "_object = object\n", tab4, "_newclass = 1\n", "except AttributeError:\n", tab4, "class _object:\n", tab8, "pass\n", tab4, "_newclass = 0\n", -// "del types\n", - "\n\n", NIL); + tab4, "_object = object\n", tab4, "_newclass = 1\n", + "except __builtin__.Exception:\n", + tab4, "class _object:\n", tab8, "pass\n", tab4, "_newclass = 0\n\n", NIL); } } if (modern) { From 506a5bc8e65141d62a32b03599cc8b64ac5d1d79 Mon Sep 17 00:00:00 2001 From: Alec Cooper Date: Sun, 24 Jan 2016 21:24:19 -0500 Subject: [PATCH 6/8] Don't claim to new-style support in classic mode --- Source/Modules/python.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index e0102a1a8..3eb1f67c3 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -1002,7 +1002,7 @@ public: if (shadow) { Swig_banner_target_lang(f_shadow_py, "#"); - if (!modern) { + if (!modern && !classic) { Printv(f_shadow, "# This file is compatible with both classic and new-style classes.\n", NIL); } Printv(f_shadow_py, "\n", f_shadow_begin, "\n", NIL); From acbe04b5482c2048f7ed96a87d2baeaee7144bbc Mon Sep 17 00:00:00 2001 From: Alec Cooper Date: Sun, 24 Jan 2016 21:20:00 -0500 Subject: [PATCH 7/8] Support checking names of old-style classic classes --- .../python/import_packages/same_modnames1/runme.py | 10 ++++++++-- .../python/import_packages/same_modnames2/runme.py | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/Examples/python/import_packages/same_modnames1/runme.py b/Examples/python/import_packages/same_modnames1/runme.py index 2107597b3..3c3c00c1a 100644 --- a/Examples/python/import_packages/same_modnames1/runme.py +++ b/Examples/python/import_packages/same_modnames1/runme.py @@ -8,6 +8,12 @@ import pkg2.foo print " Finished importing pkg2.foo" var2 = pkg2.foo.Pkg2_Foo() -if str(type(var2)).find("'pkg2.foo.Pkg2_Foo'") == -1: - raise RuntimeError("failed type checking: " + str(type(var2))) + +classname = str(type(var2)) +# Check for an old-style class if swig was run in -classic mode +if classname == "": + classname = str(var2.__class__) + +if classname.find("pkg2.foo.Pkg2_Foo") == -1: + raise RuntimeError("failed type checking: " + classname) print " Successfully created object pkg2.foo.Pkg2_Foo" diff --git a/Examples/python/import_packages/same_modnames2/runme.py b/Examples/python/import_packages/same_modnames2/runme.py index 41ff1afec..38daad0a3 100644 --- a/Examples/python/import_packages/same_modnames2/runme.py +++ b/Examples/python/import_packages/same_modnames2/runme.py @@ -7,6 +7,12 @@ import pkg1.pkg2.foo print " Finished importing pkg1.pkg2.foo" var2 = pkg1.pkg2.foo.Pkg2_Foo() -if str(type(var2)).find("'pkg1.pkg2.foo.Pkg2_Foo'") == -1: - raise RuntimeError("failed type checking: " + str(type(var2))) + +classname = str(type(var2)) +# Check for an old-style class if swig was run in -classic mode +if classname == "": + classname = str(var2.__class__) + +if classname.find("pkg1.pkg2.foo.Pkg2_Foo") == -1: + raise RuntimeError("failed type checking: " + classname) print " Successfully created object pkg1.pkg2.foo.Pkg2_Foo" From e67b9d00a4783145002cab05ef845adf8d8b67e0 Mon Sep 17 00:00:00 2001 From: Alec Cooper Date: Mon, 25 Jan 2016 12:47:03 -0500 Subject: [PATCH 8/8] Updating changelog and marking -classic as passing CI --- .travis.yml | 4 ---- CHANGES.current | 12 ++++++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0951df707..5a0ea5a2b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -158,10 +158,6 @@ matrix: os: linux env: SWIGLANG=ocaml # Not quite working yet - - compiler: gcc - os: linux - env: SWIGLANG=python SWIG_FEATURES=-classic - # Not quite working yet - compiler: gcc os: linux env: SWIGLANG=python SWIG_FEATURES=-O diff --git a/CHANGES.current b/CHANGES.current index 2a0017822..34ed0c8e5 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -8,6 +8,18 @@ Version 3.0.9 (in progress) 2016-01-27: steeve [Go] Ensure structs are properly packed between gc and GCC/clang. +2016-01-25: ahnolds + [Python] Support the full Python test suite in -classic mode + * Convert long/unsigned long/long long/unsigned long long to PyInt + rather than PyLong when possible. Certain python functions like + len() require a PyInt when operating on old-style classes. + * Add support for static methods in classic mode, including support + for pythonappend, pythonprepend, and docstrings. + * Removing the use of __swig_getmethods__ for static member methods + since they will always be found by the standard argument lookup + * Fix a bug where the wrong type of exception was caught when + checking for new-style class support + 2016-01-23: ahnolds [Go] Enable support for the Go test-suite on OSX: * The linker on OSX requires that all symbols (even weak symbols)