Hi,
I tried to support building SWIG 4 on Python 3.x, and post patch.
Since SWIG 4, -classic and -modern options have been dropped. As the result,
SWIG generates new-style classes which are using property() instead of
__swig_[gs]etmethods__.
In attached patch, SWIG would generate new-style classes without
__swig_[gs]etmethods__ when SWIG 3.x is used (-modern option would be used),
in the same as SWIG 4.x.
Verified by check-swig-py with:
- Python 3.[5678] with SWIG 1.3.40, 2.0.12, 3.0.12 on Ubuntu 16.04 amd64
- Python 2.7 with SWIG 3.0.12 and 4.0.1 on Ubuntu 16.04 amd64
[[[
Support building SWIG 4 on Python 3.x.
* build/ac-macros/swig.m4 (SVN_FIND_SWIG):
Allow building with SWIG 4+, and add -modern option when Python 3 and
SWIG 3.x are detected.
* subversion/bindings/swig/include/proxy.py
Use _get_instance_attr and _set_instance_attr.
* subversion/bindings/swig/include/proxy.swg
(_get_instance_attr): New function to get an instance attribute
without metadata for new-style and old-style classes.
(_set_instance_attr): New function to set an instance attribute for
new-style and old-style classes.
]]]
--
Jun Omae <[email protected]> (大前 潤)
diff --git a/build/ac-macros/swig.m4 b/build/ac-macros/swig.m4
index 6c1f97429de..bc2599038f2 100644
--- a/build/ac-macros/swig.m4
+++ b/build/ac-macros/swig.m4
@@ -158,14 +158,17 @@ AC_DEFUN(SVN_FIND_SWIG,
])
if test "$ac_cv_python_is_py3" = "yes"; then
- if test "$SWIG_VERSION" -ge "300010" -a "$SWIG_VERSION" -lt
"400000"; then
- SWIG_PY_OPTS="-python -py3"
+ if test "$SWIG_VERSION" -ge "300010"; then
dnl SWIG Python bindings successfully configured, clear the
error message dnl
SWIG_PY_ERRMSG=""
else
- SWIG_PY_OPTS="-python -py3 -nofastunpack"
SWIG_PY_ERRMSG="SWIG version is not suitable"
- AC_MSG_WARN([Subversion Python bindings for Python 3 require
3.0.10 <= SWIG < 4.0.0])
+ AC_MSG_WARN([Subversion Python bindings for Python 3 require
SWIG 3.0.10 or newer])
+ fi
+ if test "$SWIG_VERSION" -lt "400000"; then
+ SWIG_PY_OPTS="-python -py3 -nofastunpack -modern"
+ else
+ SWIG_PY_OPTS="-python -py3 -nofastunpack"
fi
else
if test "$SWIG_VERSION" -lt "400000"; then
diff --git a/subversion/bindings/swig/include/proxy.py
b/subversion/bindings/swig/include/proxy.py
index f97b7234a24..73ff5ffdad8 100644
--- a/subversion/bindings/swig/include/proxy.py
+++ b/subversion/bindings/swig/include/proxy.py
@@ -25,13 +25,6 @@ def _retrieve_swig_value(self, name, value):
return value
- # SWIG classes generated with -classic do not define this variable,
- # so set it to 0 when it doesn't exist
- try:
- _newclass
- except NameError:
- _newclass = 0
-
# Attribute access must be intercepted to ensure that objects coming from
# read attribute access match those that are set with write attribute access.
# Specifically the metadata, such as the associated apr_pool object, should
@@ -58,13 +51,7 @@ def __getattribute__(self, name):
object.__getattribute__(self, 'assert_valid')()
- try:
- value = object.__getattribute__(self, name)
- except AttributeError:
- value = _swig_getattr(self,
- object.__getattribute__(self, '__class__'),
- name)
-
+ value = _get_instance_attr(self, name)
fn = object.__getattribute__(self, '_retrieve_swig_value')
return fn(name, value)
else:
@@ -85,4 +72,4 @@ def __setattr__(self, name, value):
# SWIG-land
self.__dict__.setdefault("_members",{})[name] = value
- return _swig_setattr(self, self.__class__, name, value)
+ return _set_instance_attr(self, name, value)
diff --git a/subversion/bindings/swig/include/proxy.swg
b/subversion/bindings/swig/include/proxy.swg
index bc929131365..ac67d434ca8 100644
--- a/subversion/bindings/swig/include/proxy.swg
+++ b/subversion/bindings/swig/include/proxy.swg
@@ -64,7 +64,58 @@
pass
else:
fn()
+
%}
+#if defined(SWIGPYTHON_PY3)
+#if SWIG_VERSION >= 0x040000
+%pythoncode %{
+ # -classic and -modern options have been dropped and this variable
+ # is not generated since SWIG 4
+ _newclass = 1
+ _get_instance_attr = object.__getattribute__
+ _set_instance_attr =
_swig_setattr_nondynamic_instance_variable(object.__setattr__)
+
+%}
+#else
+%pythoncode %{
+ # SWIG classes generated with -modern do not define this variable
+ try:
+ _newclass
+ except NameError:
+ _newclass = 1
+ else:
+ raise RuntimeError("Require -modern option, but _newclass is defined")
+
+ _get_instance_attr = object.__getattribute__
+ _set_instance_attr = _swig_setattr_nondynamic_method(object.__setattr__)
+
+%}
+#endif
+#else
+%pythoncode %{
+ # SWIG classes generated with -classic do not define this variable,
+ # so set it to 0 when it doesn't exist
+ try:
+ _newclass
+ except NameError:
+ _newclass = 0
+
+ if _newclass:
+ def _get_instance_attr(self, name):
+ try:
+ return object.__getattribute__(self, name)
+ except AttributeError:
+ return _swig_getattr(self, object.__getattribute__(self, '__class__'),
+ name)
+ else:
+ def _get_instance_attr(self, name):
+ return _swig_getattr(self, self.__class__, name)
+
+ def _set_instance_attr(self, name, value):
+ return _swig_setattr(self, self.__class__, name, value)
+
+%}
+#endif
/* Default code for all wrapped proxy classes in Python.
* Inline the code from a separate file to avoid issues with