From f068f2c2d6d2d8f8a3c101f34fc290d3b822653e Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 21 Mar 2022 23:56:54 +0000 Subject: [PATCH] Add Python < 3.3 support for pyabc.i pyabc.i for abstract base classes now supports versions of Python prior to 3.3 by using the collection module for these older versions. Python-3.3 and later continue to use the collections.abc module. The -py3 option no longer has any effect on the %pythonabc feature. --- CHANGES.current | 6 ++++ Doc/Manual/Python.html | 19 ++++++++---- .../python/python_abstractbase_runme.py | 31 +++++++++++-------- Examples/test-suite/python_abstractbase.i | 6 ---- Lib/python/pyabc.i | 20 +++++++----- Source/Modules/python.cxx | 5 ++- 6 files changed, 51 insertions(+), 36 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 46e2e7133..1a5a5d0a6 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,12 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-03-21: wsfulton + [Python] #1779 pyabc.i for abstract base classes now supports versions of + Python prior to 3.3 by using the collection module for these older versions. + Python-3.3 and later continue to use the collections.abc module. + The -py3 option no longer has any effect on the %pythonabc feature. + 2022-03-21: jschueller, jim-easterbrook, wsfulton [Python] #2137 C++ static member functions no longer generate a "flattened" name in the Python module. For example: diff --git a/Doc/Manual/Python.html b/Doc/Manual/Python.html index 907daf353..2ed0211cc 100644 --- a/Doc/Manual/Python.html +++ b/Doc/Manual/Python.html @@ -7036,10 +7036,11 @@ modify the buffer.

-By including pyabc.i and using the -py3 command -line option when calling SWIG, the proxy classes of the STL containers +By including pyabc.i in your interface file, +the proxy classes of the STL containers will automatically gain an appropriate abstract base class from the -collections.abc module. For +collections.abc module for Python 3.3 and later, otherwise from the +collections module. For example, the following SWIG interface:

