[Twisted-Python] Adapting RemoteReferences

Sam Jordan sam at twistedmatrix.com
Mon Nov 3 06:41:14 MST 2003


Hi,

What is the general opinion on having a standard way to adapt
RemoteReferences to specific interfaces which basically just
wraps callRemote for each respective method?

The reason i'm bringing this up is I can imagine various
use-cases for wanting to treat remote objects and local objects
as semantically equivalent. For example, I may be employing
the observer pattern for a simple system to separate UI components
from data components. Currently if I wish to have both remote and
local observers interoperate I would have to either store them
in separate data structures and treat each differently when
sending notifications, or, I could store them in a single
data structure and use appropriate type-checking to dispatch the
calls. IMHO both of these solutions are relatively ugly.

Whether or not there are sufficient use-cases for a standard twisted
way to do this is another story, so i'm wondering what the views of
people are on this subject. Certainly one could just register their own
adapter for RemoteReference in each case, but the code to do this is rather
ugly and for those that _do_ have to deal with such cases I think it would
be nicer to have a simple, standard way of doing it,
e.g. remoteRef.adaptTo(Interface).

I've written a function that outlines the functionality I think it should
provide which is included below; while this implementation is rather ugly
i'm more worried about the idea rather than how it would eventually be
implemented if someone decides this is worth having.

Of course, there are certain constraints, such as the method wrappers
having no way of knowing if the remote object actually implements the
desired interface or not, but I don't see this as a problem for something
that already requires string based dispatch. I guess you could say this
proposal is somewhat similar to java's 'stub' approach, only it doesn't
force it :-).

Cheers,

Sam.

------------------------------------------
import types

class Interface:
  def add(x,y): pass
  def mul(x,y): pass

class Interface2(Interface):
  def div(x,y): pass
  def sub(x,y): pass

class Foo:
  def callRemote(self, name, *args, **kw): print 'calling %s with %s %s' % (name, args, kw)

# this would likely put put in RemoteReference
# to provide context
def adaptTo(self, interface):
    # obtain all interface methods
    methods = interface.__dict__
    for base in interface.__bases__:
        for attrib,val in base.__dict__.iteritems():
            if not methods.has_key(attrib) and isinstance(val, types.FunctionType):
                methods[attrib] = base.__dict__[attrib]

    class _Adapter:
        def __init__(self, original): self.original = original

        for m in methods:
            exec "def %s(self, *args, **kw): return self.original.callRemote('%s', *args, **kw)" % (m,m)

    del _Adapter.m
    del _Adapter.methods
    return _Adapter(self)

def test():
    a = adaptTo(Foo(), Interface2)
    a.add(1,2)
    a.mul(2,4)
    a.div(8,4)
    a.sub(3,5)

test()

------------------------------------------




More information about the Twisted-Python mailing list