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.
This commit is contained in:
William S Fulton 2022-03-21 23:56:54 +00:00
commit f068f2c2d6
6 changed files with 51 additions and 36 deletions

View file

@ -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) 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 2022-03-21: jschueller, jim-easterbrook, wsfulton
[Python] #2137 C++ static member functions no longer generate a "flattened" [Python] #2137 C++ static member functions no longer generate a "flattened"
name in the Python module. For example: name in the Python module. For example:

View file

@ -7036,10 +7036,11 @@ modify the buffer.
<p> <p>
By including <tt>pyabc.i</tt> and using the <tt>-py3</tt> command By including <tt>pyabc.i</tt> in your interface file,
line option when calling SWIG, the proxy classes of the STL containers the proxy classes of the STL containers
will automatically gain an appropriate abstract base class from the will automatically gain an appropriate abstract base class from the
<tt>collections.abc</tt> module. For <tt>collections.abc</tt> module for Python 3.3 and later, otherwise from the
<tt>collections</tt> module. For
example, the following SWIG interface: example, the following SWIG interface:
</p> </p>
@ -7056,8 +7057,10 @@ namespace std {
<p> <p>
will generate a Python proxy class <tt>Mapii</tt> inheriting from will generate a Python proxy class <tt>Mapii</tt> inheriting from
<tt>collections.abc.MutableMap</tt> and a proxy class <tt>IntList</tt> <tt>collections.abc.MutableMap</tt> for Python 3.3 and later, or <tt>collections.MutableMap</tt>
inheriting from <tt>collections.abc.MutableSequence</tt>. for earlier versions and a proxy class <tt>IntList</tt>
inheriting from <tt>collections.abc.MutableSequence</tt> for Python 3.3 or later,
or <tt>collections.MutableSequence</tt> for earlier versions.
</p> </p>
<p> <p>
@ -7066,7 +7069,9 @@ used to define an abstract base class for your own C++ class:
</p> </p>
<div class="code"><pre> <div class="code"><pre>
%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 &gt;= (3, 3) else collections.MutableSet"); # All Python versions
</pre></div> </pre></div>
<p> <p>
@ -7080,6 +7085,8 @@ For details of abstract base class, please see
of the classes in the <tt>collections</tt> module in Python 3.7. of the classes in the <tt>collections</tt> module in Python 3.7.
The <tt>collections.abc</tt> module was introduced in Python 3.3 and hence this feature The <tt>collections.abc</tt> module was introduced in Python 3.3 and hence this feature
requires Python 3.3 or later. requires Python 3.3 or later.
SWIG-4.1.0 introduced the flexibility of using
either the <tt>collections.abc</tt> module for Python 3.3 and later or the <tt>collections</tt> module for earlier Python versions.
</p> </p>
<H3><a name="Python_nn77">33.12.4 Byte string output conversion</a></H3> <H3><a name="Python_nn77">33.12.4 Byte string output conversion</a></H3>

View file

@ -1,31 +1,36 @@
import sys import sys
# collections.abc requires Python 3.3+ # collections.abc requires Python 3.3+
if sys.version_info[0:2] < (3, 3):
exit(0)
from python_abstractbase import * from python_abstractbase import *
if sys.version_info[0:2] >= (3, 3):
import collections.abc import collections.abc
else:
import collections
# This is expected to fail with -builtin option # This is expected to fail with -builtin option
# Builtin types can't inherit from pure-python abstract bases # Builtin types can't inherit from pure-python abstract bases
if is_python_builtin(): if is_python_builtin():
exit(0) 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): def check_issubclass(derived, base):
if not issubclass(derived, base): if not issubclass(derived, base):
raise RuntimeError("{} is not a subclass of {}".format(derived, base)) raise RuntimeError("{} is not a subclass of {}".format(derived, base))
if sys.version_info[0:2] >= (3, 3):
check_issubclass(Mapii, collections.abc.MutableMapping) check_issubclass(Mapii, collections.abc.MutableMapping)
check_issubclass(Multimapii, collections.abc.MutableMapping) check_issubclass(Multimapii, collections.abc.MutableMapping)
check_issubclass(IntSet, collections.abc.MutableSet) check_issubclass(IntSet, collections.abc.MutableSet)
check_issubclass(IntMultiset, collections.abc.MutableSet) check_issubclass(IntMultiset, collections.abc.MutableSet)
check_issubclass(IntVector, collections.abc.MutableSequence) check_issubclass(IntVector, collections.abc.MutableSequence)
check_issubclass(IntList, 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() mapii = Mapii()
multimapii = Multimapii() multimapii = Multimapii()

View file

@ -24,9 +24,3 @@ bool is_python_builtin() { return true; }
bool is_python_builtin() { return false; } bool is_python_builtin() { return false; }
#endif #endif
%} %}
#ifdef SWIGPYTHON_PY3 // set when using -py3
#define is_swig_py3 1
#else
#define is_swig_py3 0
#endif

View file

@ -1,10 +1,14 @@
%define %pythonabc(Type, Abc) %define %pythonabc(Type, Abc)
%feature("python:abc", #Abc) Type; %feature("python:abc", Abc) Type;
%enddef %enddef
%pythoncode %{import collections.abc%} %pythoncode %{if _swig_python_version_info[0:2] >= (3, 3):
%pythonabc(std::vector, collections.abc.MutableSequence); import collections.abc
%pythonabc(std::list, collections.abc.MutableSequence); else:
%pythonabc(std::map, collections.abc.MutableMapping); import collections
%pythonabc(std::multimap, collections.abc.MutableMapping); %}
%pythonabc(std::set, collections.abc.MutableSet); %pythonabc(std::vector, "collections.abc.MutableSequence if _swig_python_version_info >= (3, 3) else collections.MutableSequence");
%pythonabc(std::multiset, collections.abc.MutableSet); %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");

View file

@ -4480,10 +4480,9 @@ public:
/* dealing with abstract base class */ /* dealing with abstract base class */
String *abcs = Getattr(n, "feature:python:abc"); String *abcs = Getattr(n, "feature:python:abc");
if (py3 && abcs) { if (abcs) {
if (Len(base_class)) { if (Len(base_class) > 0)
Printv(base_class, ", ", NIL); Printv(base_class, ", ", NIL);
}
Printv(base_class, abcs, NIL); Printv(base_class, abcs, NIL);
} }