@@ -7056,8 +7057,10 @@ namespace std {

will generate a Python proxy class Mapii inheriting from -collections.abc.MutableMap and a proxy class IntList -inheriting from collections.abc.MutableSequence. +collections.abc.MutableMap for Python 3.3 and later, or collections.MutableMap +for earlier versions and a proxy class IntList +inheriting from collections.abc.MutableSequence for Python 3.3 or later, +or collections.MutableSequence for earlier versions.

@@ -7066,7 +7069,9 @@ used to define an abstract base class for your own C++ class:

-%pythonabc(MySet, collections.abc.MutableSet);
+%pythonabc(MySet, collections.abc.MutableSet); # Python 3.3 and later
+%pythonabc(MySet, collections.MutableSet);     # Prior to Python 3.3
+%pythonabc(MySet, "collections.abc.MutableSet if _swig_python_version_info >= (3, 3) else collections.MutableSet"); # All Python versions
 

@@ -7080,6 +7085,8 @@ For details of abstract base class, please see of the classes in the collections module in Python 3.7. The collections.abc module was introduced in Python 3.3 and hence this feature requires Python 3.3 or later. +SWIG-4.1.0 introduced the flexibility of using +either the collections.abc module for Python 3.3 and later or the collections module for earlier Python versions.

33.12.4 Byte string output conversion

diff --git a/Examples/test-suite/python/python_abstractbase_runme.py b/Examples/test-suite/python/python_abstractbase_runme.py index 9f99dcb54..0790c5ca7 100644 --- a/Examples/test-suite/python/python_abstractbase_runme.py +++ b/Examples/test-suite/python/python_abstractbase_runme.py @@ -1,31 +1,36 @@ import sys # collections.abc requires Python 3.3+ -if sys.version_info[0:2] < (3, 3): - exit(0) from python_abstractbase import * -import collections.abc +if sys.version_info[0:2] >= (3, 3): + import collections.abc +else: + import collections # This is expected to fail with -builtin option # Builtin types can't inherit from pure-python abstract bases if is_python_builtin(): exit(0) -# Python abc is only turned on when -py3 option is passed to SWIG -if not is_swig_py3: - exit(0) - def check_issubclass(derived, base): if not issubclass(derived, base): raise RuntimeError("{} is not a subclass of {}".format(derived, base)) -check_issubclass(Mapii, collections.abc.MutableMapping) -check_issubclass(Multimapii, collections.abc.MutableMapping) -check_issubclass(IntSet, collections.abc.MutableSet) -check_issubclass(IntMultiset, collections.abc.MutableSet) -check_issubclass(IntVector, collections.abc.MutableSequence) -check_issubclass(IntList, collections.abc.MutableSequence) +if sys.version_info[0:2] >= (3, 3): + check_issubclass(Mapii, collections.abc.MutableMapping) + check_issubclass(Multimapii, collections.abc.MutableMapping) + check_issubclass(IntSet, collections.abc.MutableSet) + check_issubclass(IntMultiset, collections.abc.MutableSet) + check_issubclass(IntVector, collections.abc.MutableSequence) + check_issubclass(IntList, collections.abc.MutableSequence) +else: + check_issubclass(Mapii, collections.MutableMapping) + check_issubclass(Multimapii, collections.MutableMapping) + check_issubclass(IntSet, collections.MutableSet) + check_issubclass(IntMultiset, collections.MutableSet) + check_issubclass(IntVector, collections.MutableSequence) + check_issubclass(IntList, collections.MutableSequence) mapii = Mapii() multimapii = Multimapii() diff --git a/Examples/test-suite/python_abstractbase.i b/Examples/test-suite/python_abstractbase.i index 2146e758e..65f3d9931 100644 --- a/Examples/test-suite/python_abstractbase.i +++ b/Examples/test-suite/python_abstractbase.i @@ -24,9 +24,3 @@ bool is_python_builtin() { return true; } bool is_python_builtin() { return false; } #endif %} - -#ifdef SWIGPYTHON_PY3 // set when using -py3 -#define is_swig_py3 1 -#else -#define is_swig_py3 0 -#endif diff --git a/Lib/python/pyabc.i b/Lib/python/pyabc.i index fbd91dce4..cae1e7032 100644 --- a/Lib/python/pyabc.i +++ b/Lib/python/pyabc.i @@ -1,10 +1,14 @@ %define %pythonabc(Type, Abc) - %feature("python:abc", #Abc) Type; + %feature("python:abc", Abc) Type; %enddef -%pythoncode %{import collections.abc%} -%pythonabc(std::vector, collections.abc.MutableSequence); -%pythonabc(std::list, collections.abc.MutableSequence); -%pythonabc(std::map, collections.abc.MutableMapping); -%pythonabc(std::multimap, collections.abc.MutableMapping); -%pythonabc(std::set, collections.abc.MutableSet); -%pythonabc(std::multiset, collections.abc.MutableSet); +%pythoncode %{if _swig_python_version_info[0:2] >= (3, 3): + import collections.abc +else: + import collections +%} +%pythonabc(std::vector, "collections.abc.MutableSequence if _swig_python_version_info >= (3, 3) else collections.MutableSequence"); +%pythonabc(std::list, "collections.abc.MutableSequence if _swig_python_version_info >= (3, 3) else collections.MutableSequence"); +%pythonabc(std::map, "collections.abc.MutableMapping if _swig_python_version_info >= (3, 3) else collections.MutableMapping"); +%pythonabc(std::multimap, "collections.abc.MutableMapping if _swig_python_version_info >= (3, 3) else collections.MutableMapping"); +%pythonabc(std::set, "collections.abc.MutableSet if _swig_python_version_info >= (3, 3) else collections.MutableSet"); +%pythonabc(std::multiset, "collections.abc.MutableSet if _swig_python_version_info >= (3, 3) else collections.MutableSet"); diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index b58c9961b..83c00929c 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -4480,10 +4480,9 @@ public: /* dealing with abstract base class */ String *abcs = Getattr(n, "feature:python:abc"); - if (py3 && abcs) { - if (Len(base_class)) { + if (abcs) { + if (Len(base_class) > 0) Printv(base_class, ", ", NIL); - } Printv(base_class, abcs, NIL); }