[Twisted-Python] [spread] "We're walking, we're walking, we're walking..."

[Yes, I do intend to spend some more time digesting this and working it into code and perhaps more english, but that won't get done tonight... So for now, Share and Enjoy!] IRC log started Thu Aug 02 00:06:16 2001 (PDT -0700) * Acapnotic pokes glyph <glyph> Acapnotic: sorry, did you answer before? <Acapnotic> glyph: Ok, I started the log ten minutes ago for you, and so far it mainly consists of descriptions of thirmite's van =) <dash> haha <thirmite> my van is awsome <dash> "ph34r my l33t v4n" <thirmite> heh <glyph> Acapnotic: OK. Let's get started then. :) <glyph> Acapnotic: What do you want to do with PB? <Acapnotic> glyph: whiteboard, say. client -> server -> many-clients. but we can start with just half of that. <glyph> Acapnotic: OK. First thing you need is a whiteboard service on the server. <glyph> Acapnotic: by "service" I literally mean a subclass of pb.Service <Acapnotic> a pb.Service, okay. That doesn't have many methods <glyph> Acapnotic: crap. I think I may have changed some naming here :-). Does your version say anything about getPerspectiveNamed? <Acapnotic> glyph: yes, getPerspectiveNamed(self,name) is the only method <glyph> Acapnotic: Ok, cool. <glyph> Acapnotic: So you have to implement that method to retrieve something that represents a viewer of whiteboards <glyph> Acapnotic: twisted.reality.plumbing can provide an example for this. <glyph> uh, actually twisted.reality.reality.Reality, now that I think of it :) <dash> reality, reality, REALITY! (ta-daa!) <dash> glyph: you have such a way with names <Acapnotic> "a viewer" probably being a front-end? or the client that's got a display attached? <glyph> dash: everybody has a bad day sometimes :-\ <dash> glyph: no, i like it <dash> it's a as subtle as a jackhammer :) <glyph> Acapnotic: It's the back-end, not the front-end. We're still on the server. <glyph> Acapnotic: whatever you return is the thing that the authenticated user is going to be able to call methods on; it should be a subclass of pb.Perspective <Acapnotic> ah, okay, I was derailed for a moment there getting stuck on "viewer". but this isn't just a passive thing, it's what we call on to modify the whiteboard as well, ja? <glyph> yes <glyph> hmm, maybe we should do this tomorrow, *AFTER* I check in these changes <Acapnotic> no two days the same, eh? <Acapnotic> glyph: Ok, then don't give me specifics on every method I need to override. Big picture -- what classes go on which end, what talks to what? <glyph> Acapnotic: welll, after hte handshake we just described, you've got a Perspective on the server <glyph> the client has a Reference to that Perspective <glyph> so when the client says perspective.foo(bar, baz), the server's perspective gets x.perspective_foo(bar, baz) called on it <Acapnotic> glyph: Okay. And is this one of your "there are no return values" areas? <Acapnotic> yes, because calls are asyncronyous... crap, I can't spell these days. <glyph> Acapnotic: Yes. There are no return values; if the client wants to get a callback when the return value's ready, it calls p.foo(bar, baz, pbcallback=qux) <Acapnotic> glyph: So now I can do whiteboard_author_client->server. To do server->whiteboard_audience_client, will I flip this around and put a "server" in each client? (a la X) <glyph> Acapnotic: No need. <glyph> Acapnotic: You can just have each interested "listener" pass a subclass of "pb.Referenced" into a remote callback, which defines a method that the server will call. <Acapnotic> glyph: so I'm just going to stash a bunch of these Referenced callbacks in some private attribute, and then run through them whenever I want to talk at them? <glyph> Acapnotic: essentially, yes. <Acapnotic> glyph: now you said these subclasses_of(pb.Referenced) defined a method to call. Does that mean I should have them __call__able? Or will I call their methods? Or is that entirely up to me? <glyph> Acapnotic: Subclasess of pb.Referenced define methods named remote_XXX; remoteobj.XXX() on the other side will invoke those methods. <Acapnotic> glyph: and I missed a piece of the handshaking. Where did the client/server connection happen? <glyph> Acapnotic: that's irrelevant :) <glyph> the way that happens is just you instantiate a tcp.Client with a Broker as the protocol <glyph> all fo these interactions happen through the pb.Broker <glyph> (requestPerspective, to be precise) <Acapnotic> ok, that's good to know, I wouldn't call that irrelevant =) -- "...we're stopped."

