FAQ
Hi!

I have an extension module (a plugin written with Boost.Python) and around
that a wrapper class that adapts a few things. Since the module is a
plugin, there are multiple implementations of this. What I'm currently
doing is this:

plugin = __import__(plugin_name)

class PluginWrapper(plugin.PluginClass):
...

This means that the definition of class PluginWrapper actually depends on
the previously loaded module. What I would like to do is to define the
wrapper just once and instead pass the plugin module to the constructor:

class PluginWrapper(object):
...
plugin = __import__(plugin_name)
instance = PluginWrapper(plugin)


Now, I use the wrapper to make some function more friendly (e.g. default
parameters, keyword-parameters, wrapping raw handles) but I want other
functions from the baseclass to remain untouched. If I use a baseclass,
this lookup is automatic. However, when I pass the instance to the
constructor, I have to store it in a member, and then I have to add code
for every function only to delegate it to that member.

Is there an easy and generic way out of this?

Thanks!

Uli

--
Sator Laser GmbH
Gesch?ftsf?hrer: Thorsten F?cking, Amtsgericht Hamburg HR B62 932

Search Discussions

  • Peter Otten at Aug 10, 2010 at 9:12 am

    Ulrich Eckhardt wrote:

    Hi!

    I have an extension module (a plugin written with Boost.Python) and around
    that a wrapper class that adapts a few things. Since the module is a
    plugin, there are multiple implementations of this. What I'm currently
    doing is this:

    plugin = __import__(plugin_name)

    class PluginWrapper(plugin.PluginClass):
    ...

    This means that the definition of class PluginWrapper actually depends on
    the previously loaded module. What I would like to do is to define the
    wrapper just once and instead pass the plugin module to the constructor:

    class PluginWrapper(object):
    ...
    plugin = __import__(plugin_name)
    instance = PluginWrapper(plugin)


    Now, I use the wrapper to make some function more friendly (e.g. default
    parameters, keyword-parameters, wrapping raw handles) but I want other
    functions from the baseclass to remain untouched. If I use a baseclass,
    this lookup is automatic. However, when I pass the instance to the
    constructor, I have to store it in a member, and then I have to add code
    for every function only to delegate it to that member.

    Is there an easy and generic way out of this?
    Use getattr()
    class W(object):
    ... def __init__(self, wrapped): self._wrapped = wrapped
    ... def __getattr__(self, name):
    ... return getattr(self._wrapped, name)
    ...
    class A(object):
    ... def hello(self): print "hello"
    ...
    a = A()
    w = W(a)
    w.hello()
    hello

    However, with newsytle classes this doesn't work for __special__ methods
    w.__str__()
    '<__main__.W object at 0x7f04ef2d4c50>'

    Peter
  • Ulrich Eckhardt at Aug 10, 2010 at 10:40 am

    Peter Otten wrote:
    Use getattr()
    class W(object):
    ... def __init__(self, wrapped): self._wrapped = wrapped
    ... def __getattr__(self, name):
    ... return getattr(self._wrapped, name)
    ...
    I thought there was something like this, thanks! :)

    When I read this, I thought "OK, now I only have check first if the
    attribute can be looked up in 'self' first", but even that isn't the case.
    I tried it and added another function to class W above, which I can call
    just as if it was defined in _wrapped, so obviously (?) the __getattr__
    lookup isn't done there.

    So, short follow-up question: Why does this work?

    Uli

    --
    Sator Laser GmbH
    Gesch?ftsf?hrer: Thorsten F?cking, Amtsgericht Hamburg HR B62 932
  • Peter Otten at Aug 10, 2010 at 11:17 am

    Ulrich Eckhardt wrote:

    Peter Otten wrote:
    Use getattr()
    class W(object):
    ... def __init__(self, wrapped): self._wrapped = wrapped
    ... def __getattr__(self, name):
    ... return getattr(self._wrapped, name)
    ...
    I thought there was something like this, thanks! :)

    When I read this, I thought "OK, now I only have check first if the
    attribute can be looked up in 'self' first", but even that isn't the case.
    The getattr() call inside __getattr__() raises an AttributeError if it can't
    find an attribute called name in self._wrapped. This very thing you'd have
    to do if you wanted to signal that an attribute doesn't exist, like in
    class A:
    ... def __getattr__(self, name):
    ... if name == "foo": return 42
    ... raise AttributeError
    ...
    a = A()
    a.foo
    42
    a.bar
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "<stdin>", line 4, in __getattr__
    AttributeError
    I tried it and added another function to class W above, which I can call
    just as if it was defined in _wrapped, so obviously (?) the __getattr__
    lookup isn't done there.

    So, short follow-up question: Why does this work?
    __getattr__() is a fallback that is only tried when the normal lookup fails.
    If you need to intercept every attribute lookup use __getattribute__()
    instead:
    class A(object):
    ... def __getattr__(self, name):
    ... print "__getattr__(%r)" % name
    ... return 42
    ... def __getattribute__(self, name):
    ... print "__getattribute__(%r)" % name
    ... return super(A, self).__getattribute__(name)
    ...
    a = A()
    a.foo = "yadda"
    a.foo
    __getattribute__('foo')
    'yadda'
    a.bar
    __getattribute__('bar')
    __getattr__('bar')
    42

    Peter
  • Ulrich Eckhardt at Aug 10, 2010 at 12:20 pm

    Peter Otten wrote:
    Ulrich Eckhardt wrote:
    So, short follow-up question: Why does this work?
    __getattr__() is a fallback that is only tried when the normal lookup
    fails. If you need to intercept every attribute lookup use
    __getattribute__() instead:
    Thank you Peter, that was the missing piece to understand it!

    Uli

    --
    Sator Laser GmbH
    Gesch?ftsf?hrer: Thorsten F?cking, Amtsgericht Hamburg HR B62 932
  • Chris Rebert at Aug 10, 2010 at 9:19 am

    On Tue, Aug 10, 2010 at 2:01 AM, Ulrich Eckhardt wrote:
    Hi!

    I have an extension module (a plugin written with Boost.Python) and around
    that a wrapper class that adapts a few things. Since the module is a
    plugin, there are multiple implementations of this. What I'm currently
    doing is this:

    ?plugin = __import__(plugin_name)

    ?class PluginWrapper(plugin.PluginClass):
    ? ? ...

    This means that the definition of class PluginWrapper actually depends on
    the previously loaded module. What I would like to do is to define the
    wrapper just once and instead pass the plugin module to the constructor:

    ?class PluginWrapper(object):
    ? ?...
    ?plugin = __import__(plugin_name)
    ?instance = PluginWrapper(plugin)


    Now, I use the wrapper to make some function more friendly (e.g. default
    parameters, keyword-parameters, wrapping raw handles) but I want other
    functions from the baseclass to remain untouched. If I use a baseclass,
    this lookup is automatic. However, when I pass the instance to the
    constructor, I have to store it in a member, and then I have to add code
    for every function only to delegate it to that member.

    Is there an easy and generic way out of this?
    Create the subclass(es) dynamically:

    def wrap(plug_in):
    class PluginWrapper(plug_in.PluginClass):
    ...
    return PluginWrapper

    plugin = __import__(plugin_name)
    WrappedPlugin = wrap(plugin)

    Cheers,
    Chris

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedAug 10, '10 at 9:01a
activeAug 10, '10 at 12:20p
posts6
users3
websitepython.org

People

Translate

site design / logo © 2022 Grokbase