"""Declaration support for Twisted Interfaces""" __all__ = [] from adapters import * from api import advise from interfaces import IOpenProtocol from weakref import WeakKeyDictionary # Twisted uses an approach to __adapt__ that is largely incompatible with # PEP 246, so we have to jump through some twisty hoops to convince it to work # for our purposes, without breaking Twisted's test suite. class TwistedAdaptMethod(object): """__adapt__ implementation for Twisted interfaces""" __slots__ = 'iface' def __init__(self,iface): self.iface = iface def __call__(self, obj): # This is the __adapt__ method that you get # for ISomething.__adapt__()... if TwistedImplements(obj, self.iface): return obj # Get Twisted to try and adapt return self.iface(obj, None) def im_func(self, ob, default): # And this is what MetaInterface.__call__ calls when # it goes after __adapt__.im_func! meth = self.iface.__dict__.get('__adapt__') if meth is None: return default return meth(ob,default) # Monkeypatch Twisted Interfaces try: from twisted.python.components import \ implements as TwistedImplements, \ MetaInterface as TwistedInterfaceClass, \ getInterfaces as TwistedGetInterfaces except ImportError: TwistedInterfaceTypes = [] else: # Force all Twisted interfaces to have an __adapt__ method TwistedInterfaceClass.__adapt__ = property(lambda s: TwistedAdaptMethod(s)) TwistedInterfaceTypes = [TwistedInterfaceClass] class TwistedInterfaceAsProtocol(object): __slots__ = 'iface' advise( instancesProvide=[IOpenProtocol], asAdapterForTypes=TwistedInterfaceTypes, ) def __init__(self, iface): self.iface = iface def __adapt__(self, obj): return self.iface.__adapt__(obj) def registerImplementation(self,klass,adapter=NO_ADAPTER_NEEDED,depth=1): oldImplements = TwistedGetInterfaces(klass) if adapter is NO_ADAPTER_NEEDED: klass.__implements__ = self.iface, tuple(oldImplements) elif adapter is DOES_NOT_SUPPORT: if self.iface in oldImplements: oldImplements.remove(self.iface) klass.__implements__ = tuple(oldImplements) else: raise TypeError( "Twisted interfaces can only declare support, not adapters", self.iface, klass, adapter ) def addImpliedProtocol(self, proto, adapter=NO_ADAPTER_NEEDED, depth=1): iface = self.iface # XXX need to ensure 'proto' is usable w/Twisted! self.iface.adaptWith(lambda o: adapter(o, iface), proto) # XXX is the above sufficient? # XXX What are Twisted's adapter override semantics? listeners = iface.__dict__.get('_Protocol__listeners',{}) for listener in listeners.keys(): # Must use keys()! listener.newProtocolImplied(self, proto, adapter, depth) def registerObject(self, ob, adapter=NO_ADAPTER_NEEDED, depth=1): oldImplements = TwistedGetInterfaces(ob) if adapter is NO_ADAPTER_NEEDED: ob.__implements__ = self.iface, tuple(oldImplements) elif adapter is DOES_NOT_SUPPORT: if self.iface in oldImplements: oldImplements.remove(self.iface) ob.__implements__ = tuple(oldImplements) else: raise TypeError( "Twisted interfaces can only declare support, not adapters", self.iface, ob, adapter ) def addImplicationListener(self, listener): listeners = self.iface.__dict__.setdefault( '_Protocol__listeners',WeakKeyDictionary() ) listeners[listener] = True