Abstract: Trace the construction of a PB-using application from the top, to the side, to the inside-out. [XXX: Add "why the gleep you should actually care about PB introduction-hook here."] Disclaimer: I wrote this before writing any code, and reading only a little. So the possibility remains open that I am horribly, tragically wrong. ---- Application (twisted.internet.main.Application): The overall container and entry point for your program as a whole. The answer to the question "Uh, okay, now how do I start it?". In addition to starting, it also handles shutdown, typically pickling itself to disk in the process. And yes, that means that when you pickle.load an object from a twisted .spl file, an Application is what you are getting. An Application has a name (first argument to the constructor), a string which it uses in naming logfiles, shutdown pickles, etc. When Applications are running, they typically have at least one Port (see below) listening for connections, as internet..Applications which don't communicate with anyone are less fun than dead puppies. Ports are added with the .addPort() method, and the Application has them startListening as soon as it is run(). - - Port (twisted.internet.tcp.Port): The class of much-debated naming, an open "server port" or "listener port". Constructed of two arguments (port, factory): the first is either a TCP port number or the filename of a unix socket, the second is an instance of a protocol.Factory -- typically a pb.BrokerFactory() So when a Port gets a connection, it has the factory pop out a new Protocol (in this case, a Broker), and hooks it up to the connection with a Transport. - - Broker (twisted.spread.pb.Broker) Typically created by a pb.BrokerFactory, these broker between a connection (from the Port) and a pb.Service. The services available to the broker are those which have been added to the BrokerFactory with its addService method. - - Service (twisted.spread.pb.Service) The service you are providing (XXX: a less vauge, circular description?) is defined as a subclass of pb.Service (ex: web.ResourcePublisher). I expect the common usage is to only have no more than one instance of a given Service class, as it defines the service *as a whole*, and generally does not bother itself with the details of a request. Instead, Services are asked (through the broker) for Perspectives, through the getPerspectiveNamed method. - - Perspective (twisted.spread.pb.Perspective) Well, it's called "Perspective Broker", and that's what all the excitement is about, right? That's probably why my clarity has been dropping as I near it... Let me see if I can explain this. Then someone will have to jump in and tell me if I explained the right thing. The reason the client is asking the server to perform a service is because the server is able to see and do things the client does not have access to. That is, from the client's perspective, these things are not visible, but from the server's perspective, they're perfectly accessible. Enter one Perspective Broker. Through the Perspective Broker, clients may have actions performed from the perspective of an object on the server. These objects are instances of classes descended from pb.Perspective. If a client runs a method .foo() on a reference to such an object, the server will run the method .perspective_foo() on the instance on the server side. XXX: Examples would help loads. Note: Since all commands over the broker happen asynchronously, the client cannot receive return values from a perspective_foo() method. - - Referenced (twisted.spread.pb.Referenced) Since a Perspective object cannot pass data back to the client through return values, how does the client ever learn anything about what it's done through the broker? If the client passes an object that is Referenced through to the perspective, then the perspective on the server side will be able to pass data to methods of the Referenced object. A call to .foo() on the server's side will call .remote_foo() on the object in the client. This works in much the same way as clients calling methods of Perspective objects. ---- Ports get added to Applications (a BrokerFactory is attached to the port) Services get added to BrokerFactories Perspectives are issued by Services ---- How does error notification work? What naming conventions should application authors use? Any other must-have pb classes?

