[Twisted-Python] Assigning AMP box senders & receivers from the responder

Laurens Van Houtven _ at lvh.cc
Tue Jul 3 01:08:41 MDT 2012


Hi,

I have an AMP service that does cred-based auth with IBoxReceiver as the interface (see mantissa). On login, the user gets a different API depending if they're a staff member or not.

Additionally, I wrote a composing IResponderLocator. It takes a bunch of responder locators and calls them in sequence to see if they can provide a responder. The reason it exists is because I want to put behavior in their separate, related modules, but @Command.responder is only supposed to work at class definition time. Here's the implementation:

class ComposedLocator(object):
   """
   A responder locator that consists of other locators.
   """
   interface.implements(amp.IResponderLocator)

   class __metaclass__(type):
       def __new__(meta, name, bases, attrs):
           """
           Makes sure every subclass gets its own set of locator classes.
           """
           attrs["_locatorClasses"] = []
           return type.__new__(meta, name, bases, attrs)


   def __init__(self, *args, **kwargs):
       self._locators = [l(*args, **kwargs) for l in self._locatorClasses]


   def locateResponder(self, name):
       """
       Locates a responder from all the component responders.
       """
       for locator in self._locators:
           responder = locator.locateResponder(name)
           if responder is not None:
               return responder


   @classmethod
   def component(cls, locatorClass):
       """
       Registers a component locator.
       """
       cls._locatorClasses.append(locatorClass)
       return locatorClass



This has worked fine so far, but I've hit something so annoying to fix that I'm wondering if I'm not doing something very stupid and overlooking the obvious.

I'm trying to implement a command called "Become" that allows a staff member to work as if he was the user himself. The most obvious way (to me at least) to do that  to create the customer API (an IBoxReceiver/amp.BoxDispatcher subclass) for that customer (that'd normally be the Realm's job -- but since we're already logged in as an administrator, we don't go through Cred again), and hook up the current connection with that box receiver. Yay, code reuse!

Except, no. Because of the composed locator detailed above, the responding method has no reference to the box sender and box receiver.  It's it's own little standalone object, with barely any AMP-specific knowledge. Ordinarily elegant, now annoying.

The only reason it ever worked before is because the default AMP implementation basically just involves subclassing everything into one object (self is self.boxReceiver is self.boxSender)

I don't see an obvious way to get a reference to the boxReceiver/boxSender from the responder method using documented APIs. Does this just mean I have to leak a reference to them all the way down? Am I doing something stupid?


cheers
lvh






More information about the Twisted-Python mailing list