Sophie

Sophie

distrib > Mandriva > 2008.1 > x86_64 > media > main-release > by-pkgid > db93d7191b12a3d5ce887da46fc79bf1 > files > 106

python-twisted-core-doc-2.5.0-3mdv2008.1.x86_64.rpm

<?xml version="1.0"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><title>Twisted Documentation: Designing Twisted Applications</title><link href="../howto/stylesheet.css" type="text/css" rel="stylesheet" /></head><body bgcolor="white"><h1 class="title">Designing Twisted Applications</h1><div class="toc"><ol><li><a href="#auto0">Goals</a></li><li><a href="#auto1">Example of a modular design: TwistedQuotes</a></li><ul><li><a href="#auto2">Set up the project directory</a></li><li><a href="#auto3">A Look at the Heart of the Application</a></li></ul></ol></div><div class="content"><span></span><h2>Goals<a name="auto0"></a></h2><p>This document describes how a good Twisted application is structured. It
should be useful for beginning Twisted developers who want to structure their
code in a clean, maintainable way that reflects current best practices.</p><p>Readers will want to be familiar with <a href="async.html">asynchonous
programming using Deferreds</a> and with writing <a href="servers.html">servers</a> and <a href="clients.html">clients</a> using
Twisted.</p><h2>Example of a modular design: TwistedQuotes<a name="auto1"></a></h2><p><code>TwistedQuotes</code> is a very simple plugin which is a great
demonstration of
Twisted's power.  It will export a small kernel of functionality -- Quote of
the Day -- which can be accessed through every interface that Twisted supports:
web pages, e-mail, instant messaging, a specific Quote of the Day protocol, and
more.</p><h3>Set up the project directory<a name="auto2"></a></h3><p>See the description of <a href="quotes.html">setting up the TwistedQuotes
example</a>.</p><h3>A Look at the Heart of the Application<a name="auto3"></a></h3><div class="py-listing"><pre>
<span class="py-src-keyword">from</span> <span class="py-src-variable">zope</span>.<span class="py-src-variable">interface</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Interface</span>, <span class="py-src-variable">implements</span>

<span class="py-src-keyword">from</span> <span class="py-src-variable">random</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">choice</span>


<span class="py-src-keyword">class</span> <span class="py-src-identifier">IQuoter</span>(<span class="py-src-parameter">Interface</span>):
    <span class="py-src-string">&quot;&quot;&quot;An object that returns quotes.&quot;&quot;&quot;</span>

    <span class="py-src-keyword">def</span> <span class="py-src-identifier">getQuote</span>():
        <span class="py-src-string">&quot;&quot;&quot;Return a quote.&quot;&quot;&quot;</span>


<span class="py-src-keyword">class</span> <span class="py-src-identifier">StaticQuoter</span>:
    <span class="py-src-string">&quot;&quot;&quot;Return a static quote.&quot;&quot;&quot;</span>

    <span class="py-src-variable">implements</span>(<span class="py-src-variable">IQuoter</span>)

    <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">quote</span>):
        <span class="py-src-variable">self</span>.<span class="py-src-variable">quote</span> = <span class="py-src-variable">quote</span>

    <span class="py-src-keyword">def</span> <span class="py-src-identifier">getQuote</span>(<span class="py-src-parameter">self</span>):
        <span class="py-src-keyword">return</span> <span class="py-src-variable">self</span>.<span class="py-src-variable">quote</span>


<span class="py-src-keyword">class</span> <span class="py-src-identifier">FortuneQuoter</span>:
    <span class="py-src-string">&quot;&quot;&quot;Load quotes from a fortune-format file.&quot;&quot;&quot;</span>

    <span class="py-src-variable">implements</span>(<span class="py-src-variable">IQuoter</span>)

    <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">filenames</span>):
        <span class="py-src-variable">self</span>.<span class="py-src-variable">filenames</span> = <span class="py-src-variable">filenames</span>

    <span class="py-src-keyword">def</span> <span class="py-src-identifier">getQuote</span>(<span class="py-src-parameter">self</span>):
        <span class="py-src-keyword">return</span> <span class="py-src-variable">choice</span>(<span class="py-src-variable">open</span>(<span class="py-src-variable">choice</span>(<span class="py-src-variable">self</span>.<span class="py-src-variable">filenames</span>)).<span class="py-src-variable">read</span>().<span class="py-src-variable">split</span>(<span class="py-src-string">'\n%\n'</span>))
