Re: Wrapper objects

2004-12-10 Thread redhog
Bengt Richter wrote:
> On 9 Dec 2004 06:11:41 -0800, [EMAIL PROTECTED] (Egil M?ller) wrote:
>
> >Is there any way to create transparent wrapper objects in Python?
> >
> >I thought implementing __getattribute__ on either the wrapper class
or
> >its metaclass would do the trick, but it does not work for the built
> >in operators:
> >
> >class Foo(object):
> >class __metaclass__(type):
> >def __getattribute__(self, name):
> >print "Klass", name
> >return type.__getattribute__(self, name)
> >def __getattribute__(self, name):
> >print "Objekt", name
> >return object.__getattribute__(self, name)
> >
> >
>  Foo() + 1
> >Traceback (most recent call last):
> >  File "", line 1, in ?
> >TypeError: unsupported operand type(s) for +: 'Foo' and 'int'
>  Foo().__add__(1)
> >Objekt __add__
> >Traceback (most recent call last):
> >  File "", line 1, in ?
> >  File "", line 8, in __getattribute__
> >AttributeError: 'Foo' object has no attribute '__add__'
> >
> >
> >Thus, note that a + b does not do
> >
> >try:
> >return a.__add__(b)
> >except:
> >return b.__radd__(a)
> >
> >and neither, as I first thought
> >
> >try:
> >return type(a).__add__(a, b)
> >...
> >
> >but something along the lines of
> >
> >try:
> >return type.__getattribute__(type(a), '__add__')(a, b)
> >...
> >
> >
> >So my naive implementation of a wrapper class,
> >
> >
> >class wrapper(object):
> >def __init__(self, value, otherdata):
> >self.value = value
> >self.otherdata = otherdata
> >def __getattribute__(self, name):
> >return getattr(self.value, name)
> >
> >
> >does not work. Any ideas for a solution?
>
> This seems to go some way towards it:
>
>  >>> class MethodDesc(object):
>  ... def __get__(self, inst, cls=None):
>  ... if inst is None: return self
>  ... func = self.__dict__['func']
>  ... if func: return func.__get__(self.thing,
type(self.thing))
>  ... else: return getattr(self.thing, self.name)
>  ... def __init__(self, name, thing, func):
>  ... self.name = name
>  ... self.thing = thing
>  ... self.func = func
>  ... def __call__(self, *args, **kw): print 'called %s: %r
%r'%(self.name, args, kw)
>  ...
>  >>> def wrapit(thing, *otherdata):
>  ... class Wrapper(object):
>  ... def __metaclass__(cname, cbases, cdict):
>  ... for name, func in type(thing).__dict__.items():
>  ... if callable(func):
>  ... if name not in [
>  ... '__getattr__', '__getattribute__',
'__setattr__',
>  ... '__new__', '__init__']:
>  ... cdict[name] = MethodDesc(name,
thing, func)
>  ... else:
>  ... cdict[name] = MethodDesc(name, thing, None)
>  ... return type(cname, cbases, cdict)
>  ... def __init__(self, *otherdata):
>  ... if otherdata: self.otherdata = otherdata
>  ... def __getattr__(self, name):
>  ... raise AttributeError('Wrapped %r object has no
attribute %r'% (type(self).__name__, name))
>  ... Wrapper.__name__ = 'Wrapped_'+type(thing).__name__
>  ... return Wrapper(*otherdata)
>  ...
>  >>> class Demo(object):
>  ... a = 'eigh'
>  ... two = 2
>  ... def foo(self): return 'Demo foo'
>  ... def bar(self, *args, **kw): print 'Demo bar %r %r'%(args,
kw)
>  ...
>  >>> o2 = wrapit( Demo(), 'stuff')
>  >>> o2.foo
>  >
>  >>> o2.foo()
>  'Demo foo'
>  >>> o2.bar(1,2,3,x=111,y=222)
>  Demo bar (1, 2, 3) {'y': 222, 'x': 111}
>  >>> o2.a
>  'eigh'
>  >>> o2.two
>  2
>  >>> o2.z
>  Traceback (most recent call last):
>File "", line 1, in ?
>File "", line 16, in __getattr__
>  AttributeError: Wrapped 'Wrapped_Demo' object has no attribute 'z'
>  >>> o2.z = 'zee'
>  >>> o2.z
>  'zee'
>  >>> o2
>  
>  >>> o2.a = 'not eigh'
>  >>> o2.a
>  'not eigh'
>  >>> del o2.a
>  >>> o2.a
>  'eigh'
>  >>> o3 = wrapit('strange', 'stuff')
>  >>> o3
>  'strange'
>  >>> o3.otherdata
>  ('stuff',)
>  >>> o3[2:]
>  'range'
>  >>>
>  >>> o3.z
>  Traceback (most recent call last):
>File "", line 1, in ?
>File "", line 16, in __getattr__
>  AttributeError: Wrapped 'Wrapped_str' object has no attribute 'z'
>
> Not tested beyond what you see ;-) This doesn't wrap setting
attributes on the wrapped object,
> so setting attributes sets them on the wrapper itself, but that could
be fixed.
>
> Now what was it you wanted to use a wrapper for? ;-)
> Note:
>
>  >>> o3 += 'fail'
>  >>> o3
>  'strangefail'
>  >>> type(o3)
>  
>
> So if you want new wrapped instances as results from various ops, we
need some more code ;-)
> Another time ... (cf. a recent post of mine re wrapping complex as a
point type).
>
> Regards,
> Bengt Richter


