<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1256">
<meta name="Generator" content="Microsoft Exchange Server">
<!-- converted from text --><style><!-- .EmailQuote { margin-left: 1pt; padding-left: 4pt; border-left: #800000 2px solid; } --></style>
</head>
<body>
<div>
<div>
<div style="font-size:11pt; font-family:Calibri,sans-serif">Could the same result be achieved by hooking the MRO that super uses and returning a list of proxy objects? And then wouldn't you only really need a __getattribute__ that doesn't recurse (__getlocalattribute__)?
 The end result may be conceptually simpler, but you've thought through the edge cases better than I have.
<br>
<br>
(Apologies for the HTML top-post)<br>
<br>
Sent from my Windows Phone</div>
</div>
<div dir="ltr">
<hr>
<span style="font-size:11pt; font-family:Calibri,sans-serif; font-weight:bold">From:
</span><span style="font-size:11pt; font-family:Calibri,sans-serif"><a href="mailto:ronaldoussoren@mac.com">Ronald Oussoren</a></span><br>
<span style="font-size:11pt; font-family:Calibri,sans-serif; font-weight:bold">Sent:
</span><span style="font-size:11pt; font-family:Calibri,sans-serif">ý7/ý6/ý2013 0:47</span><br>
<span style="font-size:11pt; font-family:Calibri,sans-serif; font-weight:bold">To:
</span><span style="font-size:11pt; font-family:Calibri,sans-serif"><a href="mailto:ronaldoussoren@mac.com">Ronald Oussoren</a></span><br>
<span style="font-size:11pt; font-family:Calibri,sans-serif; font-weight:bold">Cc:
</span><span style="font-size:11pt; font-family:Calibri,sans-serif"><a href="mailto:python-dev@python.org">python-dev@python.org Dev</a></span><br>
<span style="font-size:11pt; font-family:Calibri,sans-serif; font-weight:bold">Subject:
</span><span style="font-size:11pt; font-family:Calibri,sans-serif">Re: [Python-Dev] Hooking into super() attribute resolution</span><br>
<br>
</div>
</div>
<font size="2"><span style="font-size:10pt;">
<div class="PlainText">I've updated the implementation in issue 18181 <<a href="http://bugs.python.org/issue18181">http://bugs.python.org/issue18181</a>> while adding some tests, and have updated the proposal as well.
<br>
<br>
The proposal has some open issues at the moment, most important of which is the actual signature for the new special method; in particular I haven't been able to decide if this should be an instance-, class- or static method. It is a static method in the proposal
 and prototype, but I'm not convinced that that is the right solution.<br>
<br>
Ronald<br>
<br>
<br>
<br>
<br>
PEP: TODO<br>
Title: Hooking into super attribute resolution<br>
Version: $Revision$<br>
Last-Modified: $Date$<br>
Author: Ronald Oussoren <ronaldoussoren@mac.com><br>
Status: Draft<br>
Type: Standards Track<br>
Content-Type: text/x-rst<br>
Created: 12-Jun-2013<br>
Post-History: 2-Jul-2013, ?<br>
<br>
<br>
Abstract<br>
========<br>
<br>
In current python releases the attribute resolution of the `super class`_<br>
peeks in the ``__dict__`` attribute of classes on the MRO to look<br>
for attributes. This PEP introduces a hook that classes can use<br>
to override that behavior for specific classes.<br>
<br>
<br>
Rationale<br>
=========<br>
<br>
Peeking in the class ``__dict__`` works for regular classes, but can<br>
cause problems when a class dynamicly looks up attributes in a<br>
``__getattribute__`` method.<br>
<br>
The new hook makes it possible to introduce the same customization for<br>
attribute lookup through the `super class`_.<br>
<br>
<br>
The superclass attribute lookup hook<br>
====================================<br>
<br>
In C code<br>
---------<br>
<br>
A new slot ``tp_getattro_super`` is added to the ``PyTypeObject`` struct. The<br>
``tp_getattro`` slot for super will call this slot when it is not ``NULL``,<br>
and will raise an exception when it is not set (which shouldn't happen because<br>
the method is implemented for :class:`object`).<br>
<br>
The slot has the following prototype::<br>
<br>
    PyObject* (*getattrosuperfunc)(PyTypeObject* cls, PyObject* name,<br>
        PyObject* object, PyObject* owner);<br>
<br>
The function should perform attribute lookup on *object* for *name*, but only<br>
looking in type *tp* (which will be one of the types on the MRO for *self*)<br>
and without looking in the instance *__dict__*.<br>
<br>
The function returns ``NULL`` when the attribute cannot be found, and raises and<br>
exception. Exception other than ``AttributeError`` will cause failure of super's<br>
attribute resolution.<br>
<br>
The implementation of the slot for the :class:`object` type is<br>
``PyObject_GenericGetAttrSuper``, which peeks in the ``tp_dict`` for *cls*.<br>
<br>
Note that *owner* and *object* will be the same object when using a<br>
class-mode super.<br>
<br>
<br>
In Python code<br>
--------------<br>
<br>
A Python class can contain a definition for a static method<br>
``__getattribute_super__`` with the following prototype::<br>
<br>
   def __getattribute_super__(cls, name, object, owner): pass<br>
<br>
The method should perform attribute lookup for *name* on instance *self* while<br>
only looking at *cls* (it should not look in super classes or the instance<br>
*__dict__*<br>
<br>
XXX: I haven't got a clue at the moment if the method should be an<br>
instance-, class- or staticmethod. The prototype uses a staticmethod.<br>
<br>
XXX: My prototype automagicly makes this a static method, just like __new__ is<br>
made into a static method. That's more convenient, but also (too?) magical.<br>
<br>
XXX: Should this raise AttributeError or return a magic value to signal that<br>
an attribute cannot be found (such as NotImplemented, used in the comparison<br>
operators)? I'm currently using an exception, a magical return value would<br>
be slightly more efficient because the exception machinery is not invoked.<br>
<br>
<br>
Alternative proposals<br>
---------------------<br>
<br>
Reuse ``tp_getattro``<br>
.....................<br>
<br>
It would be nice to avoid adding a new slot, thus keeping the API simpler and<br>
easier to understand.  A comment on `Issue 18181`_ asked about reusing the<br>
``tp_getattro`` slot, that is super could call the ``tp_getattro`` slot of all<br>
methods along the MRO.<br>
<br>
AFAIK that won't work because ``tp_getattro`` will look in the instance<br>
``__dict__`` before it tries to resolve attributes using classes in the MRO.<br>
This would mean that using ``tp_getattro`` instead of peeking the class<br>
dictionaries changes the semantics of the `super class`_.<br>
<br>
<br>
Open Issues<br>
===========<br>
<br>
* The names of the new slot and magic method are far from settled.<br>
<br>
* I'm not too happy with the prototype for the new hook.<br>
<br>
* Should ``__getattribute_super__`` be a class method instead?<br>
<br>
  -> Yes? The method looks up a named attribute name of an object in<br>
     a specific class. Is also likely needed to deal with @classmethod<br>
     and super(Class, Class)<br>
<br>
* Should ``__getattribute_super__`` be defined on object?<br>
<br>
  -> Yes: makes it easier to delegate to the default implementation<br>
<br>
* This doesn't necessarily work for class method super class<br>
   (e.g. super(object, object))...<br>
<br>
<br>
References<br>
==========<br>
<br>
* `Issue 18181`_ contains a prototype implementation<br>
<br>
<br>
Copyright<br>
=========<br>
<br>
This document has been placed in the public domain.<br>
<br>
.. _`Issue 18181`: <a href="http://bugs.python.org/issue18181">http://bugs.python.org/issue18181</a><br>
<br>
.. _`super class`: <a href="http://docs.python.org/3/library/functions.html?highlight=super#super">
http://docs.python.org/3/library/functions.html?highlight=super#super</a><br>
<br>
_______________________________________________<br>
Python-Dev mailing list<br>
Python-Dev@python.org<br>
<a href="http://mail.python.org/mailman/listinfo/python-dev">http://mail.python.org/mailman/listinfo/python-dev</a><br>
Unsubscribe: <a href="http://mail.python.org/mailman/options/python-dev/steve.dower%40microsoft.com">
http://mail.python.org/mailman/options/python-dev/steve.dower%40microsoft.com</a><br>
<br>
<br>
</div>
</span></font>
</body>
</html>