Generic proxy (that proxies methods like __iter__)

2010-01-27 Thread D HANNEY

>>> def show(opened):
... with opened as file:
... for line in file:
... print line.strip()
...

>>> show(open("test.txt"))
blah1
blah2
blah3


#
# Good! I wonder if I can do that with StringIO ...
#


>>> import StringIO
>>> show(StringIO.StringIO("blah1\nblah2\nblah3\n"))
Traceback (most recent call last):
  File "", line 1, in 
  File "", line 2, in show
AttributeError: StringIO instance has no attribute '__exit__'

#
# Oh dear ... I'll need to proxy it ...
#


>>> class IterNoGuardProxy(object):
... def __init__(self, t):
... self.t = t
... def __enter__(self):
... return self
... def __exit__(self, type, value, traceback):
... return False
... def __iter__(self):
... return self.t.__iter__()
...
>>> show(IterNoGuardProxy(StringIO.StringIO("blah1\nblah2\nblah3\n")))
blah1
blah2
blah3
>>>


#
# Great! That works well. Now I wonder if I can do it generically
# in a way that can proxy for ALL methods (including, but not limited
to, __iter__)
#


>>> class NoGuardProxy(object):
... def __init__(self, t):
... self.t = t
... def __enter__(self):
... return self
... def __exit__(self, type, value, traceback):
... return False
... def __getattr__(self):
... return self.t.__getattr__(self)
...
>>> show(NoGuardProxy(StringIO.StringIO("blah1\nblah2\nblah3\n")))
Traceback (most recent call last):
  File "", line 1, in 
  File "", line 3, in show
TypeError: 'NoGuardProxy' object is not iterable

#
# Now I'm stuck.
# Can anyone help?
#
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Generic proxy (that proxies methods like __iter__)

2010-01-28 Thread D HANNEY
On Jan 27, 3:07 pm, Arnaud Delobelle  wrote:
> On 27 Jan, 14:41, D HANNEY  wrote:
> [...]
>
> See [1] for an explanation.  Here is an idea: you could get round that
> by generating a class on the fly, if you don't mind changing the class
> of the object (untested):
>
> def noguardproxy(obj):
>     class NoGuardProxy(type(obj)):
>         def __enter__(self):
>                return self
>         def __exit__(self, type, value, traceback):
>                return False
>     obj.__class__ = NoGuardProxy
>     return obj
>
> If you want to keep obj untouched, you could add the line
>
>     obj = copy(obj)
>
> before changing the class.
>
> --
> Arnaud
>
> [1]http://docs.python.org/reference/datamodel.html#new-style-special-lookup

Thank you!

Your solution works if I change "type(obj)" to say "obj.__class__".
If I don't make this change Python complains "TypeError: Error when
calling the metaclass bases type 'instance' is not an acceptable base
type".
So, I've got something that works but I don't understand why it works.
I've read your docs.python reference but that hasn't helped yet. It
might come to me but in the meantime, can you (or anyone) offer an
explanation for this?

Thanks in advance,

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


Re: Generic proxy (that proxies methods like __iter__)

2010-01-28 Thread D HANNEY
On Jan 28, 1:31 pm, D HANNEY  wrote:
>
> Your solution works if I change "type(obj)" to say "obj.__class__".
> If I don't make this change Python complains "TypeError: Error when
> calling the metaclass bases type 'instance' is not an acceptable base
> type".
> So, I've got something that works but I don't understand why it works.
> I've read your docs.python reference but that hasn't helped yet. It
> might come to me but in the meantime, can you (or anyone) offer an
> explanation for this?
>
> Thanks in advance,
>
> David

Oh it looks like this is py3K thing.

Python 3.0.1+ (r301:69556, Apr 15 2009, 15:59:22)
>>> from io import StringIO
>>> type(StringIO("x"))

>>> StringIO("x").__class__

>>>

Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41)
>>> from StringIO import StringIO
>>> type(StringIO("x"))

>>> StringIO("x").__class__

>>>

I was using 2.6.2. Your suggestion would have been fine in py3k.

Even if I stuck with 2.6.2 and StringIO was a "new style class" there
then it would have been fine ... but it isn't.
As it stands __class__ seems the only way that works on both 3k and
2k.
Bit weird, but I get it now.

Thanks again!

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