I'll wait for others to jump on this bandwagon... IMO the tempfile
object would be better off not to bother with caching at all...

On Thu, Apr 3, 2008 at 5:33 AM, Nick Coghlan <[EMAIL PROTECTED]> wrote:
> Guido van Rossum wrote:
>
> > On Wed, Apr 2, 2008 at 6:30 AM, Nick Coghlan <[EMAIL PROTECTED]> wrote:
> >
> > > One of the issues with porting to Py3k is the problem that __getattr__
> > >  and __getattribute__ can't reliably provide special methods like
> __add__
> > >  the way __getattr__ could with classic classes. (As first noted by
> Terry
> > >  Reedy years ago, and recently seeing some new activity on the bug
> > >  tracker [1])
> > >
> > >  The culprit here is the fact that __getattribute__ and its associated
> > >  machinery is typically never invoked for the methods with dedicated
> tp_*
> > >  slots in the C-level type structure.
> > >
> >
> > Well, yes, this is all an intentional part of the new-style class design.
> >
>
>  Not complaining, just trying to provide some background for those that may
> not be quite as familiar with the inner workings of typeobject.c :)
>
>
>
> >
> > >  What do people think of the idea of providing an extra method on type
> > >  objects that goes through all of the C-level special method slots, and
> > >  for each one that isn't currently set, does a getattr() on the
> > >  associated special name and stores the result (if any) on the current
> > >  type object?
> > >
> >
> > Does a getattr on what? Since you seem to be thinking specifically of
> > proxies here, I'm thinking you're doing a getattr on an *instance* --
> > but it seems wrong to base the *type* slots on that.
> >
>
>  D'oh, you're right - the specific proxying example I am thinking of (see
> below) does indeed grab bound methods directly from the underlying instance.
> However, I think the idea is salvageable (whether or not it is *worth*
> salvaging is of course a completely different question!).
>
>
>
> >
> > >  When converting a proxy class that relies on __getattr__ from classic
> > >
> >
> > Can you show specific code for such a proxy class? I'm having a hard
> > time imagining how it would work (not having used proxies in a really
> > long time...).
> >
>
>  From tempfile._TemporaryFileWrapper, which aims to delegate as many
> operations as it can automatically to the underlying file object:
>
>     def __getattr__(self, name):
>         # Attribute lookups are delegated to the underlying file
>         # and cached for non-numeric results
>         # (i.e. methods are cached, closed and friends are not)
>         file = self.__dict__['file']
>         a = getattr(file, name)
>         if not issubclass(type(a), type(0)):
>             setattr(self, name, a)
>         return a
>
>  For 2.x, the only methods that need to be overridden explicitly are those
> where this bound method caching does the wrong thing (__exit__ and __enter__
> needed to be on that list, which is what first brought this class to my
> attention). For 3.0, it was also necessary to add:
>
>     def __iter__(self):
>         return iter(self.file)
>
>  It wasn't too bad in this case since file doesn't implement many tp_*
> slots, but the 3.0 version of classes that delegate a lot of operations to a
> specific member variable will be a lot more verbose in any cases where the
> underlying type being delegated to implements some of the number or
> container protocols.
>
>
>
> >
> > > to new-style, all that would then be needed is to invoke the new method
> on
> > >  the class object after defining the class (a class decorator or
> > >  metaclass could be provided somewhere to make this a bit tidier).
> > >
> >
> > Hm. So you are thinking of a proxy for a class?!?!
> >
>
>  Sort of - I'm thinking mainly of classes like _TemporaryFileWrapper that
> delegate most operations to a specific member variable, and expect that
> member variable to always be of a specific type.
>
>
>
> > Note that if you set a class attribute corresponding to a special
> > method (e.g. C.__add__ = ...) the corresponding C slot is
> > automatically updated, so you should be able to write a class
> > decorator or mixin or helper function to do this in pure Python,
> > unless I completely misunderstand what you're after.
> >
>
>  Yeah, doing it in typeobject was mostly an easy way of getting at the
> complete list of special methods with tp_* slots without having to maintain
> two copies of that list.
>
>
>
> >
> > >  This seems a lot cleaner than expecting everyone that implements a
> proxy
> > >  object to maintain there own list of all of the relevant special
> > >  methods, and locates the implementation support in an area of the code
> > >  that already has plenty of infrastructure dedicated to keeping Python
> > >  visible attributes in sync with the C visible tp_* slots.
> > >
> >
> > How many proxy implementations does the world need? Maybe we should
> > add one to the stdlib?
> >
>
>  I don't know enough about the different ways people proxy or otherwise
> delegate special methods to know if it is feasible to provide a
> one-size-fits-most implementation in the standard library.
>
>  That said, maybe it would be enough if a type instance could be queried for
> the list of special method names it implements that the interpreter can
> access without going through __getattribute__?
>
>  Then the slots of a class delegating to a specific type could be
> initialised appropriately by doing something like:
>
>   for name in delegate_type.special_methods():
>     if not hasattr(cls, name):
>         def delegation(*args, **kwds):
>             self, *args = args    # +1 on arbitrary tuple unpacking ;)
>             getattr(self.delegate, name)(*args, **kwds)
>         setattr(cls, name, delegation)
>
>  The approach I suggested in my original email would instead look more like
> this:
>
>   class Foo: ...
>
>   Foo.delegate_special_methods('delegate', delegate_type)
>
>  where delegate_special_methods is basically just a C level implementation
> of the loop described above (except that the 'delegation' callable could be
> a lot more efficient than the given Python function).
>
>  Another option would be to provide an explicit list in the documentation of
> the slot names for the tp_* methods which the interpreter may access without
> going through __getattr__ and __getattribute__.
>
>  The discussion in the bug report that got me thinking about this topic
> commented on the fact that quite a few magic methods were added during the
> 2.x development cycle - I think the key point I missed at the time is the
> fact that most of those *didn't* have corresponding tp_* slots, so
> __getattr__ and __getattribute__ (particularly the latter) can intercept
> them just fine.
>
>  That said, the documentation approach would probably be too limiting on
> alternate interpreters though - why should other implementations be
> restricted from providing optimised access to special methods just because
> we haven't done so certain cases in CPython?
>
>  If we don't make any changes at all, the delegation loop shown above can
> actually already be written as follows:
>
>   for name in dir(delegate_type):
>     if (name.startswith('__')
>           and name.endswith('__')
>           and not hasattr(cls, name)):
>         def delegation(*args, **kwds):
>             self, *args = args    # +1 on arbitrary tuple unpacking ;)
>             getattr(self.delegate, name)(*args, **kwds)
>         setattr(cls, name, delegation)
>
>
>
> >
> > >  Thoughts? Altenative ideas? Howls of protest?
> > >
> >
> > No, so far just a bit of confusion. :-)
> >
>
>  Hopefully the above makes my concerms a bit clearer.
>
>  I'm actually hoping to hear from some more people that would benefit from
> having better support for this kind of delegation - my interest in the
> matter is fairly academic (based solely on the tempfile bugs arising from
> the initial conversion to Py3k), so my personal inclination is actually to
> put a stronger note in the documentation about the fact that the lookup of
> special methods may bypass __getattribute__ entirely and leave it at that.
>
>  Cheers,
>  Nick.
>
>
>
>  --
>  Nick Coghlan   |   [EMAIL PROTECTED]   |   Brisbane, Australia
>  ---------------------------------------------------------------
>             http://www.boredomandlaziness.org
>



-- 
--Guido van Rossum (home page: http://www.python.org/~guido/)
_______________________________________________
Python-3000 mailing list
Python-3000@python.org
http://mail.python.org/mailman/listinfo/python-3000
Unsubscribe: 
http://mail.python.org/mailman/options/python-3000/archive%40mail-archive.com

Reply via email to