Twisted python: the correct way to pass a kwarg through the component system to a factory

StackOverflow https://stackoverflow.com/questions/19128517

Вопрос

I need to pass a kwarg to the parent class of my equivalent of FingerFactoryFromService using super.

I know I am actually passing the kwarg to IFingerFactory because that is also where I pass the service that ends up in init FingerFactoryFromService and I can understand that it is getting tripped up somewhere in the component system but I cannot think of any other way.

The error I keep getting is

exceptions.TypeError: 'test' is an invalid keyword argument for this function

Versions of code in my virtualenv are:

pip (1.4.1)
setuptools (1.1.6)
Twisted (13.1.0)
wsgiref (0.1.2)
zope.interface (4.0.5)

This is a cutdown example from the finger tutorial demonstrating the issue:

from twisted.protocols import basic

from twisted.application import internet, service
from twisted.internet import protocol, reactor, defer
from twisted.python import components
from zope.interface import Interface, implements  # @UnresolvedImport


class IFingerService(Interface):

    def getUser(user):  # @NoSelf
        """
        Return a deferred returning a string.
        """

    def getUsers():  # @NoSelf
        """
        Return a deferred returning a list of strings.
        """


class IFingerFactory(Interface):

    def getUser(user):  # @NoSelf
        """
        Return a deferred returning a string.
        """

    def buildProtocol(addr):  # @NoSelf
        """
        Return a protocol returning a string.
        """


def catchError(err):
    return "Internal error in server"


class FingerProtocol(basic.LineReceiver):

    def lineReceived(self, user):
        d = self.factory.getUser(user)
        d.addErrback(catchError)

        def writeValue(value):
            self.transport.write(value + '\r\n')
            self.transport.loseConnection()
        d.addCallback(writeValue)


class FingerService(service.Service):

    implements(IFingerService)

    def __init__(self, filename):
        self.filename = filename
        self.users = {}

    def _read(self):
        self.users.clear()
        for line in file(self.filename):
            user, status = line.split(':', 1)
            user = user.strip()
            status = status.strip()
            self.users[user] = status
        self.call = reactor.callLater(30, self._read)  # @UndefinedVariable

    def getUser(self, user):
        print user
        return defer.succeed(self.users.get(user, "No such user"))

    def getUsers(self):
        return defer.succeed(self.users.keys())

    def startService(self):
        self._read()
        service.Service.startService(self)

    def stopService(self):
        service.Service.stopService(self)
        self.call.cancel()


class FingerFactoryFromService(protocol.ServerFactory):

    implements(IFingerFactory)

    protocol = FingerProtocol

    #def __init__(self, srv):
    def __init__(self, srv, test=None):
        self.service = srv
        ## I need to call super here because my equivalent of ServerFactory requires 
        ## a kwarg but this cutdown example doesnt so I just assign it to a property
        # super(FingerFactoryFromService, self).__init__(test=test)
        self.test_thing = test or 'Default Something'

    def getUser(self, user):
        return self.service.getUser(user)

components.registerAdapter(FingerFactoryFromService,
                           IFingerService,
                           IFingerFactory)

application = service.Application('finger')
serviceCollection = service.IServiceCollection(application)

finger_service = FingerService('/etc/passwd')
finger_service.setServiceParent(serviceCollection)

#line_finger_factory = IFingerFactory(finger_service)
line_finger_factory = IFingerFactory(finger_service, test='Something')
line_finger_server = internet.TCPServer(1079, line_finger_factory)
line_finger_server.setServiceParent(serviceCollection)  
Это было полезно?

Решение

This has nothing to do with the component system. What you want to do is override the Factory's buildProtocol method, as documented here:

https://twistedmatrix.com/documents/current/core/howto/servers.html#auto9

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top