Ticket #4568: high-level.xhtml.patch

File high-level.xhtml.patch, 22.9 KB (added by jdb, 6 years ago)

Adapted the lore input of the articles in the "High-Level Twisted" section of the core howto

  • doc/core/howto/application.xhtml

    diff --git a/doc/core/howto/application.xhtml b/doc/core/howto/application.xhtml
    index 79f19db..3b6601a 100644
    a b Client service. </p> 
    9595
    9696<h3>twistd and tac</h3><a name="twistd" />
    9797
    98 <p>To handle start-up and configuration of your Twisted application, the
    99 Twisted Application infrastructure uses <code>.tac</code> files.
    100 <code>.tac</code> are Python files which configure an <code class="API"
    101 base="twisted.application.service">Application</code> object and assign this
    102 object to the top-level variable <q><code>application</code></q>.</p>
     98<p>To handle start-up and configuration of your Twisted application,
     99the Twisted Application infrastructure uses <code>.tac</code>
     100files. <code>.tac</code> are Python files which configure
     101an <code class="API"
     102base="twisted.application.service">Application</code> object and
     103assign this object to the top-level
     104variable <q><code>application</code></q>.</p>
    103105
    104106<p>The following is a simple example of a <code>.tac</code> file:</p>
    105107
    106108<a href="listings/application/service.tac" class="py-listing">service.tac</a>
    107109
    108 <p><code>twistd</code> is a program that runs Twisted applications using a
    109 <code>.tac</code> file. In its most simple form, it takes a single argument
    110 <code>-y</code> and a tac file name. For example, you can run the above server
    111 with the command <code class="shell">twistd -y service.tac</code>.</p>
     110<p><code>twistd</code> is a program that runs Twisted applications
     111using a <code>.tac</code> file. In its most simple form, it takes a
     112single argument <code>-y</code> and a tac file name. For example, you
     113can run the above server with the command <code class="shell">twistd
     114-y service.tac</code>.</p>
    112115
    113 <p>By default, <code>twistd</code> daemonizes and logs to a file called
    114 <code>twistd.log</code>. More usually, when debugging, you will want your
    115 application to run in the foreground and log to the command line. To run the
    116 above file like this, use the command <code class="shell">twistd -noy
    117 service.tac</code></p>
     116<p>By default, <code>twistd</code> daemonizes and logs to a file
     117called <code>twistd.log</code>. More usually, when debugging, you will
     118want your application to run in the foreground and log to the command
     119line. To run the above file like this, use the
     120command <code class="shell">twistd -noy service.tac</code></p>
    118121
    119122<p>For more information, see the <code>twistd</code> man page.</p>
    120123
    121124<h3>Customizing <code>twistd</code> logging in a .tac application</h3>
    122125
    123126<p>
    124 The logging behavior can be customized through an API
    125 accessible from <code>.tac</code> files.  The <code class="API"
    126 base="twisted.python.log">ILogObserver</code> component can be
    127 set on an Application in order to customize the default log observer that
    128 <code>twistd</code> will use.
     127The logging behavior can be customized through an API accessible
     128from <code>.tac</code> files.  The <code class="API"
     129base="twisted.python.log">ILogObserver</code> component can be set on
     130an Application in order to customize the default log observer
     131that <code>twistd</code> will use.
    129132</p>
    130133
    131134<p>
    application.setComponent(ILogObserver, FileLogObserver(logfile).emit) 
    146149
    147150<p>
    148151invoking <code class="shell">twistd -y my.tac</code> will create a log file
    149 at<code>/tmp/my.log</code>.
     152at <code>/tmp/my.log</code>.
    150153</p>
    151154
    152155<h3>Services provided by Twisted</h3>
    corresponds to reactor.connectTCP. </p> 
    253256<h3>Service Collection</h3>
    254257
    255258<p><code class="API"
    256 base="twisted.application.service">IServiceCollection</code> objects contain
    257 <code class="API" base="twisted.application.service">IService</code> objects.
    258 IService objects can be added to IServiceCollection by calling <code class="API"
    259 base="twisted.application.service.IService">setServiceParent</code> and detached
    260 by using <code class="API"
     259base="twisted.application.service">IServiceCollection</code> objects
     260contain <code class="API"
     261base="twisted.application.service">IService</code> objects.  IService
     262objects can be added to IServiceCollection by
     263calling <code class="API"
     264base="twisted.application.service.IService">setServiceParent</code>
     265and detached by using <code class="API"
    261266base="twisted.application.service.IService">disownServiceParent</code>.</p>
    262267
    263268<p>The standard implementation of IServiceCollection is <code class="API"
  • doc/core/howto/basics.xhtml

    diff --git a/doc/core/howto/basics.xhtml b/doc/core/howto/basics.xhtml
    index df27fba..20b00ed 100644
    a b  
    1212
    1313<h2>Application</h2>
    1414
    15 <p>Twisted programs usually work with
    16 <code class="API">twisted.application.service.Application</code>.
    17 This class usually holds all persistent configuration of
    18 a running server -- ports to bind to, places where connections
    19 to must be kept or attempted, periodic actions to do and almost
    20 everything else. It is the root object in a tree of services implementing
    21 <code class="API" base="twisted.application.service">IService</code>.</p>
     15<p>Twisted programs usually work
     16with <code class="API">twisted.application.service.Application</code>.
     17This class usually holds all persistent configuration of a running
     18server -- ports to bind to, places where connections to must be kept
     19or attempted, periodic actions to do and almost everything else. It is
     20the root object in a tree of services implementing <code class="API"
     21base="twisted.application.service">IService</code>.</p>
    2222
    2323<p>Other HOWTOs describe how to write custom code for Applications,
    2424but this one describes how to use already written code (which can be
    directory. When a straight Python file which defines an <code>Application</code> 
    5252object called <code>application</code> is used, use the <code class="shell">-y</code>
    5353option.</p>
    5454
    55 <p>When <code class="shell">twistd</code> runs, it records its process id in a
    56 <code>twistd.pid</code> file (this can be configured via a command line
    57 switch). In order to shutdown the <code class="shell">twistd</code> process, kill that
    58 pid (usually you would do <code class="shell">kill `cat twistd.pid`</code>).
     55<p>When <code class="shell">twistd</code> runs, it records its process
     56id in a <code>twistd.pid</code> file (this can be configured via a
     57command line switch). In order to shutdown
     58the <code class="shell">twistd</code> process, kill that pid (usually
     59you would do <code class="shell">kill `cat twistd.pid`</code>).
    5960</p>
    6061
    6162<p>As always, the gory details are in the manual page.</p>
    pid (usually you would do <code class="shell">kill `cat twistd.pid`</code>). 
    6364<h2>OS Integration</h2>
    6465
    6566<p>
    66 If you have an Application that runs with <code class="shell">twistd</code>,
    67 you can easily deploy it on RedHat Linux or Debian GNU/Linux based systems
    68 using the <code class="shell">tap2deb</code> or <code
    69 class="shell">tap2rpm</code> tools. These take a Twisted Application file (of
    70 any of the supported formats — Python source, XML or pickle), and build a
    71 Debian or RPM package (respectively) that installs the Application as a system
    72 service. The package includes the Application file, a default
    73 <code>/etc/init.d/</code> script that starts and stops the process with twistd,
    74 and post-installation scripts that configure the Application to be run in the
    75 appropriate init levels.
     67If you have an Application that runs
     68with <code class="shell">twistd</code>, you can easily deploy it on
     69RedHat Linux or Debian GNU/Linux based systems using
     70the <code class="shell">tap2deb</code>
     71or <code class="shell">tap2rpm</code> tools. These take a Twisted
     72Application file (of any of the supported formats — Python source, XML
     73or pickle), and build a Debian or RPM package (respectively) that
     74installs the Application as a system service. The package includes the
     75Application file, a default <code>/etc/init.d/</code> script that
     76starts and stops the process with twistd, and post-installation
     77scripts that configure the Application to be run in the appropriate
     78init levels.
    7679</p>
    7780
    7881<!-- Is "note" really the right class to be using here? -->
    79 <div class="note">
    80 <code class="shell">tap2rpm</code> and <code class="shell">tap2deb</code> do
    81 not package your entire application and dependent code, just the Twisted
    82 Application file. You will need to find some other way to package your Python
    83 code, such as <code class="API">distutils</code>' <code>bdist_rpm</code>
    84 command.
     82<div class="note"> <code class="shell">tap2rpm</code>
     83and <code class="shell">tap2deb</code> do not package your entire
     84application and dependent code, just the Twisted Application file. You
     85will need to find some other way to package your Python code, such
     86as <code class="API">distutils</code>' <code>bdist_rpm</code> command.
    8587</div>
    8688
    8789<p>
  • doc/core/howto/components.xhtml

    diff --git a/doc/core/howto/components.xhtml b/doc/core/howto/components.xhtml
    index 3567d6e..135e4ef 100644
    a b  
    88<body>
    99<h1>Components: Interfaces and Adapters</h1>
    1010
    11 <p>Object oriented programming languages allow programmers to reuse portions of
    12 existing code by creating new <q>classes</q> of objects which subclass another
    13 class.  When a class subclasses another, it is said to <em>inherit</em> all of its
    14 behaviour.  The subclass can then <q>override</q> and <q>extend</q> the behavior
    15 provided to it by the superclass. Inheritance is very useful in many situations,
    16 but because it is so convenient to use, often becomes abused in large software
    17 systems, especially when multiple inheritance is involved. One solution is to
    18 use <em>delegation</em> instead of <q>inheritance</q> where appropriate.
    19 Delegation is simply the act of asking <em>another</em> object to perform a task
    20 for an object. To support this design pattern, which is often referred to as the
    21 <em>components</em> pattern because it involves many small interacting components,
    22 <em>interfaces</em> and <em>adapters</em> were created by the Zope 3 team.</p>
     11<p>Object oriented programming languages allow programmers to reuse
     12portions of existing code by creating new <q>classes</q> of objects
     13which subclass another class.  When a class subclasses another, it is
     14said to <em>inherit</em> all of its behaviour.  The subclass can
     15then <q>override</q> and <q>extend</q> the behavior provided to it by
     16the superclass. Inheritance is very useful in many situations, but
     17because it is so convenient to use, often becomes abused in large
     18software systems, especially when multiple inheritance is
     19involved. One solution is to use <em>delegation</em> instead
     20of <q>inheritance</q> where appropriate.  Delegation is simply the act
     21of asking <em>another</em> object to perform a task for an object. To
     22support this design pattern, which is often referred to as
     23the <em>components</em> pattern because it involves many small
     24interacting components, <em>interfaces</em> and <em>adapters</em> were
     25created by the Zope 3 team.</p>
    2326
    2427<p><q>Interfaces</q> are simply markers which objects can use to say <q>I
    2528implement this interface</q>. Other objects may then make requests like
    technique called <em>composition</em>, which relies on delegation rather than 
    100103inheritance to break code into small reusable chunks. Let us continue with the
    101104Multiple Inheritance example, though, because it is often used in practice.</p>
    102105
    103 <p>What if both the Color and the Area base class defined the same method,
    104 perhaps <code>calculate</code>? Where would the implementation come from? The
    105 implementation that is located for <code>Square().calculate()</code> depends on
    106 the method resolution order, or MRO, and can change when programmers change
    107 seemingly unrelated things by refactoring classes in other parts of the system,
    108 causing obscure bugs. Our first thought might be to change the calculate method
    109 name to avoid name clashes, to perhaps <code>calculateArea</code> and
    110 <code>calculateColor</code>.  While explicit, this change could potentially
    111 require a large number of changes throughout a system, and is error-prone,
    112 especially when attempting to integrate two systems which you didn't write.</p>
     106<p>What if both the Color and the Area base class defined the same
     107method, perhaps <code>calculate</code>? Where would the implementation
     108come from? The implementation that is located
     109for <code>Square().calculate()</code> depends on the method resolution
     110order, or MRO, and can change when programmers change seemingly
     111unrelated things by refactoring classes in other parts of the system,
     112causing obscure bugs. Our first thought might be to change the
     113calculate method name to avoid name clashes, to
     114perhaps <code>calculateArea</code> and <code>calculateColor</code>.
     115While explicit, this change could potentially require a large number
     116of changes throughout a system, and is error-prone, especially when
     117attempting to integrate two systems which you didn't write.</p>
    113118
    114119<p>Let's imagine another example. We have an electric appliance, say a hair
    115120dryer. The hair dryer is american voltage. We have two electric sockets, one of
    I was plugged in improperly and 
    151156now you have no hair dryer any more.
    152157</pre>
    153158
    154 <p>We are going to attempt to solve this problem by writing an Adapter for the
    155 <code>ForeignSocket</code> which converts the voltage for use with an American
    156 hair dryer. An Adapter is a class which is constructed with one and only one
    157 argument, the <q>adaptee</q> or <q>original</q> object. In this example, we
    158 will show all code involved for clarity:</p>
     159<p>We are going to attempt to solve this problem by writing an Adapter
     160for the <code>ForeignSocket</code> which converts the voltage for use
     161with an American hair dryer. An Adapter is a class which is
     162constructed with one and only one argument, the <q>adaptee</q>
     163or <q>original</q> object. In this example, we will show all code
     164involved for clarity:</p>
    159165
    160166<pre class="python">
    161167class AdaptToAmericanSocket:
    the class block do not have any method body! Since Python does not have any 
    213219native language-level support for Interfaces like Java does, this is what
    214220distinguishes an Interface definition from a Class.</p>
    215221
    216 <p>Now that we have a defined Interface, we can talk about objects using terms
    217 like this: <q>The <code>AmericanSocket</code> class implements the
    218 <code>IAmericanSocket</code> interface</q> and <q>Please give me an object which
     222<p>Now that we have a defined Interface, we can talk about objects
     223using terms like this: <q>The <code>AmericanSocket</code> class
     224implements the <code>IAmericanSocket</code> interface</q>
     225and <q>Please give me an object which
    219226adapts <code>ForeignSocket</code> to the <code>IAmericanSocket</code>
    220 interface</q>. We can make <em>declarations</em> about what interfaces a certain
    221 class implements, and we can request adapters which implement a certain
    222 interface for a specific class.</p>
     227interface</q>. We can make <em>declarations</em> about what interfaces
     228a certain class implements, and we can request adapters which
     229implement a certain interface for a specific class.</p>
    223230
    224231<p>Let's look at how we declare that a class implements an interface:</p>
    225232
    class AmericanSocket: 
    234241        return 110
    235242</pre>
    236243
    237 <p>So, to declare that a class implements an interface, we simply call
    238 <code>zope.interface.implements</code> at the class level.</p>
     244<p>So, to declare that a class implements an interface, we simply
     245call <code>zope.interface.implements</code> at the class level.</p>
    239246
    240 <p>Now, let's say we want to rewrite the <code>AdaptToAmericanSocket</code>
    241 class as a real adapter. In this case we also specify it as implementing
    242 <code>IAmericanSocket</code>:</p>
     247<p>Now, let's say we want to rewrite
     248the <code>AdaptToAmericanSocket</code> class as a real adapter. In
     249this case we also specify it as
     250implementing <code>IAmericanSocket</code>:</p>
    243251
    244252<pre class="python">
    245253from zope.interface import implements
    class AdaptToAmericanSocket: 
    258266        return self.original.voltage() / 2
    259267</pre>
    260268
    261 <p>Notice how we placed the implements declaration on this adapter class. So
    262 far, we have not achieved anything by using components other than requiring us
    263 to type more. In order for components to be useful, we must use the
    264 <em>component registry</em>. Since <code>AdaptToAmericanSocket</code> implements
    265 <code>IAmericanSocket</code> and regulates the voltage of a
    266 <code>ForeignSocket</code> object, we can <em>register
    267 <code>AdaptToAmericanSocket</code> as an <code>IAmericanSocket</code> adapter
    268 for the <code>ForeignSocket</code> class</em>. It is easier to see how this is
    269 done in code than to describe it:</p>
     269<p>Notice how we placed the implements declaration on this adapter
     270class. So far, we have not achieved anything by using components other
     271than requiring us to type more. In order for components to be useful,
     272we must use the <em>component
     273registry</em>. Since <code>AdaptToAmericanSocket</code>
     274implements <code>IAmericanSocket</code> and regulates the voltage of
     275a <code>ForeignSocket</code> object, we
     276can <em>register </em> <code>AdaptToAmericanSocket</code> <em> as
     277an </em> <code>IAmericanSocket</code> <em> adapter for
     278the </em> <code>ForeignSocket</code> <em>class</em>. It is easier to see how
     279this is done in code than to describe it:</p>
    270280
    271281<pre class="python">
    272282from zope.interface import Interface, implements
    False 
    321331</pre>
    322332
    323333<p>As you can see, the <code>AmericanSocket</code> instance claims to
    324 implement <code>IAmericanSocket</code>, but the <code>ForeignSocket</code>
    325 does not. If we wanted to use the <code>HairDryer</code> with the
    326 <code>AmericanSocket</code>, we could know that it would be safe to do so by
    327 checking whether it implements <code>IAmericanSocket</code>. However, if we
    328 decide we want to use <code>HairDryer</code> with a <code>ForeignSocket</code>
    329 instance, we must <em>adapt</em> it to <code>IAmericanSocket</code> before
    330 doing so.  We use the interface object to do this:</p>
     334implement <code>IAmericanSocket</code>, but
     335the <code>ForeignSocket</code> does not. If we wanted to use
     336the <code>HairDryer</code> with the <code>AmericanSocket</code>, we
     337could know that it would be safe to do so by checking whether it
     338implements <code>IAmericanSocket</code>. However, if we decide we want
     339to use <code>HairDryer</code> with a <code>ForeignSocket</code>
     340instance, we must <em>adapt</em> it to <code>IAmericanSocket</code>
     341before doing so.  We use the interface object to do this:</p>
    331342
    332343<pre class="python-interpreter">
    333344&gt;&gt;&gt; IAmericanSocket(fs)
    334345&lt;__main__.AdaptToAmericanSocket instance at 0x1a5120&gt;
    335346</pre>
    336347
    337 <p>When calling an interface with an object as an argument, the interface
    338 looks in the adapter registry for an adapter which implements the interface for
    339 the given instance's class. If it finds one, it constructs an instance of the
    340 Adapter class, passing the constructor the original instance, and returns it.
    341 Now the <code>HairDryer</code> can safely be used with the adapted
    342 <code>ForeignSocket</code>. But what happens if we attempt to adapt an object
    343 which already implements <code>IAmericanSocket</code>? We simply get back the
    344 original instance:</p>
     348<p>When calling an interface with an object as an argument, the
     349interface looks in the adapter registry for an adapter which
     350implements the interface for the given instance's class. If it finds
     351one, it constructs an instance of the Adapter class, passing the
     352constructor the original instance, and returns it.  Now
     353the <code>HairDryer</code> can safely be used with the
     354adapted <code>ForeignSocket</code>. But what happens if we attempt to
     355adapt an object which already implements <code>IAmericanSocket</code>?
     356We simply get back the original instance:</p>
    345357
    346358<pre class="python-interpreter">
    347359&gt;&gt;&gt; IAmericanSocket(am)
    class Root(Referenceable): 
    395407    implements(IPBRoot)
    396408</pre>
    397409
    398 <p>Suppose you have your own class which implements your
    399 <code>IMyInterface</code> interface:</p>
     410<p>Suppose you have your own class which implements
     411your <code>IMyInterface</code> interface:</p>
    400412
    401413<pre class="python">
    402414from zope.interface import implements, Interface
    class MyThing: 
    408420    implements(IMyInterface)
    409421</pre>
    410422
    411 <p>Now if you want to make this class inherit from <code>pb.Root</code>,
    412 the interfaces code will automatically determine that it also implements
    413 <code>IPBRoot</code>:</p>
     423<p>Now if you want to make this class inherit
     424from <code>pb.Root</code>, the interfaces code will automatically
     425determine that it also implements <code>IPBRoot</code>:</p>
    414426
    415427<pre class="python">
    416428from twisted.spread import pb
    class MyThing(pb.Root): 
    429441True
    430442</pre>
    431443
    432 <p>If you want <code>MyThing</code> to inherit from <code>pb.Root</code> but
    433 <em>not</em> implement <code>IPBRoot</code> like <code>pb.Root</code> does,
     444<p>If you want <code>MyThing</code> to inherit
     445from <code>pb.Root</code> but <em>not</em>
     446implement <code>IPBRoot</code> like <code>pb.Root</code> does,
    434447use <code>implementOnly</code>:</p>
    435448
    436449<pre class="python">
  • doc/core/howto/cred.xhtml

    diff --git a/doc/core/howto/cred.xhtml b/doc/core/howto/cred.xhtml
    index f16080b..dae222b 100644
    a b This has only 2 methods -</p> 
    6565<ul>
    6666<li><code class="API" base="twisted.cred.portal.Portal">login</code><code>(credentials, mind, *interfaces)</code>
    6767
    68 <p>The docstring is quite expansive (see <code class="API">twisted.cred.portal</code>), but in
    69 brief, this is what you call when you need to call in order to connect
    70 a user to the system.  Typically you only pass in one interface, and the mind is
    71 <code class="python">None</code>. The interfaces are the possible interfaces the returned
    72 avatar is expected to implement, in order of preference.
    73 The result is a deferred which fires a tuple of:</p>
     68<p>The docstring is quite expansive
     69(see <code class="API">twisted.cred.portal</code>), but in brief, this
     70is what you call when you need to call in order to connect a user to
     71the system.  Typically you only pass in one interface, and the mind
     72is <code class="python">None</code>. The interfaces are the possible
     73interfaces the returned avatar is expected to implement, in order of
     74preference.  The result is a deferred which fires a tuple of:</p>
    7475    <ul>
    7576        <li>interface the avatar implements (which was one of the interfaces passed in the *interfaces
    7677tuple)</li>
    href="tap.xhtml">Writing a twistd plugin</a> document.</p> 
    343344
    344345   <h3>Building a cred plugin</h3>
    345346
    346 <p> To build a plugin for cred, you should first define an <code
    347 class="python">authType</code>, a short one-word string that defines
    348 your plugin to the command-line. Once you have this, the convention is
    349 to create a file named <code>myapp_plugins.py</code> in the
    350 <code class="API">twisted.plugins</code> module path. </p>
     347<p> To build a plugin for cred, you should first define
     348an <code class="python">authType</code>, a short one-word string that
     349defines your plugin to the command-line. Once you have this, the
     350convention is to create a file named <code>myapp_plugins.py</code> in
     351the <code class="API">twisted.plugins</code> module path. </p>
    351352
    352353<p> Below is an example file structure for an application that defines
    353354such a plugin: </p>