Ah, thanks. I didn't think of the possibility of creating a list of
methods that needed wrapping, and wrapping them uppon creation of

Re: Wrapper objects

2004-12-10 Thread redhog
Ah, thanks. I didn't think of the possibility of creating a list of
methods that needed wrapping, and wrapping them uppon creation of the
wrapper object. Mainly I think, becaus it seems to me as such an uggly
workaround for a misdesign in Python. Also, if the wrapped object gets
some extra methods/callable member variables added "after the fact",
those will not get wrapped (this is however not a common thing to
happen, it just annoys me that it won't work).

As to what I want to use this for, I today have a huge program in which
several objects are wrapped up with comments (made up by some DOMish
structre) which are displayed to the user at various times. For
example, a list of users may be represented as as comment "List of
users" and a python list of elements, each being a user id (represented
as an integer), with a comment being the username. This means the list
is usable both for user-output and for machine-handling. Hm, this
wasn't prolly such a good example, but hopefully, it shows enought of
the idea...

Todya, the comment-value-pair is an ordinary object with two member
variables, and there are two functions, getComment and getValue, which
extracts a comment if its argument is such an object, or None
otherwise, and the wrapped value if its argument is such an object, and
the argument itself otherwize, respectively.

This means my code is literally filled with calls to getValue(), which
I would like to be able to remove by making the comment-value pair more
transparent.

Anyway, I do have some questions about your implementation:

If "if inst is None: return self" to protect for infinite recursion
when looking up self.__dict__?

What is the reason to give func to the MethodDesc property object, why
does its __get__ method have to do

if func: return func.__get__(self.thing, type(self.thing))

?

What is the reason to neither wrap, nor just copy, any of __getattr__,
__getattribute__, __setattr__, '__new__' or '__init__'? Especially
__getattr__, __getattribute__ and __setattr__ seems to need at least
some type of wrapping (but perheaps some special one)?
Regards,
Egil Möller

--
http://mail.python.org/mailman/listinfo/python-list


Re: Wrapper objects

2004-12-10 Thread redhog
As to what I want to use this for, I today have a huge program in which
several objects are wrapped up with comments (made up by some DOMish
structre) which are displayed to the user at various times. For
example, a list of users may be represented as as comment "List of
users" and a python list of elements, each being a user id (represented
as an integer), with a comment being the username. This means the list
is usable both for user-output and for machine-handling. Hm, this
wasn't prolly such a good example, but hopefully, it shows enought of
the idea...

Tody, the comment-value-pair is an ordinary object with two member
variables, and there are two functions, getComment and getValue, which
extracts a comment if its argument is such an object, or None
otherwise, and the wrapped value if its argument is such an object, and
the argument itself otherwize, respectively.

This means my code is literally filled with calls to getValue(), which
I would like to be able to remove by making the comment-value pair more
transparent.

The wrapper objects needs to work as dictionary keys, to support
printing, concatenation/addition, getitem/setitem and such things...

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Wrapper objects

2004-12-10 Thread redhog
>Well, that could be a feature, depending on what your use case is.
>Or you could make a method for adding methods, I suppose.
>A perfectly transparent wrap of obj would be to do nothing ;-)
>What do you actually want to do?

Actually, the very best would if only type(), isinstance() and the
is-keyword could an object and a wrapped version of it apart.

I've thought of using a weakdict instaed, problem is, it would be a
little bit too transparent for my purpose as the only way to tell an
object and a wrapped version of it apart would be by my own functions
which would do lookups in that dict. Secondly, it would only allow for
one comment per object dopy, which would fail horribly for e.g. numbers
(there are hundreds of uses of the number 1, which all needs different
comments for the number).

-- 
http://mail.python.org/mailman/listinfo/python-list