You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by tr...@apache.org on 2018/01/04 04:06:36 UTC

svn commit: r1820032 - in /subversion/branches/swig-py3: build/ac-macros/swig.m4 subversion/bindings/swig/include/proxy.py

Author: troycurtisjr
Date: Thu Jan  4 04:06:36 2018
New Revision: 1820032

URL: http://svn.apache.org/viewvc?rev=1820032&view=rev
Log:
On branch swig-py3: Go back to using classic classes for Python 2 swig bindings.

Add some additional clarifying comments for the reasons behind overriding
__getattr__ and __getattribute__.

* build/ac-macros/swig.m4
  (SVN_FIND_SWIG): Add the '-classic' flag to swig when python 2 is detected.

* subversion/bindings/swig/include/proxy.py
   (_retrieve_swig_value): Factor out metadata retrieval from __getattribute__ to a new function.  
   (__getattribute__): Only define __getattribute__ for new style classes.
   (__getattr__): Add back implementation for classic classes.

Suggested By: brane

Modified:
    subversion/branches/swig-py3/build/ac-macros/swig.m4
    subversion/branches/swig-py3/subversion/bindings/swig/include/proxy.py

Modified: subversion/branches/swig-py3/build/ac-macros/swig.m4
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/build/ac-macros/swig.m4?rev=1820032&r1=1820031&r2=1820032&view=diff
==============================================================================
--- subversion/branches/swig-py3/build/ac-macros/swig.m4 (original)
+++ subversion/branches/swig-py3/build/ac-macros/swig.m4 Thu Jan  4 04:06:36 2018
@@ -155,7 +155,7 @@ AC_DEFUN(SVN_FIND_SWIG,
             if test "$ac_cv_python_is_py3" = "yes"; then
                SWIG_PY_OPTS="-python -py3"
             else
-               SWIG_PY_OPTS="-python"
+               SWIG_PY_OPTS="-python -classic"
             fi
 
             dnl Sun Forte adds an extra space before substituting APR_INT64_T_FMT

Modified: subversion/branches/swig-py3/subversion/bindings/swig/include/proxy.py
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/bindings/swig/include/proxy.py?rev=1820032&r1=1820031&r2=1820032&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/bindings/swig/include/proxy.py (original)
+++ subversion/branches/swig-py3/subversion/bindings/swig/include/proxy.py Thu Jan  4 04:06:36 2018
@@ -12,42 +12,70 @@
     if "_is_valid" in self.__dict__:
       assert self.__dict__["_is_valid"](), "Variable has already been deleted"
 
-  def __getattribute__(self, name):
-    """Manage access to all attributes of this object."""
-
-    # Start by mimicing __getattr__ behavior: immediately return __dict__ or
-    # items directly present in __dict__
-    mydict = object.__getattribute__(self, '__dict__')
-    if name == "__dict__":
-      return mydict
-
-    if name in mydict:
-      return mydict[name]
-
-    object.__getattribute__(self, 'assert_valid')()
-
-    try:
-      value = object.__getattribute__(self, name)
-    except AttributeError:
-      value = _swig_getattr(self,
-                            object.__getattribute__(self, '__class__'),
-                            name)
-
-    # If we got back a different object than we have, we need to copy all our
-    # metadata into it, so that it looks identical
-    try:
-      members = object.__getattribute__(self, '_members')
-      if name in members:
-          _copy_metadata_deep(value, members[name])
-          # Verify that the new object is good
-    except AttributeError:
-      pass
+  def _retrieve_swig_value(self, name, value):
+    # If we got back a different object than we have cached, we need to copy
+    # all our metadata into it, so that it looks identical to the one
+    # originally set.
+    members = self.__dict__.get('_members')
+    if members is not None and name in members:
+      _copy_metadata_deep(value, members[name])
 
     # Verify that the new object is good
     _assert_valid_deep(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
+  # match the originally assigned object.
+  #
+  # For classic classes it is enough to use __getattr__ to intercept swig
+  # derived attributes. However, with new style classes SWIG makes use of
+  # descriptors which mean that __getattr__ is never called. Therefore,
+  # __getattribute__ must be used for the interception.
+
+  if _newclass:
+    def __getattribute__(self, name):
+      """Manage access to all attributes of this object."""
+
+      # Start by mimicing __getattr__ behavior: immediately return __dict__ or
+      # items directly present in __dict__
+      mydict = object.__getattribute__(self, '__dict__')
+
+      if name == "__dict__":
+        return mydict
+
+      if name in mydict:
+        return mydict[name]
+
+      object.__getattribute__(self, 'assert_valid')()
+
+      try:
+        value = object.__getattribute__(self, name)
+      except AttributeError:
+        value = _swig_getattr(self,
+                              object.__getattribute__(self, '__class__'),
+                              name)
+
+      fn = object.__getattribute__(self, '_retrieve_swig_value')
+      return fn(name, value)
+  else:
+    def __getattr__(self, name):
+      """Get an attribute from this object"""
+      self.assert_valid()
+
+      value = _swig_getattr(self, self.__class__, name)
+
+      return self._retrieve_swig_value(name, value)
+
   def __setattr__(self, name, value):
     """Set an attribute on this object"""
     self.assert_valid()