Generic proxy (that proxies methods like __iter__)

D

D HANNEY

.... with opened as file:
.... for line in file:
.... print line.strip()
....
blah1
blah2
blah3


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

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in show
AttributeError: StringIO instance has no attribute '__exit__'

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

.... 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__()
....
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__)
#

.... 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)
....Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in show
TypeError: 'NoGuardProxy' object is not iterable

#
# Now I'm stuck.
# Can anyone help?
#
 
A

Arnaud Delobelle

... 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 "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in show
TypeError: 'NoGuardProxy' object is not iterable

#
# Now I'm stuck.
# Can anyone help?
#

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.
 
D

D HANNEY

[...]

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.

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
 
D

D HANNEY

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)
Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41)
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top