Initial import to Tizen
[profile/ivi/python-twisted.git] / doc / historic / 2002 / ipc10 / twisted-network-framework / errata.html
1 <?xml version="1.0"?>
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
3     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
4
5 <html xmlns="http://www.w3.org/1999/xhtml">
6   <head>
7     <title>The World of Software is a World of Constant
8     Change</title>
9   </head>
10
11   <body>
12     <p><em><strong>Note:</strong> This document is relevant for the
13     version of Twisted that was current at <a
14     href="http://www.python10.com">IPC10</a>. It has since been
15     superseded by many changes to the Python API. It is remaining
16     unchanged for historical reasons, but please refer to
17     documentation for the specific system you are looking for and
18     not these papers for current information.</em></p>
19
20     <h1>The World of Software is a World of Constant Change</h1>
21
22     <p>Twisted has undergone several major revisions since Moshe
23     Zadka and I wrote the <a href="ipc10paper.html">"The Twisted
24     Network Framework"</a>. Most of these changes have not deviated
25     from the central vision of the framework, but almost all of the
26     code listings have been re-visited and enhanced in some
27     way.</p>
28
29     <p>So, while the paper was correct at the time that it was
30     originally written, a few things have changed which have
31     invalidated portions of it.</p>
32
33     <p>Most significant is the fact that almost all methods which
34     pass callbacks of some kind have been changed to take no
35     callback or error-callback arguments, and instead return an
36     instance of a <code
37     class="API">twisted.python.defer.Deferred</code>. This means
38     that an asynchronous function can be easily identified visually
39     because it will be of the form: <code
40     class="python">async_obj.asyncMethod("foo")<b>.addCallbacks(succeded,
41     failed)</b></code>. There is also a utility method <code
42     class="python">addCallback</code> which makes it more
43     convenient to pass additional arguments to a callback function
44     and omit special-case error handling.</p>
45
46     <p>While it is still backwards compatible, <code
47     class="API">twisted.internet.passport</code> has been re-named
48     to <code class="API">twisted.cred</code>, and the various
49     classes in it have been split out into submodules of that
50     package, and the various remote-object superclasses have been
51     moved out of twisted.spread.pb and put into
52     twisted.spread.flavors.</p>
53
54     <p><code class="python">Application.listenOn</code> has been
55     replaced with the more descripively named <code
56     class="python">Application.listenTCP</code>, <code
57     class="python">Application.listenUDP</code>, and <code
58     class="python">Application.listenSSL</code>.</p>
59
60     <p><code class="API">twisted.web.widgets</code> has progressed
61     quite far since the paper was written! One description
62     specifically given in the paper is no longer correct:</p>
63
64     <blockquote>
65       The namespace for evaluating the template expressions is
66       obtained by scanning the class hierarchy for attributes, and
67       getting each of those attributes from the current instance.
68       This means that all methods will be bound methods, so
69       indicating "self" explicitly is not required. While it is
70       possible to override the method for creating namespaces,
71       using this default has the effect of associating all
72       presentation code for a particular widget in one class, along
73       with its template. If one is working with a non-programmer
74       designer, and the template is in an external file, it is
75       always very clear to the designer what functionality is
76       available to them in any given scope, because there is a list
77       of available methods for any given class.
78     </blockquote>
79 <p>This is still possible to avoid breakages in old code, but
80 after some experimentation, it became clear that simply passing
81     <code class="python">self</code> was an easier method for
82     creating the namespace, both for designers and programmers.</p>
83     <p>In addition, since the advent of Zope3, interoperability
84     with Zope has become increasingly interesting possibility for
85     the Twisted development team, since it would be desirable if
86     Twisted could use their excellent strategy for
87     content-management, while still maintaining Twisted's
88     advantages in the arena of multi-protocol servers. Of
89     particular interest has been Zope Presentation Templates, since
90     they seem to be a truly robust solution for keeping design
91     discrete from code, compatible with the event-based method in
92     which twisted.web.widgets processes web requests. <code
93     class="API">twisted.web.widgets.ZopePresentationTemplate</code>
94     may be opening soon in a theatre near you!</p>
95
96     <p>The following code examples are corrected or modernized
97     versions of the ones that appear in the paper.</p>
98
99     <blockquote>
100       Listing 9: A remotely accessible object and accompanying call
101       
102 <pre class="python">
103 # Server Side
104 class MyObject(pb.Referenceable):
105     def remote_doIt(self):
106         return "did it"
107
108 # Client Side
109     ...
110     def myCallback(result):
111         print result # result will be 'did it'
112     def myErrback(stacktrace):
113         print 'oh no, mr. bill!'
114         print stacktrace
115     myRemoteReference.doIt().addCallbacks(myCallback,
116                                           myErrback)
117 </pre>
118     </blockquote>
119
120     <blockquote>
121       Listing 10: An object responding to its calling perspective 
122 <pre class="python">
123 # Server Side
124 class Greeter(pb.Viewable):
125     def view_greet(self, actor):
126         return "Hello %s!\n" % actor.perspectiveName
127
128 # Client Side
129     ...
130     remoteGreeter.greet().addCallback(sys.stdout.write)
131     ...
132 </pre>
133     </blockquote>
134      
135
136     <blockquote>
137       Listing 12: A client for Echoer objects. 
138 <pre class="python">
139 from twisted.spread import pb
140 from twisted.internet import main
141 def gotObject(object):
142     print "got object:",object
143     object.echo("hello network".addCallback(gotEcho)
144 def gotEcho(echo):
145     print 'server echoed:',echo
146     main.shutDown()
147 def gotNoObject(reason):
148     print "no object:",reason
149     main.shutDown()
150 pb.getObjectAt("localhost", 8789, gotObject, gotNoObject, 30)
151 main.run()
152 </pre>
153     </blockquote>
154
155     <blockquote>
156       Listing 13: A PB server using twisted's "passport"
157       authentication. 
158 <pre class="python">
159 from twisted.spread import pb
160 from twisted.internet import main
161 class SimplePerspective(pb.Perspective):
162     def perspective_echo(self, text):
163         print 'echoing',text
164         return text
165 class SimpleService(pb.Service):
166     def getPerspectiveNamed(self, name):
167         return SimplePerspective(name, self)
168 if __name__ == '__main__':
169     import pbecho
170     app = main.Application("pbecho")
171     pbecho.SimpleService("pbecho",app).getPerspectiveNamed("guest").makeIdentity("guest")
172     app.listenTCP(pb.portno, pb.BrokerFactory(pb.AuthRoot(app)))
173     app.save("start")
174 </pre>
175     </blockquote>
176
177     <blockquote>
178       Listing 14: Connecting to an Authorized Service 
179 <pre class="python">
180 from twisted.spread import pb
181 from twisted.internet import main
182 def success(message):
183     print "Message received:",message
184     main.shutDown()
185 def failure(error):
186     print "Failure...",error
187     main.shutDown()
188 def connected(perspective):
189     perspective.echo("hello world").addCallbacks(success, failure)
190     print "connected."
191
192 pb.connect("localhost", pb.portno, "guest", "guest",
193            "pbecho", "guest", 30).addCallbacks(connected,
194                                                failure)
195 main.run()
196 </pre>
197     </blockquote>
198
199     <blockquote>
200       Listing 15: A Twisted GUI application 
201 <pre class="python">
202 from twisted.internet import main, ingtkernet
203 from twisted.spread.ui import gtkutil
204 import gtk
205 ingtkernet.install()
206 class EchoClient:
207     def __init__(self, echoer):
208         l.hide()
209         self.echoer = echoer
210         w = gtk.GtkWindow(gtk.WINDOW_TOPLEVEL)
211         vb = gtk.GtkVBox(); b = gtk.GtkButton("Echo:")
212         self.entry = gtk.GtkEntry(); self.outry = gtk.GtkEntry()
213         w.add(vb)
214         map(vb.add, [b, self.entry, self.outry])
215         b.connect('clicked', self.clicked)
216         w.connect('destroy', gtk.mainquit)
217         w.show_all()
218     def clicked(self, b):
219         txt = self.entry.get_text()
220         self.entry.set_text("")
221         self.echoer.echo(txt).addCallback(self.outry.set_text)
222 l = gtkutil.Login(EchoClient, None, initialService="pbecho")
223 l.show_all()
224 gtk.mainloop()
225 </pre>
226     </blockquote>
227
228     <blockquote>
229       Listing 16: an event-based web widget. 
230 <pre class="python">
231 from twisted.spread import pb
232 from twisted.python import defer
233 from twisted.web import widgets
234 class EchoDisplay(widgets.Gadget, widgets.Presentation):
235     template = """&lt;H1&gt;Welcome to my widget, displaying %%%%echotext%%%%.&lt;/h1&gt;
236     &lt;p&gt;Here it is: %%%%getEchoPerspective()%%%%&lt;/p&gt;"""
237     echotext = 'hello web!'
238     def getEchoPerspective(self):
239         return ['&lt;b&gt;',
240             pb.connect("localhost", pb.portno,
241                    "guest", "guest", "pbecho", "guest", 1).
242                 addCallbacks(self.makeListOf, self.formatTraceback)
243             ,'&lt;/b&gt;']
244     def makeListOf(self, echoer):
245         return [echoer.echo(self.echotext).addCallback(lambda x: [x])]
246 if __name__ == "__main__":
247     from twisted.web import server
248     from twisted.internet import main
249     a = main.Application("pbweb")
250     a.listenTCP(8080, server.Site(EchoDisplay()))
251     a.run()
252 </pre>
253     </blockquote>
254   </body>
255 </html>
256