Thank you, kevin, for doing this write-up... I hope this feedback enables you to keep going with it. I'd highly encourage you to write some code though :) On Thu, 2 Aug 2001, Kevin Turner wrote:
Now .tap file...
You may want to add the fact that they'll often have a Delayed as well.
Port (twisted.internet.tcp.Port):
Your description of Ports is fairly accurate.
Broker (twisted.spread.pb.Broker)
Typically created by a pb.BrokerFactory, these broker between a
Or manually instantiated for use with a tcp.Client!
Service (twisted.spread.pb.Service)
The service you are providing (XXX: a less vauge, circular description?)
No, sounds good -- I want to reinforce that these classes are what they sound like :)
Might want to be a little clearer about the service doing the authentication here...
Perspective (twisted.spread.pb.Perspective)
I think it would make sense to explain references first, even though you can't get to them without perspectives (because on the client, you have a reference to a perspective); the notion of translating calls on references into 'special' calls on instances is important for Perspective, Proxied, Referenced, and Cached... Also don't talk so much about "client" and "server" when referring to the perspective; this is objects-to-objects.
Yep.
XXX: Examples would help loads.
# Here's one to get you started. class Foo(pb.Perspective): def perspective_bar(self, baz): print 'received remote method call'
Note: Since all commands over the broker happen asynchronously, the client cannot receive return values from a perspective_foo() method.
Yes it can, actually. If you pass a keyword parameter 'pbcallback', that callback will be invoked on the client when the return value is received. However, you can't get that as a return value from the .foo call on the client (obviously).
Speaking in terms of client and server still doesn't make sense. The server can send Referenced instances to the client too. And the lead-in sentence is wrong anyway :) Additionally, you can pass a reference in to the requestPerspective method now, to provide an analogue for the "client" object that you'd send messages to in many other protocols.
Proxies are issued by returning Proxied instances from Perspective methods (or from Proxied methods) Copies are made [ditto] Copied [ditto] Caches are like copies, but they maintain identity rather than being re-sent each time. (optional)
How does error notification work?
Similiarly to return-value notification. myReference.do(arg,arg,pbcallback=myCallback, pberrback=myErrorCallback) All you get as an argument to the error callback is is a traceback or error message string though.
What naming conventions should application authors use?
Just stick to the Twisted coding standard and you'll be fine.
Any other must-have pb classes?
Copied and Proxied are worth explaining. Reference is crucial. Cached is interesting, but complex and you'll know if you need it. Other things are peripheral. Hope this helps. ______ __ __ _____ _ _ | ____ | \_/ |_____] |_____| |_____| |_____ | | | | @ t w i s t e d m a t r i x . c o m http://twistedmatrix.com/users/glyph

On Fri, Aug 03, 2001 at 01:05:56PM -0500, Glyph Lefkowitz wrote:
Yeah, I noticed that, but left it out for the first pass as it wasn't necessary to get the network connection up and running...
That sounds like an excellent idea. However, it's an area I remain entirely ignorant of...
Well, I've got to have some terms other than "this" and "that" to keep straight what I'm talking about. Would you rather I called them "Alice" and "Bob"? Besides, if we are talking about this in the context of Services, (which we are, as that text isn't general enough to be used as all-purpose docstrings) I would think it makes sense to refer to one side as a server, does it not?
And "The callback will be called with a single argument, the return value."
This means including the pberrback parameter on every call? What happens if you don't? Is there a catch-all error handler you can set? Why the sometimes strings/sometimes traceback inconsistancy?
What naming conventions should application authors use?
Just stick to the Twisted coding standard and you'll be fine.
CodingStandard.html does not have the adverb prefixes like perspective_, remote_, etc.
Cached is interesting, but complex and you'll know if you need it.
Yeah, """It's like a Copy, but way, *WAY* worse!"""
I'd highly encourage you to write some code though :)
ah'm workin on that =)

Ok, my mind is shutting down, but I want to throw something at the list tonight so I don't forget what I was thinking on. Now, I know you've put a lot of effort into naming things so you can say "it is what it says it is", but no matter how common you think the words you use are, there's going to be *someone* who isn't familiar. That's why I was trying to give a non-circular definition of "Service" the other day. And today, The Word Of The Day is: Serializable! It might even be kinda a real word, but it's sure not one in my vocabulary. So while it appears that the docstring for Perspective goes to great length to make a very reasoned explanation, I'm having a difficult time deciphering it. twisted.spread.pb.Perspective.__doc__ reads:
See, I *think* that answers the question I was going to ask, "How is a Perspective different than a Referenced object," but I don't know how to read it. In addition to uncomprehension through non-deep-grokking of the lingo, the phrase "I can *see* your perspective, but I can't see *from* your perspective," is a riddle I can't say I have, uh, untwisted. Ok, hopefully that's enough to get you talking a bit. I'm going to go have myself a sleep. ...the thing about writing code is, some of us have to understand what tools and components are available to us *before* we can do so. ;) -- The moon is full (99.96%), 14.6 days old, phase: 0.493524 Angular diameter as seen from the earth: 0.4926 degrees.

On Sat, 4 Aug 2001, Kevin Turner wrote:
And today, The Word Of The Day is: Serializable!
Serializable, Perspective, and a few other things are now documented in CVS. Let me know if they answer some of your questions, and what you think I should document next. ______ __ __ _____ _ _ | ____ | \_/ |_____] |_____| |_____| |_____ | | | | @ t w i s t e d m a t r i x . c o m http://twistedmatrix.com/users/glyph