</pre><div class="caption">Twisted Quotes
Central Abstraction - <a href="listings/TwistedQuotes/quoters.py"><span class="filename">listings/TwistedQuotes/quoters.py</span></a></div></div><p>This code listing shows us what the Twisted Quotes system is all about.  The
code doesn't have any way of talking to the outside world, but it provides a
library which is a clear and uncluttered abstraction: <q>give me the quote of
the day</q>. </p><p>Note that this module does not import any Twisted functionality at all!  The
reason for doing things this way is integration.  If your <q>business
objects</q> are not stuck to your user interface, you can make a module that
can integrate those objects with different protocols, GUIs, and file formats.
Having such classes provides a way to decouple your components from each other,
by allowing each to be used independently.</p><p>In this manner, Twisted itself has minimal impact on the logic of your
program.  Although the Twisted <q>dot products</q> are highly interoperable,
they
also follow this approach.  You can use them independently because they are not
stuck to each other.  They communicate in well-defined ways, and only when that
communication provides some additional feature.  Thus, you can use <code class="API">twisted.web</code> with <code class="API">twisted.enterprise</code>, but neither requires the other, because
they are integrated around the concept of <a href="defer.html">Deferreds</a>.</p><p>Your Twisted applications should follow this style as much as possible.
Have (at least) one module which implements your specific functionality,
independent of any user-interface code.  </p><p>Next, we're going to need to associate this abstract logic with some way of
displaying it to the user.  We'll do this by writing a Twisted server protocol,
which will respond to the clients that connect to it by sending a quote to the
client and then closing the connection.  Note: don't get too focused on the
details of this -- different ways to interface with the user are 90% of what
Twisted does, and there are lots of documents describing the different ways to
do it.</p><div class="py-listing"><pre>
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span>.<span class="py-src-variable">protocol</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Factory</span>, <span class="py-src-variable">Protocol</span>

<span class="py-src-keyword">class</span> <span class="py-src-identifier">QOTD</span>(<span class="py-src-parameter">Protocol</span>):

    <span class="py-src-keyword">def</span> <span class="py-src-identifier">connectionMade</span>(<span class="py-src-parameter">self</span>):
        <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">write</span>(<span class="py-src-variable">self</span>.<span class="py-src-variable">factory</span>.<span class="py-src-variable">quoter</span>.<span class="py-src-variable">getQuote</span>()+<span class="py-src-string">'\r\n'</span>)
        <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">loseConnection</span>()

<span class="py-src-keyword">class</span> <span class="py-src-identifier">QOTDFactory</span>(<span class="py-src-parameter">Factory</span>):

    <span class="py-src-variable">protocol</span> = <span class="py-src-variable">QOTD</span>

    <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">quoter</span>):
        <span class="py-src-variable">self</span>.<span class="py-src-variable">quoter</span> = <span class="py-src-variable">quoter</span>
</pre><div class="caption">Twisted
Quotes Protocol Implementation - <a href="listings/TwistedQuotes/quoteproto.py"><span class="filename">listings/TwistedQuotes/quoteproto.py</span></a></div></div><p>This is a very straightforward <code>Protocol</code> implementation, and the
pattern described above is repeated here.  The Protocol contains essentially no
logic of its own, just enough to tie together an object which can generate
quotes (a <code class="python">Quoter</code>) and an object which can relay
bytes to a TCP connection (a <code class="python">Transport</code>).  When a
client connects to this server, a <code class="python">QOTD</code> instance is
created, and its <code class="python">connectionMade</code> method is called.
</p><p> The <code class="python">QOTDFactory</code>'s role is to specify to the
Twisted framework how to create a <code class="python">Protocol</code> instance
that will handle the connection.  Twisted will not instantiate a <code class="python">QOTDFactory</code>; you will do that yourself later, in the
<code class="shell">mktap</code> plug-in below.
</p><p>Note: you can read more specifics of <code class="python">Protocol</code> and
<code class="python">Factory</code> in the <a href="servers.html">Writing
Servers</a> HOWTO.</p><p>Once we have an abstraction -- a <code>Quoter</code> -- and we have a
mechanism to connect it to the network -- the <code>QOTD</code> protocol -- the
next thing to do is to put the last link in the chain of functionality between
abstraction and user.  This last link will allow a user to choose a
<code>Quoter</code> and configure the protocol. Writing this configuration is
covered in the <a href="application.html">Application HOWTO</a>.</p></div><p><a href="../howto/index.html">Index</a></p><span class="version">Version: 2.5.0</span></body></html>