Ticket #4569: tutorial2.xhtml.patch

File tutorial2.xhtml.patch, 18.1 KB (added by jdb, 4 years ago)
  • doc/core/howto/tutorial/intro.xhtml

    diff -bu doc/core/howto/tutorial/intro.xhtml doc/core/howto/tutorial/intro.xhtml
     
    2727No Plan. 
    2828</pre> 
    2929 
    30 <p>If the target computer does not have the <code>fingerd</code> <a 
    31 href="../glossary.xhtml#Daemon">daemon</a> running you'll get a "Connection 
    32 Refused" error. Paranoid sysadmins keep <code>fingerd</code> off or limit the 
    33 output to hinder crackers and harassers. The above format is the standard 
    34 <code>fingerd</code> default, but an alternate implementation can output 
    35 anything it wants, such as automated responsibility status for everyone in an 
    36 organization. You can also define pseudo "users", which are essentially 
    37 keywords.</p> 
     30<p>If the target computer does not have 
     31the <code>fingerd</code> <a href="../glossary.xhtml#Daemon">daemon</a> 
     32running you'll get a "Connection Refused" error. Paranoid sysadmins 
     33keep <code>fingerd</code> off or limit the output to hinder crackers 
     34and harassers. The above format is the standard <code>fingerd</code> 
     35default, but an alternate implementation can output anything it wants, 
     36such as automated responsibility status for everyone in an 
     37organization. You can also define pseudo "users", which are 
     38essentially keywords.</p> 
    3839 
    3940<p>This portion of the tutorial makes use of factories and protocols as 
    4041introduced in the <a href="../servers.xhtml">Writing a TCP Server howto</a> and 
     
    7576over and over again, responding to network events and making scheduled calls to 
    7677code.</p> 
    7778 
    78 <p>Note that there are actually several different reactors to choose from; 
    79 <code>from twisted.internet import reactor</code> returns the current reactor. 
    80 If you haven't chosen a reactor class yet, it automatically chooses the 
    81 default.  See the <a href="../reactor-basics.xhtml">Reactor Basics HOWTO</a> 
    82 for more information.</p> 
     79<p>Note that there are actually several different reactors to choose 
     80from; <code>from twisted.internet import reactor</code> returns the 
     81current reactor.  If you haven't chosen a reactor class yet, it 
     82automatically chooses the default.  See 
     83the <a href="../reactor-basics.xhtml">Reactor Basics HOWTO</a> for 
     84more information.</p> 
    8385 
    8486<h2>Do Nothing</h2> 
    8587 
     
    189191other operations in the meantime, and waits for some signal that data is ready 
    190192to be processed before returning to that process.</p> 
    191193 
    192 <p>In brief, the code in <code>FingerFactory</code> above creates a Deferred, 
    193 to which we start to attach <em>callbacks</em>.  The deferred action in 
    194 <code>FingerFactory</code> is actually a fast-running expression consisting of 
    195 one dictionary method, <code>get</code>. Since this action can execute without 
    196 delay, <code>FingerFactory.getUser</code> uses <code>defer.succeed</code> to 
    197 create a <code>Deferred</code> which already has a result, meaning its return 
    198 value will be passed immediately to the first callback function, which turns out 
    199 to be <code>FingerProtocol.writeResponse</code>.  We've also defined an 
    200 <em>errback</em> (appropriately named <code>FingerProtocol.onError</code>) that 
    201 will be called instead of <code>writeResponse</code> if something goes 
    202 wrong.</p> 
     194<p>In brief, the code in <code>FingerFactory</code> above creates a 
     195Deferred, to which we start to attach <em>callbacks</em>.  The 
     196deferred action in <code>FingerFactory</code> is actually a 
     197fast-running expression consisting of one dictionary 
     198method, <code>get</code>. Since this action can execute without 
     199delay, <code>FingerFactory.getUser</code> 
     200uses <code>defer.succeed</code> to create a Deferred which already has 
     201a result, meaning its return value will be passed immediately to the 
     202first callback function, which turns out to 
     203be <code>FingerProtocol.writeResponse</code>.  We've also defined 
     204an <em>errback</em> (appropriately 
     205named <code>FingerProtocol.onError</code>) that will be called instead 
     206of <code>writeResponse</code> if something goes wrong.</p> 
    203207 
    204208<h2>Run 'finger' Locally</h2> 
    205209 
    206210<a href="listings/finger/finger09.py" class="py-listing">finger09.py</a> 
    207211 
    208 <p>This example also makes use of a <code>Deferred</code>. 
    209 <code>twisted.internet.utils.getProcessOutput</code> is a non-blocking version 
    210 of Python's <code>commands.getoutput</code>: it runs a shell command 
    211 (<code>finger</code>, in this case) and captures its standard output.  However, 
    212 <code>getProcessOutput</code> returns a <code>Deferred</code> instead of the 
    213 output itself.  Since <code>FingerProtocol.lineReceived</code> is already 
    214 expecting a Deferred to be returned by <code>getUser</code>, it doesn't need to 
    215 be changed, and it returns the standard output as the finger result.</p> 
     212<p>This example also makes use of a 
     213Deferred. <code>twisted.internet.utils.getProcessOutput</code> is a 
     214non-blocking version of Python's <code>commands.getoutput</code>: it 
     215runs a shell command (<code>finger</code>, in this case) and captures 
     216its standard output.  However, <code>getProcessOutput</code> returns a 
     217Deferred instead of the output itself. 
     218Since <code>FingerProtocol.lineReceived</code> is already expecting a 
     219Deferred to be returned by <code>getUser</code>, it doesn't need to be 
     220changed, and it returns the standard output as the finger result.</p> 
    216221 
    217222<p>Note that in this case the shell's built-in <code>finger</code> command is 
    218223simply run with whatever arguments it is given. This is probably insecure, so 
     
    222227 
    223228<h2>Read Status from the Web</h2> 
    224229 
    225 <p>The web. That invention which has infiltrated homes around the world finally 
    226 gets through to our invention. In this case we use the built-in Twisted web 
    227 client via <code>twisted.web.client.getPage</code>, a non-blocking version of 
    228 Python's <code>urllib2.urlopen(URL).read()</code>.  Like 
    229 <code>getProcessOutput</code> it returns a <code>Deferred</code> which will be 
    230 called back with a string, and can thus be used as a drop-in replacement.</p> 
     230<p>The web. That invention which has infiltrated homes around the 
     231world finally gets through to our invention. In this case we use the 
     232built-in Twisted web client 
     233via <code>twisted.web.client.getPage</code>, a non-blocking version of 
     234Python's <code>urllib2.urlopen(URL).read()</code>. 
     235Like <code>getProcessOutput</code> it returns a Deferred which will be 
     236called back with a string, and can thus be used as a drop-in 
     237replacement.</p> 
    231238 
    232239<p>Thus, we have examples of three different database back-ends, none of which 
    233240change the protocol class. In fact, we will not have to change the protocol 
     
    279286 
    280287<a href="listings/finger/finger11.tac" class="py-listing">finger11.tac</a> 
    281288 
    282 <p>Instead of using <code>reactor.listenTCP</code> as in the above examples, 
    283 here we are using its application-aware counterpart, 
    284 <code>internet.TCPServer</code>.  Notice that when it is instantiated, the 
    285 application object itself does not reference either the protocol or the factory. 
    286 Any services (such as <code>TCPServer</code>) which have the application as 
    287 their parent will be started when the application is started by twistd.  The 
    288 application object is more useful for returning an object that supports the 
    289 <code class="API" 
     289 
     290<p>Instead of using <code>reactor.listenTCP</code> as in the above 
     291examples, here we are using its application-aware 
     292counterpart, <code>internet.TCPServer</code>.  Notice that when it is 
     293instantiated, the application object itself does not reference either 
     294the protocol or the factory.  Any services (such as TCPServer) which 
     295have the application as their parent will be started when the 
     296application is started by twistd.  The application object is more 
     297useful for returning an object that supports the <code class="API" 
    290298base="twisted.application.service">IService</code>, <code class="API" 
    291299base="twisted.application.service">IServiceCollection</code>, <code class="API" 
    292 base="twisted.application.service">IProcess</code>, and <code class="API" 
    293 base="twisted.persisted">sob.IPersistable</code> interfaces with the given 
    294 parameters; we'll be seeing these in the next part of the tutorial. As the 
    295 parent of the <code>TCPServer</code> we opened, the application lets us manage 
    296 the <code>TCPServer</code>.</p> 
     300base="twisted.application.service">IProcess</code>, 
     301and <code class="API" base="twisted.persisted">sob.IPersistable</code> 
     302interfaces with the given parameters; we'll be seeing these in the 
     303next part of the tutorial. As the parent of the TCPServer we opened, 
     304the application lets us manage the TCPServer.</p> 
    297305 
    298306<p>With the daemon running on the standard finger port, you can test it with 
    299307the standard finger command: <code>finger moshez</code>.</p> 
  • doc/core/howto/tutorial/protocol.xhtml

    Common subdirectories: doc/core/howto/tutorial/listings and doc/core/howto/tutorial/listings
    diff -bu doc/core/howto/tutorial/protocol.xhtml doc/core/howto/tutorial/protocol.xhtml
     
    4040 
    4141<a href="listings/finger/finger12.tac" class="py-listing">finger12.tac</a> 
    4242 
    43 <p>This program has two protocol-factory-TCPServer pairs, which are both child 
    44 services of the application.  Specifically, the 
    45 <code base="API" class="twisted.application.service.Service">setServiceParent</code> 
    46 method is used to define the two TCPServer services as children of 
    47 <code>application</code>, which implements 
    48 <code base="API" class="twisted.application.servce">IServiceCollection</code>. 
    49 Both services are thus started with the application.</p> 
     43<p>This program has two protocol-factory-TCPServer pairs, which are 
     44both child services of the application.  Specifically, 
     45the <code base="API" 
     46class="twisted.application.service.Service">setServiceParent</code> 
     47method is used to define the two TCPServer services as children 
     48of <code>application</code>, which implements <code base="API" 
     49class="twisted.application.servce">IServiceCollection</code>.  Both 
     50services are thus started with the application.</p> 
     51 
    5052 
    5153<h2>Use Services to Make Dependencies Sane</h2> 
    5254 
     
    5860class with methods that will create factories on the fly. The service 
    5961also contains methods the factories will depend on.</p> 
    6062 
    61 <p>The factory-creation methods, <code>getFingerFactory</code> and 
    62 <code>getFingerSetterFactory</code>, follow this pattern:</p> 
     63<p>The factory-creation methods, <code>getFingerFactory</code> 
     64and <code>getFingerSetterFactory</code>, follow this pattern:</p> 
    6365 
    6466<ol> 
    6567 
    66 <li>Instantiate a generic server factory, 
    67 <code>twisted.internet.protocol.ServerFactory</code>.</li> 
     68<li>Instantiate a generic server 
     69factory, <code>twisted.internet.protocol.ServerFactory</code>.</li> 
    6870 
    6971<li>Set the protocol class, just like our factory class would have.</li> 
    7072 
    7173<li>Copy a service method to the factory as a function attribute.  The 
    72 function won't have access to the factory's <code>self</code>, but that's OK 
    73 because as a bound method it has access to the service's <code>self</code>, 
    74 which is what it needs.  For <code>getUser</code>, a custom method defined in 
    75 the service gets copied.  For <code>setUser</code>, a standard method of the 
    76 <code>users</code> dictionary is copied.</li> 
     74function won't have access to the factory's <code>self</code>, but 
     75that's OK because as a bound method it has access to the 
     76service's <code>self</code>, which is what it needs. 
     77For <code>getUser</code>, a custom method defined in the service gets 
     78copied.  For <code>setUser</code>, a standard method of 
     79the <code>users</code> dictionary is copied.</li> 
     80 
    7781 
    7882</ol> 
    7983 
     
    8286none of our protocol classes had to be changed, and neither will have to 
    8387change until the end of the tutorial.</p> 
    8488 
    85 <p>As an application 
    86 <code class="API" base="twisted.application.service">Service</code> , this new 
    87 finger service implements the 
    88 <code class="API" base="twisted.application.service">IService</code> interface 
    89 and can be started and stopped in a standardized manner.  We'll make use of 
     89<p>As an application <code class="API" 
     90base="twisted.application.service">service</code> , this new finger 
     91service implements the <code class="API" 
     92base="twisted.application.service">IService</code> interface and can 
     93be started and stopped in a standardized manner.  We'll make use of 
    9094this in the next example.</p> 
    9195 
    9296<a href="listings/finger/finger13.tac" class="py-listing">finger13.tac</a> 
     
    104108 
    105109<a href="listings/finger/finger14.tac" class="py-listing">finger14.tac</a> 
    106110 
    107 <p>Since this version is reading data from a file (and refreshing the data every 
    108 30 seconds), there is no <code>FingerSetterFactory</code> and thus nothing 
    109 listening on port 1079.</p> 
    110  
    111 <p>Here we override the standard 
    112 <code class="API" base="twisted.application.service.Service">startService</code> 
    113 and 
    114 <code class="API" base="twisted.application.service.Service">stopService</code> 
    115 hooks in the Finger service, which is set up as a child service of 
    116 the application in the last line of the code. <code>startService</code> calls 
    117 <code>_read</code>, the function responsible for reading the data; 
    118 <code>reactor.callLater</code> is then used to schedule it to run again after 
    119 thirty seconds every time it is called. <code>reactor.callLater</code> returns 
    120 an object that lets us cancel the scheduled run in <code>stopService</code> 
    121 using its <code>cancel</code> method.</p> 
     111<p>Since this verison is reading data from a file (and refreshing the data  
     112every 30 seconds), there is no <code>FingerSetterFactory</code> and thus  
     113nothing listening on port 1079.</p> 
     114 
     115<p>Here we override the standard <code class="API" 
     116base="twisted.application.service.Service">startService</code> 
     117and <code class="API" 
     118base="twisted.application.service.Service">stopService</code> hooks in 
     119the Finger service, which is set up as a child service of the 
     120application in the last line of the code. <code>startService</code> 
     121calls <code>_read</code>, the function responsible for reading the 
     122data; <code>reactor.callLater</code> is then used to schedule it to 
     123run again after thirty seconds every time it is 
     124called. <code>reactor.callLater</code> returns an object that lets us 
     125cancel the scheduled run in <code>stopService</code> using 
     126its <code>cancel</code> method.</p> 
    122127 
    123128<h2>Announce on Web, Too</h2> 
    124129 
    125 <p>The same kind of service can also produce things useful for 
    126 other protocols. For example, in twisted.web, the factory 
    127 itself (<code base="API" class="twisted.web.server">Site</code>) is almost 
    128 never subclassed &mdash; instead, it is given a resource, which represents the tree 
    129 of resources available via URLs. That hierarchy is navigated by 
    130 <code base="API" class="twisted.web.server">Site</code> and overriding it 
    131 dynamically is possible with 
    132 <code base="API" class="twisted.web.resource.Resource">getChild</code>.</p> 
     130<p>The same kind of service can also produce things useful for other 
     131protocols. For example, in twisted.web, the factory itself 
     132(<code base="API" class="twisted.web.server">Site</code>) is almost 
     133never subclassed &mdash; instead, it is given a resource, which 
     134represents the tree of resources available via URLs. That hierarchy is 
     135navigated by <code base="API" class="twisted.web.server">Site</code> 
     136and overriding it dynamically is possible with <code base="API" 
     137class="twisted.web.resource.Resource">getChild</code>.</p> 
    133138 
    134139<p>To integrate this into the Finger application (just because we can), we set 
    135140up a new TCPServer that calls the <code base="API" 
     
    153158 
    154159<a href="listings/finger/finger16.tac" class="py-listing">finger16.tac</a> 
    155160 
    156 <p><code>FingerService</code> now has another new function, 
    157 <code>getIRCbot</code>, which returns the 
    158 <code>ReconnectingClientFactory</code>.  This factory in turn will instantiate 
    159 the <code>IRCReplyBot</code> protocol.  The IRCBot is configured in the last 
    160 line to connect to <code>irc.freenode.org</code> with a nickname of 
    161 <code>fingerbot</code>.</p> 
    162  
    163 <p>By overriding <code>irc.IRCClient.connectionMade</code>, 
    164 <code>IRCReplyBot</code> can access the <code>nickname</code> attribute of the 
    165 factory that instantiated it.</p> 
     161<p><code>FingerService</code> now has another new 
     162function, <code>getIRCbot</code>, which returns 
     163the <code>ReconnectingClientFactory</code>.  This factory in turn will 
     164instantiate the <code>IRCReplyBot</code> protocol.  The IRCBot is 
     165configured in the last line to connect 
     166to <code>irc.freenode.org</code> with a nickname 
     167of <code>fingerbot</code>.</p> 
     168 
     169<p>By 
     170overriding <code>irc.IRCClient.connectionMade</code>, <code>IRCReplyBot</code> 
     171can access the <code>nickname</code> attribute of the factory that 
     172instantiated it.</p> 
    166173 
    167174<h2>Add XML-RPC Support</h2> 
    168175 
  • doc/core/howto/tutorial/web.xhtml

    Only in doc/core/howto/tutorial: .svn
    diff -bu doc/core/howto/tutorial/web.xhtml doc/core/howto/tutorial/web.xhtml
     
    1313<p> This is the sixth part of the Twisted tutorial <a 
    1414href="index.xhtml">Twisted from Scratch, or The Evolution of Finger</a>.</p> 
    1515 
    16 <p>In this part, we demonstrate adding a web frontend using simple <code 
    17 class="API">twisted.web.resource.Resource</code> objects: <code 
    18 class="python">UserStatusTree</code>, which will produce a listing of all 
    19 users at the base URL (<code>/</code>) of our site; <code 
    20 class="python">UserStatus</code>, which gives the status of each user at the 
    21 location <code>/username</code>; and <code class="python">UserStatusXR</code>, 
    22 which exposes an XMLRPC interface to <code class="python">getUser</code> and 
    23 <code class="python">getUsers</code> functions at the URL <code>/RPC2</code>.</p> 
     16<p>In this part, we demonstrate adding a web frontend using 
     17simple <code class="API">twisted.web.resource.Resource</code> 
     18objects: <code class="python">UserStatusTree</code>, which will 
     19produce a listing of all users at the base URL (<code>/</code>) of our 
     20site; <code class="python">UserStatus</code>, which gives the status 
     21of each user at the locaton <code>/username</code>; 
     22and <code class="python">UserStatusXR</code>, which exposes an XMLRPC 
     23interface to <code class="python">getUser</code> 
     24and <code class="python">getUsers</code> functions at the 
     25URL <code>/RPC2</code>.</p> 
    2426 
    2527<p>In this example we construct HTML segments manually. If the web interface 
    2628was less trivial, we would want to use more sophisticated web templating and