Good morning Troy,

troycurti...@apache.org wrote on Fri, Dec 22, 2017 at 03:52:59 -0000:
> On branch swig-py3: Correctly manage swig objects with Python new style 
> classes.
> 
> * build/ac-macros/swig.m4
>   (SVN_FIND_SWIG):
>   Request that swig generate new style classes, even for Python 2, to reduce
>   differences with Python 3.
> 
> 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=1818995&r1=1818994&r2=1818995&view=diff
> ==============================================================================
> --- subversion/branches/swig-py3/build/ac-macros/swig.m4 (original)
> +++ subversion/branches/swig-py3/build/ac-macros/swig.m4 Fri Dec 22 03:52:59 
> 2017
> @@ -143,7 +143,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 -classic"
> +           SWIG_PY_OPTS="-python"
>          fi

What are the compatibility implications of this change?  I couldn't find any
documentation for the "-classic" option.

> * subversion/bindings/swig/include/proxy.py
>   (__getattr__): Replace __getattr__ with __getattribute__ to correctly
>   intercept attribute access, even when swig uses descriptors for new style
>   classes (which are the only type available in Python 3).

Could you help me understand what's going on here and why it's correct?  I've
read the documentation of object.__getattr__ and object.__getattribute__¹ but I
don't follow how the fact that the class into which this code is included
became a new-style class (rather than a classic class) brought on the need to
migrate from __getattr__ to __getattribute__, nor why the order of precedence
of lookup (first __dict__, then object.__getattribute__, then _swig_getattr) is
correct.

I'm asking because I'm trying to review the branch (to +1 its merge) and this
is one of the open questions I have.

¹ https://docs.python.org/3/reference/datamodel.html#object.__getattr__ et seq.

> 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=1818995&r1=1818994&r2=1818995&view=diff
> ==============================================================================
> --- subversion/branches/swig-py3/subversion/bindings/swig/include/proxy.py 
> (original)
> +++ subversion/branches/swig-py3/subversion/bindings/swig/include/proxy.py 
> Fri Dec 22 03:52:59 2017
> @@ -12,17 +12,36 @@
>      if "_is_valid" in self.__dict__:
>        assert self.__dict__["_is_valid"](), "Variable has already been 
> deleted"
>  
> -  def __getattr__(self, name):
> -    """Get an attribute from this object"""
> -    self.assert_valid()
> +  def __getattribute__(self, name):
> +    """Manage access to all attributes of this object."""
>  
> -    value = _swig_getattr(self, self.__class__, name)
> +    # 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
> -    members = self.__dict__.get("_members")
> -    if members is not None:
> -      _copy_metadata_deep(value, members.get(name))
> +    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
>  
>      # Verify that the new object is good
>      _assert_valid_deep(value)

Cheers,

Daniel

Reply via email to