[Twisted-Python] Questions regarding serviceCollection and Interfaces.
Hi all. I'm in the process of moving a skeleton asyncore application to Twisted, and need some help. I'm hoping that someone with much Twisted Enlightenment can point me gently in the direction of understanding. (Amusingly enough, another poster recently summarised my exact experiences: start with asyncore, find its limitations, do a bit of shoehorning and end up trying with Twisted). Because this is new code I want to do The Right Thing vis-a-vis the latest Twisted coding techniques. Everything was peachy until I reached a certain step in the "Evolution of Finger" Tutorial. Until a certain point I had completely grokked the approach that looks like this: class Foo ( Protocol ): .... factory = ServerFactory() factory.protocol = Foo application = service.Application ( "fooserver" ) internet.TCPServer ( port, factory ).setServiceParent ( application ) However, then I reached: http://twistedmatrix.com/projects/core/documentation/howto/tutorial/componen... and the approach morphed into: application = service.Application ( "fooserver" ) f = FooService() serviceCollection = service.IServiceCollection ( application ) internet.TCPServer ( port, IFooFactory ( f ) ).setServiceParent ( serviceCollection ) Here are my questions: 1. I simply don't understand the third line of the new approach! :-) In twisted.application.service.py, I see: class IServiceCollection(components.Interface): .... So, "IServiceCollection" is an Interface; my (possibly outdated) understanding is that an interface is simply a specification that you can check against when something claims to implement it, hence all the "implements(Yadda)" calls everywhere (presumably, an exception is raised when something tells porkies about what it implements). But in this case, it looks like we're actually instantiating an interface class. I can't grok what this "means", especially in light of the fact that there is "MultiService" below it that implements IServiceCollection. 2. Similarly, in the last line, "IFooFactory(f)" is taking a Service (which isn't a factory) and passing it as a construction argument to IFooFactory (which also isn't a factory). The result is used as an argument to internet.TCPServer(), which expects a factory! 3. What do I gain by using a serviceCollection over an application as the serviceParent of a TCPServer? Come to think of it, what did I gain in the first place with setServiceParent()? 4. Lastly, there are lots of examples floating around that describe how each Protocol example can reference its own Factory in order for connections to be able to talk to other connections (for example, in the chat server example). However, what approach should I take when I have a single server with multiple Protocols? For example, consider a simple cache: I have a server which accepts TCP connections from lots of clients, and handles queries from these clients. The server actually gets information from an upstream server, but caches the results that it has already seen. In this case in the server I need a Protocol/TCPServer server to handle the multiple clients, and a single Protocol/connectTCP client for the upstream connection. However, it's not clear to me how I would transfer the data from the lineReceived() method of the server Protocol to the sendLine() method of the client Protocol, since each Protocol can see its own Factory, but not the Factory of the other Protocol. Many thanks for your time, and any assistance afforded! Ricky
On Tue, 2005-07-05 at 15:16 +0300, kgi wrote:
But in this case, it looks like we're actually instantiating an interface class. I can't grok what this "means", especially in light of the fact that there is "MultiService" below it that implements IServiceCollection.
This is interface adaptation, see http://twistedmatrix.com/projects/core/documentation/howto/components.html for an expalantion.
3. What do I gain by using a serviceCollection over an application as the serviceParent of a TCPServer? Come to think of it, what did I gain in the first place with setServiceParent()?
Services are setup as a tree; the application is the root of the tree. Services let you organize your code as pluggable self-contained parts that get startup and shutdown events. Of course, for a simple TCP server that doesn't give you much.
4. Lastly, there are lots of examples floating around that describe how each Protocol example can reference its own Factory in order for connections to be able to talk to other connections (for example, in the chat server example). However, what approach should I take when I have a single server with multiple Protocols?
For example, consider a simple cache: I have a server which accepts TCP connections from lots of clients, and handles queries from these clients. The server actually gets information from an upstream server, but caches the results that it has already seen.
In this case in the server I need a Protocol/TCPServer server to handle the multiple clients, and a single Protocol/connectTCP client for the upstream connection. However, it's not clear to me how I would transfer the data from the lineReceived() method of the server Protocol to the sendLine() method of the client Protocol, since each Protocol can see its own Factory, but not the Factory of the other Protocol.
myServerFactory.clientFactory = myClientFactory # and now server Protocol instances can do self.factory.clientFactory
On Tuesday 05 July 2005 16:50, Itamar Shtull-Trauring wrote:
On Tue, 2005-07-05 at 15:16 +0300, kgi wrote:
I can't grok what this "means", especially in light of the fact that there is "MultiService" below it that implements IServiceCollection.
This is interface adaptation, see http://twistedmatrix.com/projects/core/documentation/howto/components.html for an expalantion.
Thanks for your answer, Itamar. I've read the information at the link, and I think I've moved a few rungs up the grokking ladder now. I had previously read the Zope Interface introduction at: http://svn.zope.org/Zope3/trunk/src/zope/interface/README.txt?view=markup but this mostly just talks about the relationship between interfaces and objects (i.e. lots of .providedBy() and implementedBy() examples), and doesn't touch interface adaptation and components. I do have one question arising from the Zope documentation, though. In the link above, it says (abridged): """ class IFoo(zope.interface.Interface): def bar(q, r=None): """bar blah blah""" [...] Note that `bar` doesn't take a `self` argument. Interfaces document how an object is *used*. When calling instance methods, you don't pass a `self` argument, so a `self` argument isn't included in the interface signature. """ Yet all the examples I've seen in the Twisted documentation have interface methods that contain "self" parameters; for example, from the link you sent me: from zope.interface import Interface class IAmericanSocket(Interface): def voltage(self): """Return the voltage produced by this socket object, as an integer. """ Is this simply a cosmetic thing (i.e. no code actually looks at the function signature) or is the Zope Interface documentation out of date or wrong?
3. What do I gain by using a serviceCollection over an application as the serviceParent of a TCPServer? Come to think of it, what did I gain in the first place with setServiceParent()?
Services are setup as a tree; the application is the root of the tree. Services let you organize your code as pluggable self-contained parts that get startup and shutdown events. Of course, for a simple TCP server that doesn't give you much.
Got you, thanks.
In this case in the server I need a Protocol/TCPServer server to handle the multiple clients, and a single Protocol/connectTCP client for the upstream connection. However, it's not clear to me how I would transfer the data from the lineReceived() method of the server Protocol to the sendLine() method of the client Protocol, since each Protocol can see its own Factory, but not the Factory of the other Protocol.
myServerFactory.clientFactory = myClientFactory # and now server Protocol instances can do self.factory.clientFactory
OK, so it's as simple as just boshing in a new attribute. I guess I had got so hung up on not understanding the "service" stuff previously I was convinced the right way to access other Factories was via the serviceCollection. Again, thanks for your answer. Ricky P.S. I took so long in answering because I wanted to be able to answer maintaining the original message threading information (I know some people get really upset when you break threading), which eventually meant setting up a separate postfix server just for outgoing gmail email. If anyone has any information on either (1) getting a single postfix instance to work with multiple relayhosts for multiple "identities", or (2) configuring kmail to send directly to gmail over TLS, I'd love to hear how you did it. I found lots of generic configuration info for kmail, but I couldn't get kmail to manage it whatever I did.
On Wed, 2005-07-06 at 17:18 +0300, kgi wrote:
Is this simply a cosmetic thing (i.e. no code actually looks at the function signature) or is the Zope Interface documentation out of date or wrong?
Our code is wrong and needs the self removed; in practice though the methods on interfaces only serve as documentation, so it doesn't actually matter.
On Jul 6, 2005, at 10:18 AM, kgi wrote:
I do have one question arising from the Zope documentation, though. In the link above, it says (abridged):
""" class IFoo(zope.interface.Interface): def bar(q, r=None): """bar blah blah""" [...] Note that `bar` doesn't take a `self` argument. Interfaces document how an object is *used*. When calling instance methods, you don't pass a `self` argument, so a `self` argument isn't included in the interface signature. """
Yet all the examples I've seen in the Twisted documentation have interface methods that contain "self" parameters
Twisted hasn't always used Zope Interfaces -- we used to have our own. In our implementation, we *did* use self as the first argument. Thus, the general rule is, if you inherit from twisted.python.components.Interface (our backwards compatibility wrapper), you should follow our rule and include self as the first argument. However, if you inherit directly from zope.interface.Interface, you should follow zope's rule and not include self. That said, the signature isn't really used for anything at the moment. I've played around with an interface enforcement wrapper that does use the signature, but that's just playing around at the moment. James
kgi wrote:
If anyone has any information on either (1) getting a single postfix instance to work with multiple relayhosts for multiple "identities", or (2) configuring kmail to send directly to gmail over TLS, I'd love to hear how you did it. I found lots of generic configuration info for kmail, but I couldn't get kmail to manage it whatever I did.
No, but I do know of an email services company that provides a kmail-compatible IMAPS and SMTP/TLS implementation (using Twisted, even) ;-) http://divmod.com/; contact me privately for a ticket.
participants (4)
-
Glyph Lefkowitz -
Itamar Shtull-Trauring -
James Y Knight -
kgi