Abstract: Trace the construction of a PB-using application from the top, to the side, to the inside-out. [XXX: Add "why the gleep you should actually care about PB introduction-hook here."] Disclaimer: I wrote this before writing any code, and reading only a little. So the possibility remains open that I am horribly, tragically wrong. ---- Application (twisted.internet.main.Application): The overall container and entry point for your program as a whole. The answer to the question "Uh, okay, now how do I start it?". In addition to starting, it also handles shutdown, typically pickling itself to disk in the process. And yes, that means that when you pickle.load an object from a twisted .spl file, an Application is what you are getting. An Application has a name (first argument to the constructor), a string which it uses in naming logfiles, shutdown pickles, etc. When Applications are running, they typically have at least one Port (see below) listening for connections, as internet..Applications which don't communicate with anyone are less fun than dead puppies. Ports are added with the .addPort() method, and the Application has them startListening as soon as it is run(). - - Port (twisted.internet.tcp.Port): The class of much-debated naming, an open "server port" or "listener port". Constructed of two arguments (port, factory): the first is either a TCP port number or the filename of a unix socket, the second is an instance of a protocol.Factory -- typically a pb.BrokerFactory() So when a Port gets a connection, it has the factory pop out a new Protocol (in this case, a Broker), and hooks it up to the connection with a Transport. - - Broker (twisted.spread.pb.Broker) Typically created by a pb.BrokerFactory, these broker between a connection (from the Port) and a pb.Service. The services available to the broker are those which have been added to the BrokerFactory with its addService method. - - Service (twisted.spread.pb.Service) The service you are providing (XXX: a less vauge, circular description?) is defined as a subclass of pb.Service (ex: web.ResourcePublisher). I expect the common usage is to only have no more than one instance of a given Service class, as it defines the service *as a whole*, and generally does not bother itself with the details of a request. Instead, Services are asked (through the broker) for Perspectives, through the getPerspectiveNamed method. - - Perspective (twisted.spread.pb.Perspective) Well, it's called "Perspective Broker", and that's what all the excitement is about, right? That's probably why my clarity has been dropping as I near it... Let me see if I can explain this. Then someone will have to jump in and tell me if I explained the right thing. The reason the client is asking the server to perform a service is because the server is able to see and do things the client does not have access to. That is, from the client's perspective, these things are not visible, but from the server's perspective, they're perfectly accessible. Enter one Perspective Broker. Through the Perspective Broker, clients may have actions performed from the perspective of an object on the server. These objects are instances of classes descended from pb.Perspective. If a client runs a method .foo() on a reference to such an object, the server will run the method .perspective_foo() on the instance on the server side. XXX: Examples would help loads. Note: Since all commands over the broker happen asynchronously, the client cannot receive return values from a perspective_foo() method. - - Referenced (twisted.spread.pb.Referenced) Since a Perspective object cannot pass data back to the client through return values, how does the client ever learn anything about what it's done through the broker? If the client passes an object that is Referenced through to the perspective, then the perspective on the server side will be able to pass data to methods of the Referenced object. A call to .foo() on the server's side will call .remote_foo() on the object in the client. This works in much the same way as clients calling methods of Perspective objects. ---- Ports get added to Applications (a BrokerFactory is attached to the port) Services get added to BrokerFactories Perspectives are issued by Services ---- How does error notification work? What naming conventions should application authors use? Any other must-have pb classes?

Thank you, kevin, for doing this write-up... I hope this feedback enables you to keep going with it. I'd highly encourage you to write some code though :) On Thu, 2 Aug 2001, Kevin Turner wrote:
Now .tap file...
You may want to add the fact that they'll often have a Delayed as well.
Port (twisted.internet.tcp.Port):
Your description of Ports is fairly accurate.
Broker (twisted.spread.pb.Broker)
Typically created by a pb.BrokerFactory, these broker between a
Or manually instantiated for use with a tcp.Client!
Service (twisted.spread.pb.Service)
The service you are providing (XXX: a less vauge, circular description?)
No, sounds good -- I want to reinforce that these classes are what they sound like :)
Might want to be a little clearer about the service doing the authentication here...
Perspective (twisted.spread.pb.Perspective)
I think it would make sense to explain references first, even though you can't get to them without perspectives (because on the client, you have a reference to a perspective); the notion of translating calls on references into 'special' calls on instances is important for Perspective, Proxied, Referenced, and Cached... Also don't talk so much about "client" and "server" when referring to the perspective; this is objects-to-objects.
Yep.
XXX: Examples would help loads.
# Here's one to get you started. class Foo(pb.Perspective): def perspective_bar(self, baz): print 'received remote method call'
Note: Since all commands over the broker happen asynchronously, the client cannot receive return values from a perspective_foo() method.
Yes it can, actually. If you pass a keyword parameter 'pbcallback', that callback will be invoked on the client when the return value is received. However, you can't get that as a return value from the .foo call on the client (obviously).
Speaking in terms of client and server still doesn't make sense. The server can send Referenced instances to the client too. And the lead-in sentence is wrong anyway :) Additionally, you can pass a reference in to the requestPerspective method now, to provide an analogue for the "client" object that you'd send messages to in many other protocols.
Proxies are issued by returning Proxied instances from Perspective methods (or from Proxied methods) Copies are made [ditto] Copied [ditto] Caches are like copies, but they maintain identity rather than being re-sent each time. (optional)
How does error notification work?
Similiarly to return-value notification. myReference.do(arg,arg,pbcallback=myCallback, pberrback=myErrorCallback) All you get as an argument to the error callback is is a traceback or error message string though.
What naming conventions should application authors use?
Just stick to the Twisted coding standard and you'll be fine.
Any other must-have pb classes?
Copied and Proxied are worth explaining. Reference is crucial. Cached is interesting, but complex and you'll know if you need it. Other things are peripheral. Hope this helps. ______ __ __ _____ _ _ | ____ | \_/ |_____] |_____| |_____| |_____ | | | | @ t w i s t e d m a t r i x . c o m http://twistedmatrix.com/users/glyph

On Fri, Aug 03, 2001 at 01:05:56PM -0500, Glyph Lefkowitz wrote:
Yeah, I noticed that, but left it out for the first pass as it wasn't necessary to get the network connection up and running...
That sounds like an excellent idea. However, it's an area I remain entirely ignorant of...
Well, I've got to have some terms other than "this" and "that" to keep straight what I'm talking about. Would you rather I called them "Alice" and "Bob"? Besides, if we are talking about this in the context of Services, (which we are, as that text isn't general enough to be used as all-purpose docstrings) I would think it makes sense to refer to one side as a server, does it not?
And "The callback will be called with a single argument, the return value."
This means including the pberrback parameter on every call? What happens if you don't? Is there a catch-all error handler you can set? Why the sometimes strings/sometimes traceback inconsistancy?
What naming conventions should application authors use?
Just stick to the Twisted coding standard and you'll be fine.
CodingStandard.html does not have the adverb prefixes like perspective_, remote_, etc.
Cached is interesting, but complex and you'll know if you need it.
Yeah, """It's like a Copy, but way, *WAY* worse!"""
I'd highly encourage you to write some code though :)
ah'm workin on that =)

Ok, my mind is shutting down, but I want to throw something at the list tonight so I don't forget what I was thinking on. Now, I know you've put a lot of effort into naming things so you can say "it is what it says it is", but no matter how common you think the words you use are, there's going to be *someone* who isn't familiar. That's why I was trying to give a non-circular definition of "Service" the other day. And today, The Word Of The Day is: Serializable! It might even be kinda a real word, but it's sure not one in my vocabulary. So while it appears that the docstring for Perspective goes to great length to make a very reasoned explanation, I'm having a difficult time deciphering it. twisted.spread.pb.Perspective.__doc__ reads:
See, I *think* that answers the question I was going to ask, "How is a Perspective different than a Referenced object," but I don't know how to read it. In addition to uncomprehension through non-deep-grokking of the lingo, the phrase "I can *see* your perspective, but I can't see *from* your perspective," is a riddle I can't say I have, uh, untwisted. Ok, hopefully that's enough to get you talking a bit. I'm going to go have myself a sleep. ...the thing about writing code is, some of us have to understand what tools and components are available to us *before* we can do so. ;) -- The moon is full (99.96%), 14.6 days old, phase: 0.493524 Angular diameter as seen from the earth: 0.4926 degrees.

On Sat, 4 Aug 2001, Kevin Turner wrote:
And today, The Word Of The Day is: Serializable!
Serializable, Perspective, and a few other things are now documented in CVS. Let me know if they answer some of your questions, and what you think I should document next. ______ __ __ _____ _ _ | ____ | \_/ |_____] |_____| |_____| |_____ | | | | @ t w i s t e d m a t r i x . c o m http://twistedmatrix.com/users/glyph
participants (2)
-
Glyph Lefkowitz
-
Kevin Turner