ekalinin / github-markdown-toc

Easy TOC creation for GitHub README.md
MIT License
3.23k stars 2.75k forks source link

gh-md-toc failing with some md files. #22

Closed iogf closed 5 years ago

iogf commented 8 years ago

It seems gh-md-toc(the repository version and other versions fails with it)

gh-md-toc https://github.com/iogf/untwisted/blob/master/BOOK.md

ekalinin commented 8 years ago

Hey @iogf

Just tested it (see below) and it seems like it's ok. Would you be able to provide more details (what OS do you use, for example)?

➥ ./gh-md-toc --version
0.4.6
➥ ./gh-md-toc https://github.com/iogf/untwisted/blob/master/BOOK.md

Table of Contents
=================

  * [What can i create with untwisted?](#what-can-i-create-with-untwisted)
  * [Untwisted plugins](#untwisted-plugins)
  * [The rapidserv plugin](#the-rapidserv-plugin)
      * [A simple application](#a-simple-application)
      * [The <strong>request</strong> object](#the-request-object)
        * [request.method](#requestmethod)
        * [request.headers](#requestheaders)
        * [request.data](#requestdata)
        * [request.query](#requestquery)
        * [request.path](#requestpath)
        * [request.version](#requestversion)
      * [The basic dir structure](#the-basic-dir-structure)
      * [Quote Application](#quote-application)
        * [quote/static/comment.html](#quotestaticcommenthtml)
        * [quote/templates/show.html](#quotetemplatesshowhtml)
        * [quote/templates/view.html](#quotetemplatesviewhtml)
        * [quote/app.py](#quoteapppy)
        * [Running](#running)
      * [Imup Applicaiton](#imup-applicaiton)
        * [imup/templates/view.jinja](#imuptemplatesviewjinja)
        * [imup/app.py](#imupapppy)
      * [quickserv script](#quickserv-script)
  * [The requests plugin](#the-requests-plugin)
  * [The event-driven paradigm](#the-event-driven-paradigm)
      * [Skeletons](#skeletons)
      * [Image of objects/handles](#image-of-objectshandles)
      * [The symbol **](#the-symbol-)
      * [Event arguments](#event-arguments)
  * [Dispatcher class](#dispatcher-class)
      * [Event creation](#event-creation)
      * [Spawning events from handles](#spawning-events-from-handles)
      * [Passing additional arguments to handles](#passing-additional-arguments-to-handles)
      * [Unbinding handles](#unbinding-handles)
      * [Exceptions in handles](#exceptions-in-handles)
      * [The Kill, Root exceptions](#the-kill-root-exceptions)
      * [Handle returns](#handle-returns)
      * [Handles that are mapped upon events and produce events.](#handles-that-are-mapped-upon-events-and-produce-events)
      * [Dispatcher flow control](#dispatcher-flow-control)
      * [Static handles](#static-handles)
      * [binding static handles to events](#binding-static-handles-to-events)
      * [Unbinding static handles to events](#unbinding-static-handles-to-events)
  * [Reactors](#reactors)
  * [Super socket class](#super-socket-class)
  * [Spin class](#spin-class)
  * [A word on handles](#a-word-on-handles)
  * [Basic built-in handles](#basic-built-in-handles)
  * [Basic Client/Server Applications](#basic-clientserver-applications)
      * [A simple Client (is_up.py)](#a-simple-client-is_uppy)
      * [Msg Server (msg_server.py)](#msg-server-msg_serverpy)
      * [Msg Client (msg_client.py)](#msg-client-msg_clientpy)
      * [Echo Server (echo_server.py)](#echo-server-echo_serverpy)
  * [Splits](#splits)
      * [Terminator Split](#terminator-split)
      * [Calc Server (calc_server.py)](#calc-server-calc_serverpy)
  * [Timers](#timers)
  * [Coroutines](#coroutines)
      * [A simple chat server (chat_server.py)](#a-simple-chat-server-chat_serverpy)
  * [Threads](#threads)
      * [Job class](#job-class)
      * [A basic example (sum.py)](#a-basic-example-sumpy)
  * [Spawning processes](#spawning-processes)
      * [Expect class](#expect-class)
      * [A basic example (spawn_process.py)](#a-basic-example-spawn_processpy)
  * [Tasks](#tasks)
      * [Task class](#task-class)
      * [A Port Scan (port_scan.py)](#a-port-scan-port_scanpy)
  * [Basic SSL Client/Server Applications](#basic-ssl-clientserver-applications)
  * [The IRC Client plugin](#the-irc-client-plugin)
  * [Reactor flow control](#reactor-flow-control)
      * [The Root exception](#the-root-exception)
      * [The Kill exception](#the-kill-exception)
  * [Debugging](#debugging)
  * [Tests](#tests)

Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc)
iogf commented 8 years ago

i got it.

gh-md-toc
GitHub TOC generator (gh-md-toc): 0.4.6

Usage:
  gh-md-toc src [src]     Create TOC for a README file (url or local path)
  gh-md-toc -             Create TOC for markdown from STDIN
  gh-md-toc --help        Show help
  gh-md-toc --version     Show version
[tau@lambda ~]$ gh-md-toc --version
0.4.6
[tau@lambda ~]$ gh-md-toc https://github.com/iogf/untwisted/blob/master/BOOK.md

Table of Contents
=================

  * [What can i create with untwisted?</h1>  <p>Untwisted permits the implementation of networking applications, spawning processes, threads. It is possible to implement web crawlers, web applications, irc clients, irc servers, ftp clients, ftp servers, talk to processes.</p>  <h1><a id="user-content-untwisted-plugins" class="anchor" href="#untwisted-plugins" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Untwisted plugins</h1>  <p>Untwisted is an event driven lib that offers ways to implement networking applications using a non blocking design. It is possible to implement abstractions for application layer protocols and use these abstractions in the implementation of networking applications that run on top of such internet layer protocols.</p>  <h1><a id="user-content-the-rapidserv-plugin" class="anchor" href="#the-rapidserv-plugin" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>The rapidserv plugin</h1>  <p>Rapidserv is a micro web framework that is built on top of a powerful asynchronous networking library. It shares with flask some similarities in the design of the applications that are built on top of Rapidserv. Rapidserv is non blocking network I/O consequently it can scale a lot of connections and it is ideal for some applications.  Rapidserv uses jinja2 although it doesn't enforce the usage.</p>  <h3><a id="user-content-a-simple-application" class="anchor" href="#a-simple-application" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>A simple application</h3>  <p>The source code for a basic rapidserv application is listed below.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">from</span> untwisted.plugins.rapidserv <span class="pl-k">import</span> RapidServ, core  app <span class="pl-k">=</span> RapidServ(<span class="pl-c1">__file__</span>)  <span class="pl-en">@app.request</span>(<span class="pl-s"><span class="pl-pds">'</span>GET /<span class="pl-pds">'</span></span>) <span class="pl-k">def</span> <span class="pl-en">send_base</span>(<span class="pl-smi">con</span>, <span class="pl-smi">request</span>):     con.add_data(<span class="pl-s"><span class="pl-pds">'</span>&lt;html&gt; &lt;body&gt; &lt;p&gt; Rapidserv &lt;/p&gt; &lt;/body&gt; &lt;/html&gt;<span class="pl-pds">'</span></span>)     con.done()  <span class="pl-k">if</span> <span class="pl-c1">__name__</span> <span class="pl-k">==</span> <span class="pl-s"><span class="pl-pds">'</span>__main__<span class="pl-pds">'</span></span>:     app.bind(<span class="pl-s"><span class="pl-pds">'</span>0.0.0.0<span class="pl-pds">'</span></span>, <span class="pl-c1">80</span>, <span class="pl-c1">50</span>)     core.gear.mainloop()</pre></div>  <p><strong>The basic statements</strong></p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">from</span> untwisted.plugins.rapidserv <span class="pl-k">import</span> RapidServ, core app <span class="pl-k">=</span> RapidServ(<span class="pl-c1">__file__</span>)</pre></div>  <p>The <strong>RapidServ</strong> class is the web server instance that handles the HTTP requests. The core module is untwisted module that is used to call the reactor mainloop.</p>  <p>The argument passed to the *<em>RapidServ</em> constructor tells jinja2 where to look for  templates and rapidserv plugins where to look for static files.</p>  <p>The usage of the decorator <strong>app.request</strong> tells rapidserv to deliver to the handle <strong>send_base</strong> HTTP  requests whose method used is 'GET' and the path is '/'. The <strong>send_base</strong> handle is a view function.</p>  <p>Notice that it is needed to call the method con.done() in order to get the response sent to the client.</p>  <p>These lines tells rapidserv to listen for connections on the interface <strong>'0.0.0.0'</strong> at the port <strong>80</strong>. The value <strong>50</strong> is the backlog.</p>  <div class="highlight highlight-source-python"><pre>    app.bind(<span class="pl-s"><span class="pl-pds">'</span>0.0.0.0<span class="pl-pds">'</span></span>, <span class="pl-c1">80</span>, <span class="pl-c1">50</span>)     core.gear.mainloop()</pre></div>  <h3><a id="user-content-the-request-object" class="anchor" href="#the-request-object" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>The <strong>request</strong> object](#what-can-i-create-with-untwisted)
 * [request.method</h4>  <p>It holds the HTTP method that was used in the user request.</p>  <h4><a id="user-content-requestheaders" class="anchor" href="#requestheaders" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>request.headers</h4>  <p>Obviously, it holds the HTTP headers that were sent by the user.</p>  <h4><a id="user-content-requestdata" class="anchor" href="#requestdata" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>request.data</h4>  <p>That is a <strong>cgi.FieldStorage</strong> instance that holds the body of the request, stuff like files etc.</p>  <h4><a id="user-content-requestquery" class="anchor" href="#requestquery" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>request.query</h4>  <p>That is a dict instance that holds the query parameters that were sent in the HTTP request.</p>  <p>For example, if the user has sent a request like:</p>  <pre>GET /path?name=iury HTTP/1.1 </pre>  <p>And there were a view defined like:</p>  <div class="highlight highlight-source-python"><pre><span class="pl-en">@app.request</span>(<span class="pl-s"><span class="pl-pds">'</span>GET /path<span class="pl-pds">'</span></span>) <span class="pl-k">def</span> <span class="pl-en">path</span>(<span class="pl-smi">con</span>, <span class="pl-smi">request</span>):     <span class="pl-c1">print</span> request.query[<span class="pl-s"><span class="pl-pds">'</span>name<span class="pl-pds">'</span></span>][<span class="pl-c1">0</span>]</pre></div>  <p>Would print <strong>'iury'</strong>.</p>  <h4><a id="user-content-requestpath" class="anchor" href="#requestpath" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>request.path</h4>  <p>In a request like:</p>  <pre><code>GET /view?name=iury HTTP/1.01 </code></pre>  <p>That attribute would hold the string <strong>'/view'</strong>.</p>  <h4><a id="user-content-requestversion" class="anchor" href="#requestversion" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>request.version</h4>  <p>It contains the HTTP version that was specified in the user request.</p>  <h3><a id="user-content-the-basic-dir-structure" class="anchor" href="#the-basic-dir-structure" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>The basic dir structure</h3>  <p>RapidServ applications are generally built on top of a standard structure of dirs. There is a folder named <strong>templates</strong> and a folder named *<em>static</em> to hold static files.</p>  <pre><code>application/     templates/     static/     app.py </code></pre>  <h3><a id="user-content-quote-application" class="anchor" href="#quote-application" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Quote Application</h3>  <p>The Quote application is a simple quote system that permits users to add quotes to a database and view them when they access the site base.</p>  <p>Let us create the folders and app.</p>  <pre><code>mkdir quote cd quote mkdir templates mkdir static </code></pre>  <h4><a id="user-content-quotestaticcommenthtml" class="anchor" href="#quotestaticcommenthtml" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>quote/static/comment.html</h4>  <p>this file will hold the page that is used to add a quote.</p>  <div class="highlight highlight-text-html-basic"><pre>    &lt;<span class="pl-ent">html</span>&gt;      &lt;<span class="pl-ent">body</span>&gt;       &lt;<span class="pl-ent">FORM</span> <span class="pl-e">action</span>=<span class="pl-s"><span class="pl-pds">"</span>/add_quote<span class="pl-pds">"</span></span> <span class="pl-e">method</span>=<span class="pl-s"><span class="pl-pds">"</span>get<span class="pl-pds">"</span></span>&gt;      &lt;<span class="pl-ent">table</span>&gt;      &lt;<span class="pl-ent">tr</span>&gt;      &lt;<span class="pl-ent">td</span> <span class="pl-e">colspan</span>=<span class="pl-s"><span class="pl-pds">"</span>2<span class="pl-pds">"</span></span>&gt;         &lt;<span class="pl-ent">textarea</span> <span class="pl-e">style</span>=<span class="pl-s"><span class="pl-pds">"</span>width:100\x;<span class="pl-pds">"</span></span> <span class="pl-e">name</span>=<span class="pl-s"><span class="pl-pds">"</span>quote<span class="pl-pds">"</span></span> <span class="pl-e">rows</span>=<span class="pl-s"><span class="pl-pds">"</span>10<span class="pl-pds">"</span></span> <span class="pl-e">id</span>=<span class="pl-s"><span class="pl-pds">"</span>quote<span class="pl-pds">"</span></span> <span class="pl-e">cols</span>=<span class="pl-s"><span class="pl-pds">"</span>30<span class="pl-pds">"</span></span>&gt;              The cat was playing in the garden. &lt;/<span class="pl-ent">textarea</span>&gt;       &lt;/<span class="pl-ent">td</span>&gt;      &lt;/<span class="pl-ent">tr</span>&gt;        &lt;<span class="pl-ent">tr</span>&gt;      &lt;<span class="pl-ent">td</span>&gt;         &lt;<span class="pl-ent">INPUT</span> <span class="pl-e">name</span>=<span class="pl-s"><span class="pl-pds">"</span>name<span class="pl-pds">"</span></span> <span class="pl-e">id</span>=<span class="pl-s"><span class="pl-pds">"</span>name<span class="pl-pds">"</span></span> <span class="pl-e">type</span>=<span class="pl-s"><span class="pl-pds">"</span>text<span class="pl-pds">"</span></span>&gt;      &lt;/<span class="pl-ent">td</span>&gt;      &lt;<span class="pl-ent">td</span>&gt;         &lt;<span class="pl-ent">INPUT</span> <span class="pl-e">type</span>=<span class="pl-s"><span class="pl-pds">"</span>submit<span class="pl-pds">"</span></span> <span class="pl-e">value</span>=<span class="pl-s"><span class="pl-pds">"</span>Post<span class="pl-pds">"</span></span>&gt;      &lt;/<span class="pl-ent">td</span>&gt;      &lt;/<span class="pl-ent">tr</span>&gt;      &lt;/<span class="pl-ent">FORM</span>&gt;      &lt;/<span class="pl-ent">body</span>&gt;     &lt;/<span class="pl-ent">html</span>&gt;</pre></div>  <p>Now it is time to implement the templates.</p>  <h4><a id="user-content-quotetemplatesshowhtml" class="anchor" href="#quotetemplatesshowhtml" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>quote/templates/show.html</h4>  <p>This template is used to render all the quotes of the database.</p>  <div class="highlight highlight-text-html-basic"><pre>    &lt;<span class="pl-ent">html</span>&gt;      &lt;<span class="pl-ent">head</span>&gt;       &lt;/<span class="pl-ent">head</span>&gt;      &lt;/<span class="pl-ent">body</span>&gt;     &lt;<span class="pl-ent">h1</span>&gt; List of quotes. &lt;/<span class="pl-ent">h1</span>&gt;       {\x for index, name, quote in posts \x}         &lt;<span class="pl-ent">h3</span>&gt;&lt;<span class="pl-ent">a</span> <span class="pl-e">href</span>=<span class="pl-s"><span class="pl-pds">"</span>/load_index?index={{index}}<span class="pl-pds">"</span></span>&gt; {{name}} {{quote}}... &lt;/<span class="pl-ent">a</span>&gt;&lt;/<span class="pl-ent">h3</span>&gt;       {\x endfor \x}      &lt;<span class="pl-ent">h1</span>&gt;&lt;<span class="pl-ent">a</span> <span class="pl-e">href</span>=<span class="pl-s"><span class="pl-pds">"</span>comment.html<span class="pl-pds">"</span></span>&gt; Add quote &lt;/<span class="pl-ent">a</span>&gt;&lt;/<span class="pl-ent">h1</span>&gt;     &lt;/<span class="pl-ent">body</span>&gt;      &lt;/<span class="pl-ent">html</span>&gt;</pre></div>  <h4><a id="user-content-quotetemplatesviewhtml" class="anchor" href="#quotetemplatesviewhtml" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>quote/templates/view.html</h4>  <p>This file is used to render a quote when the user clicks on the quote ref in the main page.</p>  <div class="highlight highlight-text-html-basic"><pre>    &lt;<span class="pl-ent">html</span>&gt;      &lt;<span class="pl-ent">head</span>&gt;       &lt;/<span class="pl-ent">head</span>&gt;      &lt;/<span class="pl-ent">body</span>&gt;     &lt;<span class="pl-ent">h1</span>&gt; {{name}} &lt;/<span class="pl-ent">h1</span>&gt;      &lt;<span class="pl-ent">h3</span>&gt; {{quote}} &lt;/<span class="pl-ent">h3</span>&gt;       &lt;/<span class="pl-ent">body</span>&gt;      &lt;/<span class="pl-ent">html</span>&gt;</pre></div>  <h4><a id="user-content-quoteapppy" class="anchor" href="#quoteapppy" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>quote/app.py</h4>  <p>It uses sqlite3 to hold the database of quotes. The database initialization could be placed in another file for consistency if it were a more complicated application.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">from</span> untwisted.plugins.rapidserv <span class="pl-k">import</span> RapidServ, make <span class="pl-k">import</span> sqlite3  <span class="pl-c1">DB_FILENAME</span> <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">'</span>DB<span class="pl-pds">'</span></span> <span class="pl-c1">DB</span>          <span class="pl-k">=</span> sqlite3.connect(make(<span class="pl-c1">__file__</span>, <span class="pl-c1">DB_FILENAME</span>)) app         <span class="pl-k">=</span> RapidServ(<span class="pl-c1">__file__</span>) <span class="pl-c1">DB</span>.execute(<span class="pl-s"><span class="pl-pds">'</span>CREATE TABLE IF NOT EXISTS quotes (id  INTEGER PRIMARY KEY, name TEXT, quote TEXT)<span class="pl-pds">'</span></span>) <span class="pl-c1">DB</span>.commit()  <span class="pl-en">@app.request</span>(<span class="pl-s"><span class="pl-pds">'</span>GET /<span class="pl-pds">'</span></span>) <span class="pl-k">def</span> <span class="pl-en">send_base</span>(<span class="pl-smi">con</span>, <span class="pl-smi">request</span>):     rst <span class="pl-k">=</span> <span class="pl-c1">DB</span>.execute(<span class="pl-s"><span class="pl-pds">'</span>SELECT * FROM quotes<span class="pl-pds">'</span></span>)     con.render(<span class="pl-s"><span class="pl-pds">'</span>show.jinja<span class="pl-pds">'</span></span>, <span class="pl-v">posts</span> <span class="pl-k">=</span> rst.fetchall())     con.done()  <span class="pl-en">@app.request</span>(<span class="pl-s"><span class="pl-pds">'</span>GET /load_index<span class="pl-pds">'</span></span>) <span class="pl-k">def</span> <span class="pl-en">load_index</span>(<span class="pl-smi">con</span>, <span class="pl-smi">request</span>):     index        <span class="pl-k">=</span> request.query[<span class="pl-s"><span class="pl-pds">'</span>index<span class="pl-pds">'</span></span>]     rst          <span class="pl-k">=</span> <span class="pl-c1">DB</span>.execute(<span class="pl-s"><span class="pl-pds">'</span>SELECT name, quote FROM quotes where id=?<span class="pl-pds">'</span></span>, index)     name, quote  <span class="pl-k">=</span> rst.fetchone()     con.render(<span class="pl-s"><span class="pl-pds">'</span>view.jinja<span class="pl-pds">'</span></span>, <span class="pl-v">name</span><span class="pl-k">=</span>name, <span class="pl-v">quote</span><span class="pl-k">=</span>quote)     con.done()  <span class="pl-en">@app.request</span>(<span class="pl-s"><span class="pl-pds">'</span>GET /add_quote<span class="pl-pds">'</span></span>) <span class="pl-k">def</span> <span class="pl-en">add_quote</span>(<span class="pl-smi">con</span>, <span class="pl-smi">request</span>):     name      <span class="pl-k">=</span> request.query[<span class="pl-s"><span class="pl-pds">'</span>name<span class="pl-pds">'</span></span>][<span class="pl-c1">0</span>]     quote     <span class="pl-k">=</span> request.query[<span class="pl-s"><span class="pl-pds">'</span>quote<span class="pl-pds">'</span></span>][<span class="pl-c1">0</span>]     <span class="pl-c1">DB</span>.execute(<span class="pl-s"><span class="pl-pds">"</span>INSERT INTO quotes (name, quote) VALUES <span class="pl-c1">\xs</span><span class="pl-pds">"</span></span> <span class="pl-k">\x</span> <span class="pl-c1">repr</span>((name, quote)))     <span class="pl-c1">DB</span>.commit()     send_base(con, request)  <span class="pl-k">if</span> <span class="pl-c1">__name__</span> <span class="pl-k">==</span> <span class="pl-s"><span class="pl-pds">'</span>__main__<span class="pl-pds">'</span></span>:     app.run()</pre></div>  <h4><a id="user-content-running" class="anchor" href="#running" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Running</h4>  <p>In order to run the app, issue the command below.</p>  <pre><code>python2 app.py --addr '0.0.0.0' --port 1234 </code></pre>  <h3><a id="user-content-imup-applicaiton" class="anchor" href="#imup-applicaiton" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Imup Applicaiton</h3>  <p>Imup is a simple application to upload images into a shelve database. It shows the usage of the decorator <strong>app.route</strong> that is used a shorthand to access query parameters from the request.</p>  <p>First of all it is needed to create the application folder.</p>  <pre><code>mkdir imup cd imup mkdir templates </code></pre>  <p>Let us implement the template.</p>  <h4><a id="user-content-imuptemplatesviewjinja" class="anchor" href="#imuptemplatesviewjinja" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>imup/templates/view.jinja</h4>  <div class="highlight highlight-text-html-basic"><pre>    &lt;!DOCTYPE HTML&gt;     &lt;<span class="pl-ent">html</span>&gt;     &lt;<span class="pl-ent">head</span>&gt;     &lt;<span class="pl-ent">meta</span> <span class="pl-e">http-equiv</span>=<span class="pl-s"><span class="pl-pds">"</span>content-type<span class="pl-pds">"</span></span> <span class="pl-e">content</span>=<span class="pl-s"><span class="pl-pds">"</span>text/html; charset=ISO-8859-1<span class="pl-pds">"</span></span>&gt;      &lt;<span class="pl-ent">title</span>&gt;     imup     &lt;/<span class="pl-ent">title</span>&gt;      &lt;/<span class="pl-ent">head</span>&gt;      &lt;<span class="pl-ent">body</span>&gt;     &lt;<span class="pl-ent">b</span>&gt; Max Image Size 1024 * 5024 bytes &lt;/<span class="pl-ent">b</span>&gt;     &lt;<span class="pl-ent">br</span>&gt;      &lt;<span class="pl-ent">br</span>&gt; &lt;<span class="pl-ent">h1</span>&gt; Upload image &lt;/<span class="pl-ent">h1</span>&gt;     &lt;<span class="pl-ent">form</span> <span class="pl-e">action</span>=<span class="pl-s"><span class="pl-pds">"</span>/add_image<span class="pl-pds">"</span></span> <span class="pl-e">method</span>=<span class="pl-s"><span class="pl-pds">"</span>post<span class="pl-pds">"</span></span> <span class="pl-e">enctype</span>=<span class="pl-s"><span class="pl-pds">"</span>multipart/form-data<span class="pl-pds">"</span></span>&gt;     &lt;<span class="pl-ent">input</span> <span class="pl-e">name</span>=<span class="pl-s"><span class="pl-pds">"</span>file<span class="pl-pds">"</span></span> <span class="pl-e">type</span>=<span class="pl-s"><span class="pl-pds">"</span>file<span class="pl-pds">"</span></span>&gt; &lt;<span class="pl-ent">br</span>&gt; &lt;<span class="pl-ent">br</span>&gt;     &lt;<span class="pl-ent">input</span> <span class="pl-e">type</span>=<span class="pl-s"><span class="pl-pds">"</span>submit<span class="pl-pds">"</span></span> <span class="pl-e">value</span>=<span class="pl-s"><span class="pl-pds">"</span>Send<span class="pl-pds">"</span></span>&gt;     &lt;/<span class="pl-ent">form</span>&gt;      &lt;<span class="pl-ent">br</span>&gt;      &lt;<span class="pl-ent">br</span>&gt;      &lt;<span class="pl-ent">h1</span>&gt; Images &lt;/<span class="pl-ent">h1</span>&gt;      {\x for index in posts \x}          &lt;<span class="pl-ent">h3</span>&gt; {{index}} &lt;/<span class="pl-ent">h3</span>&gt;         &lt;<span class="pl-ent">img</span> <span class="pl-e">src</span>=<span class="pl-s"><span class="pl-pds">"</span>/load_index?index={{index}}<span class="pl-pds">"</span></span>/&gt;       {\x endfor \x}       &lt;/<span class="pl-ent">body</span>&gt;     &lt;/<span class="pl-ent">html</span>&gt;</pre></div>  <p>The template above will be loaded when the user access the base site <strong>/</strong>.</p>  <p>The code below is used to add a image to the database by using the method <strong>post</strong></p>  <div class="highlight highlight-text-html-basic"><pre>    &lt;<span class="pl-ent">br</span>&gt; &lt;<span class="pl-ent">h1</span>&gt; Upload image &lt;/<span class="pl-ent">h1</span>&gt;     &lt;<span class="pl-ent">form</span> <span class="pl-e">action</span>=<span class="pl-s"><span class="pl-pds">"</span>/add_image<span class="pl-pds">"</span></span> <span class="pl-e">method</span>=<span class="pl-s"><span class="pl-pds">"</span>post<span class="pl-pds">"</span></span> <span class="pl-e">enctype</span>=<span class="pl-s"><span class="pl-pds">"</span>multipart/form-data<span class="pl-pds">"</span></span>&gt;     &lt;<span class="pl-ent">input</span> <span class="pl-e">name</span>=<span class="pl-s"><span class="pl-pds">"</span>file<span class="pl-pds">"</span></span> <span class="pl-e">type</span>=<span class="pl-s"><span class="pl-pds">"</span>file<span class="pl-pds">"</span></span>&gt; &lt;<span class="pl-ent">br</span>&gt; &lt;<span class="pl-ent">br</span>&gt;     &lt;<span class="pl-ent">input</span> <span class="pl-e">type</span>=<span class="pl-s"><span class="pl-pds">"</span>submit<span class="pl-pds">"</span></span> <span class="pl-e">value</span>=<span class="pl-s"><span class="pl-pds">"</span>Send<span class="pl-pds">"</span></span>&gt;     &lt;/<span class="pl-ent">form</span>&gt;</pre></div>  <p>This code is used to send a query string to the <strong>/load_index</strong> view to get the image data based on an index.</p>  <div class="highlight highlight-text-html-basic"><pre>&lt;<span class="pl-ent">h1</span>&gt; Images &lt;/<span class="pl-ent">h1</span>&gt;  {\x for index in posts \x}      &lt;<span class="pl-ent">h3</span>&gt; {{index}} &lt;/<span class="pl-ent">h3</span>&gt;     &lt;<span class="pl-ent">img</span> <span class="pl-e">src</span>=<span class="pl-s"><span class="pl-pds">"</span>/load_index?index={{index}}<span class="pl-pds">"</span></span>/&gt;   {\x endfor \x}</pre></div>  <p>The implementation of the app is straightforward now. </p>  <h4><a id="user-content-imupapppy" class="anchor" href="#imupapppy" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>imup/app.py</h4>  <div class="highlight highlight-source-python"><pre><span class="pl-k">from</span> untwisted.plugins.rapidserv <span class="pl-k">import</span> RapidServ, make, HttpRequestHandle <span class="pl-k">import</span> shelve  <span class="pl-c1">DB_FILENAME</span> <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">'</span>DB<span class="pl-pds">'</span></span> <span class="pl-c1">DB</span>          <span class="pl-k">=</span> shelve.open(make(<span class="pl-c1">__file__</span>, <span class="pl-c1">DB_FILENAME</span>)) HttpRequestHandle.<span class="pl-c1">MAX_SIZE</span> <span class="pl-k">=</span> <span class="pl-c1">1024</span> <span class="pl-k">*</span> <span class="pl-c1">1024</span> <span class="pl-k">*</span> <span class="pl-c1">3</span> app    <span class="pl-k">=</span> RapidServ(<span class="pl-c1">__file__</span>)  <span class="pl-en">@app.overflow</span> <span class="pl-k">def</span> <span class="pl-en">response</span>(<span class="pl-smi">con</span>, <span class="pl-smi">request</span>):     con.set_response(<span class="pl-s"><span class="pl-pds">'</span>HTTP/1.1 400 Bad request<span class="pl-pds">'</span></span>)     <span class="pl-c1">HTML</span> <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">'</span>&lt;html&gt; &lt;body&gt; &lt;h1&gt; Bad request &lt;/h1&gt; &lt;/body&gt; &lt;/html&gt;<span class="pl-pds">'</span></span>     con.add_data(<span class="pl-c1">HTML</span>)     con.done()  <span class="pl-en">@app.route</span>(<span class="pl-s"><span class="pl-pds">'</span>GET /<span class="pl-pds">'</span></span>) <span class="pl-k">def</span> <span class="pl-en">index</span>(<span class="pl-smi">con</span>):     con.render(<span class="pl-s"><span class="pl-pds">'</span>view.jinja<span class="pl-pds">'</span></span>, <span class="pl-v">posts</span> <span class="pl-k">=</span> <span class="pl-c1">DB</span>.iterkeys())     con.done()  <span class="pl-en">@app.route</span>(<span class="pl-s"><span class="pl-pds">'</span>GET /load_index<span class="pl-pds">'</span></span>) <span class="pl-k">def</span> <span class="pl-en">load_index</span>(<span class="pl-smi">con</span>, <span class="pl-smi">index</span>):     con.add_data(<span class="pl-c1">DB</span>[index[<span class="pl-c1">0</span>]], <span class="pl-v">mimetype</span><span class="pl-k">=</span><span class="pl-s"><span class="pl-pds">'</span>image/jpeg<span class="pl-pds">'</span></span>)     con.done()  <span class="pl-en">@app.route</span>(<span class="pl-s"><span class="pl-pds">'</span>POST /add_image<span class="pl-pds">'</span></span>) <span class="pl-k">def</span> <span class="pl-en">add_image</span>(<span class="pl-smi">con</span>, <span class="pl-smi">file</span>):     <span class="pl-c1">DB</span>[<span class="pl-v">file</span>.filename] <span class="pl-k">=</span> <span class="pl-v">file</span>.file.read()     index(con)  <span class="pl-k">if</span> <span class="pl-c1">__name__</span> <span class="pl-k">==</span> <span class="pl-s"><span class="pl-pds">'</span>__main__<span class="pl-pds">'</span></span>:     app.run()</pre></div>  <p>It sets the max size for images being uploaded.</p>  <div class="highlight highlight-source-python"><pre>HttpRequestHandle.<span class="pl-c1">MAX_SIZE</span> <span class="pl-k">=</span> <span class="pl-c1">1024</span> <span class="pl-k">*</span> <span class="pl-c1">1024</span> <span class="pl-k">*</span> <span class="pl-c1">3</span></pre></div>  <p>If an user attempts to upload an image that is larger than the specified then this view is called.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-en">@app.overflow</span> <span class="pl-k">def</span> <span class="pl-en">response</span>(<span class="pl-smi">con</span>, <span class="pl-smi">request</span>):     con.set_response(<span class="pl-s"><span class="pl-pds">'</span>HTTP/1.1 400 Bad request<span class="pl-pds">'</span></span>)     <span class="pl-c1">HTML</span> <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">'</span>&lt;html&gt; &lt;body&gt; &lt;h1&gt; Bad request &lt;/h1&gt; &lt;/body&gt; &lt;/html&gt;<span class="pl-pds">'</span></span>     con.add_data(<span class="pl-c1">HTML</span>)     con.done()</pre></div>  <p>When the user sends a request like:</p>  <pre><code>GET /load_index?index=10 </code></pre>  <p>Then the view below is called.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-en">@app.route</span>(<span class="pl-s"><span class="pl-pds">'</span>GET /load_index<span class="pl-pds">'</span></span>) <span class="pl-k">def</span> <span class="pl-en">load_index</span>(<span class="pl-smi">con</span>, <span class="pl-smi">index</span>):     con.add_data(<span class="pl-c1">DB</span>[index[<span class="pl-c1">0</span>]], <span class="pl-v">mimetype</span><span class="pl-k">=</span><span class="pl-s"><span class="pl-pds">'</span>image/jpeg<span class="pl-pds">'</span></span>)     con.done()</pre></div>  <p>The <strong>index</strong> variable will hold <strong>10</strong></p>  <p>This handle is used to store the image into the database.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-en">@app.route</span>(<span class="pl-s"><span class="pl-pds">'</span>POST /add_image<span class="pl-pds">'</span></span>) <span class="pl-k">def</span> <span class="pl-en">add_image</span>(<span class="pl-smi">con</span>, <span class="pl-smi">file</span>):     <span class="pl-c1">DB</span>[<span class="pl-v">file</span>.filename] <span class="pl-k">=</span> <span class="pl-v">file</span>.file.read()     index(con)</pre></div>  <p>The file variable holds a <strong>cgi.FieldStorage</strong> instance, notice that the name <strong>file</strong> was used when implementing the template <strong>imup/templates/view.jinja</strong></p>  <div class="highlight highlight-text-html-basic"><pre>    &lt;<span class="pl-ent">input</span> <span class="pl-e">name</span>=<span class="pl-s"><span class="pl-pds">"</span>file<span class="pl-pds">"</span></span> <span class="pl-e">type</span>=<span class="pl-s"><span class="pl-pds">"</span>file<span class="pl-pds">"</span></span>&gt;</pre></div>  <h3><a id="user-content-quickserv-script" class="anchor" href="#quickserv-script" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>quickserv script</h3>  <h1><a id="user-content-the-requests-plugin" class="anchor" href="#the-requests-plugin" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>The requests plugin</h1>  <h1><a id="user-content-the-event-driven-paradigm" class="anchor" href="#the-event-driven-paradigm" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>The event-driven paradigm</h1>  <p>The event-driven paradigm is a powerful tool to deal with some specific systems, in the event-driven paradigm the flow of the program is based on events. Events are intrinsically related to handles, if there is a handle mapped to an event and such an event occurs then the handle is called. An event can carry arguments that better characterize the type of happening that is related to the event. </p>  <p>In untwisted context, events can be any kind of python object, an integer, a function, a class, an exception etc. It is possible to map one or more handles to a given event, when the event occurs then the handles will be called with the event's arguments.</p>  <p>In event-driven applications there will exist generally an event loop that is responsible by processing a set of handles according to some set of events. Untwisted reactor is responsible by processing a set of handles according to a few basic events. These basic events are related to the state of a given set of sockets. So, when a socket is ready to send data it spawns an event WRITE, when there is data available for reading then it spawns READ, etc.</p>  <p>The fact of untwisted being such a powerful approach to implement networking applications consists of being possible to have events that are mapped to handles that spawn other events and so on. It may not sound obvious at first glance why it turns to be useful but it will make more sense later. </p>  <h3><a id="user-content-skeletons" class="anchor" href="#skeletons" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Skeletons</h3>  <p>The diagrams along this document are a way to express superficially interactions between objects that are used to implement networking applications on top of untwisted.</p>  <p>Consider:</p>  <pre><code>Event0  -&gt; Handle0 -&gt; (Event1, Event2) Event1  -&gt; Handle1 Event2  -&gt; Handle2 </code></pre>  <p>The expression:</p>  <pre><code>m -&gt; n </code></pre>  <p>When m and n are either an event or a handle it means that when m is processed then n is processed. A handle is processed when it is called, an event is processed when it merely happens.</p>  <p>Note that the expression:</p>  <pre><code>(Event0, event1, event2, ...) </code></pre>  <p>It means that the sequence of events will be processed.</p>  <p>It is necessary to introduce some notation to simplify the exposition of ideas and facts.</p>  <p>A set of events is denoted by:</p>  <pre><code>{Event0, Event1, Event2, ...} </code></pre>  <p>A set of handles is denoted by:</p>  <pre><code>n = {Handle0, Handle1, Handle2, ...} </code></pre>  <p>The expression:</p>  <pre><code>m =&gt; n </code></pre>  <p>When m is an event and n is a handle then when m is processed it may occur of n being called and vice versa. When m is a set of  events and n is a handle it means that when one of the events happens then it may happen of n being processed. When m is a set of handles and n is an event then when one of the handles is processed it may occur of n being processed.</p>  <p>on the other hand the expression:</p>  <pre><code>m -&gt; n </code></pre>  <p>When m is an event and n is a handle it means when the event is processed then the handle is processed and vice versa. When m is a set of events and n is a handle it means that when one of the events is processed then the handle will be processed. The case where m is a set of handles and n is an event the expression means that whenever one of the handles is called then the event is processed.</p>  <p>The expression:</p>  <pre><code>m = (Event0, Event1, Event2, ...) </code></pre>  <p>It means a sequence of events whose order matters. The same occurs with the sequence of handles.</p>  <pre><code>n = (Handle0, Handle1, Handl2, ...) </code></pre>  <p>The expression:</p>  <pre><code>Handle0 -&gt; (Event0, Event1) </code></pre>  <p>It means that Handle0 will spawn Event0 and Event1 in that exact order. While the expression.</p>  <pre><code>Handle0 -&gt; {Event0, Event1} </code></pre>  <p>It means that Handle0 will spawn Event0 and Event1 but not exactly in that order.</p>  <p>Using this scheme of notation it is possible to describe reasonably well the flow of a program that is implemented using event-driven paradigm. In order to denote arguments that are carried by events, the notation below is used.</p>  <pre><code>Event0 -(arg0, arg1, ...)-&gt; Handle0 </code></pre>  <p>and</p>  <pre><code>Event0 =(arg0, arg1, ...)=&gt; Handle0 </code></pre>  <p>Where the symbols -&gt; and =&gt; have been explained above.</p>  <p>Events are related to the state of some objects, events are mapped to handles and handles can change the state of objects that can then generate events. A socket can be abstracted as a object that can hold a set of possible states. We will be interested initially in the states of it being ready to be read and ready to be written to.</p>  <p>The expressions below need to be related to some object in order to better express systems.</p>  <pre><code>m -&gt; n m =&gt; n </code></pre>  <p>Consider the handles defined below.</p>  <pre><code>H0 = "Open the umbrella" H1 = "Close the umbrella" </code></pre>  <p>These handles are mapped to the events.</p>  <pre><code>E0 = "It starts raining" </code></pre>  <pre><code>E1 = "It stops raining" </code></pre>  <p>So you would have.</p>  <pre><code>H0 -&gt; E0 H1 -&gt; E1 </code></pre>  <p>But it is not the case that everyone would open an umbrella when it starts raining, i particularly hate to carry umbrellas. So, it is related to a specific object in the context it is a given person. A set of relations between events and handles  are always related to a given object or a set of objects.</p>  <p>The notation below is used to denote when a given set of events and handles are related to a given object:</p>  <pre><code>object0 {      Handle0 -&gt; Event0 -&gt; Handle1 -&gt; Event1     Event1 -&gt; Handle2     .     .     .  }  </code></pre>  <p>We'll be interested in specific objects when using untwisted, these are sockets, threads, processes etc. It is interesting notice that handles can be  seen as events and vice versa. </p>  <p>Consider the situation in which a handle is processed and a set of possible events might occur but just once. Such a situation is described using the notation below.</p>  <pre><code>object {     Handle0 -&gt; *{Event0, Event1, Event2, ...}  } </code></pre>  <p>That basically means that if Handle0 is processed then one of the events in the set can be processed but just one and just once. </p>  <p><strong>These diagrams will be used sometimes to explain some untwisted workings.</strong></p>  <h3><a id="user-content-image-of-objectshandles" class="anchor" href="#image-of-objectshandles" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Image of objects/handles</h3>  <p>When a handle that is associated with an object is processed then a set of events may happen, this set of possible events is the handle image. </p>  <pre><code>handle -&gt; {event0, event1, ...} </code></pre>  <p>When an object is processed then a set of possible events may happen, such a set is the image of the object.</p>  <pre><code>object -&gt; {event0, event1, ....} </code></pre>  <h3><a id="user-content-the-symbol-" class="anchor" href="#the-symbol-" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>The symbol **</h3>  <p>Consider a socket connection to a web server, the socket server can be associated to a set of events, let us consider for simplicity it is associated with three events. When the server sends data then the socket server will spawn <strong>LOAD</strong>, when it is possible to write data back to the server then it spawns <strong>WRITE</strong>, if the server closes the socket then it happens the event <strong>CLOSE</strong>. After that event there will occur no more events because the connection is down.</p>  <pre><code>server -&gt; {LOAD, WRITE, **CLOSE} </code></pre>  <p>The event <strong>CLOSE</strong> that is associated with the socket server connection if it happens just once then no more events will be processed for that object.</p>  <h3><a id="user-content-event-arguments" class="anchor" href="#event-arguments" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Event arguments</h3>  <p>Events can carry information that better characterizes the event. The notation to express that is shown below.</p>  <pre><code>LOAD -(str:data)-&gt; handle </code></pre>  <h1><a id="user-content-dispatcher-class" class="anchor" href="#dispatcher-class" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Dispatcher class</h1>  <p>The dispatcher class is responsible by processing handles that are mapped to events. In order to get a  clear picture of how implementing networking applications on top of untwisted it is needed to understand the features of the Dispatcher class. There are other classes that inherit from Dispatcher and these are the used ones to model applications.</p>  <p>A Dispatcher instance is an object that can hold a set of mappings of the type:</p>  <pre><code>Dispatcher {     m0 -&gt; n0 -&gt; m1 ...     m1 -&gt;  n1 -&gt; ...     .     .     . } </code></pre>  <p>The best way to grasp the behavior of Dispatcher objects is testing them in the python interpreter.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">from</span> untwisted.dispatcher <span class="pl-k">import</span> Dispatcher <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher <span class="pl-k">=</span> Dispatcher() <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-c1">dir</span>(dispatcher)  [<span class="pl-s"><span class="pl-pds">'</span>__class__<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>__delattr__<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>__dict__<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>__doc__<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>__format__<span class="pl-pds">'</span></span>,  <span class="pl-s"><span class="pl-pds">'</span>__getattribute__<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>__hash__<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>__init__<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>__module__<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>__new__<span class="pl-pds">'</span></span>,  <span class="pl-s"><span class="pl-pds">'</span>__reduce__<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>__reduce_ex__<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>__repr__<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>__setattr__<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>__sizeof__<span class="pl-pds">'</span></span>,  <span class="pl-s"><span class="pl-pds">'</span>__str__<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>__subclasshook__<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>__weakref__<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>add_handle<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>add_map<span class="pl-pds">'</span></span>,  <span class="pl-s"><span class="pl-pds">'</span>add_static_map<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>base<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>del_handle<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>del_map<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>del_static_map<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>drive<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>pool<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>process_base<span class="pl-pds">'</span></span>]</pre></div>  <p>The methods 'add_map' and 'del_handle' are the most used ones. These methods are used to bind handles to events that are related to the given Dispatcher object. </p>  <p>As handles and events are related to objects, objects may be related between each other in some way. A given object may change the state of other object then an event happens. The method 'drive' of the Dispatcher class is used to fire an event in the Dispatcher object. Once an event is fired in a given Dispatcher object then all handles associated with that event will be processed. As mentioned before, events can carry arguments that better characterize the event, the 'drive' method permits to fire events with a given set of arguments associated to the event.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.drive(<span class="pl-s"><span class="pl-pds">'</span>RAINING<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>Brasil<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>Rio de Janeiro<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>Rio das ostras<span class="pl-pds">'</span></span>)</pre></div>  <p>The above code spawns an event named 'RAINING' with three arguments that correspond to the country, state and city that characterizes the event.</p>  <p>Events in untwisted can be all kind of python objects. Handles can be all kind of objects that are callable.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">def</span> <span class="pl-en">handle0</span>(<span class="pl-smi">dispatcher</span>, <span class="pl-smi">country</span>, <span class="pl-smi">state</span>, <span class="pl-smi">city</span>): <span class="pl-c1">...</span>     <span class="pl-c1">print</span> <span class="pl-s"><span class="pl-pds">'</span>It is raining in <span class="pl-c1">\xs</span>, <span class="pl-c1">\xs</span>, <span class="pl-c1">\xs</span><span class="pl-pds">'</span></span> <span class="pl-k">\x</span> (country, state, city) <span class="pl-c1">...</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.add_map(<span class="pl-s"><span class="pl-pds">'</span>RAINING<span class="pl-pds">'</span></span>, handle0)</pre></div>  <p>The above code adds a mapping between the event 'RAINING' and the callback 'handle0'. Now if the event 'RAINING' occurs then the callback will be called with the arguments.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.drive(<span class="pl-s"><span class="pl-pds">'</span>RAINING<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>Brazil<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>Rio de janeiro<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>Rio das ostras<span class="pl-pds">'</span></span>) It <span class="pl-k">is</span> raining <span class="pl-k">in</span> Brazil, Rio de janeiro, Rio das ostras <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> </pre></div>  <p>Let us define a new callback and maps to the 'RAINING' event then check out what happens.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">def</span> <span class="pl-en">handle1</span>(<span class="pl-smi">dispatcher</span>, <span class="pl-smi">country</span>, <span class="pl-smi">state</span>, <span class="pl-smi">city</span>): <span class="pl-c1">...</span>     <span class="pl-k">if</span> country <span class="pl-k">==</span> <span class="pl-s"><span class="pl-pds">'</span>Brazil<span class="pl-pds">'</span></span> <span class="pl-k">and</span> \ <span class="pl-c1">...</span>                state <span class="pl-k">==</span> <span class="pl-s"><span class="pl-pds">'</span>Rio de janeiro<span class="pl-pds">'</span></span> <span class="pl-k">and</span> \ <span class="pl-c1">...</span>                         city <span class="pl-k">==</span> <span class="pl-s"><span class="pl-pds">'</span>Rio das ostras<span class="pl-pds">'</span></span>: <span class="pl-c1">...</span>         <span class="pl-c1">print</span> <span class="pl-s"><span class="pl-pds">'</span>It is raining in hell<span class="pl-pds">'</span></span> <span class="pl-c1">...</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.add_map(<span class="pl-s"><span class="pl-pds">'</span>RAINING<span class="pl-pds">'</span></span>, handle1) <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.drive(<span class="pl-s"><span class="pl-pds">'</span>RAINING<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>Brazil<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>Minas gerais<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>Belo horizonte<span class="pl-pds">'</span></span>) It <span class="pl-k">is</span> raining <span class="pl-k">in</span> Brazil, Minas gerais, Belo horizonte <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.drive(<span class="pl-s"><span class="pl-pds">'</span>RAINING<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>Brazil<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>Rio de janeiro<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>Rio das ostras<span class="pl-pds">'</span></span>) It <span class="pl-k">is</span> raining <span class="pl-k">in</span> Brazil, Rio de janeiro, Rio das ostras It <span class="pl-k">is</span> raining <span class="pl-k">in</span> hell <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> </pre></div>  <p>There is other way to add a mapping between an event and a handle to a Dispatcher object it is using the xmap function. This function is merely a synonymous for 'add_map'.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">from</span> untwisted.dispatcher <span class="pl-k">import</span> Dispatcher, xmap, spawn <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher <span class="pl-k">=</span> Dispatcher() <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">def</span> <span class="pl-en">on_alpha</span>(<span class="pl-smi">dispatcher</span>): <span class="pl-c1">...</span>     <span class="pl-c1">print</span> <span class="pl-s"><span class="pl-pds">'</span>Event ALPHA occured<span class="pl-pds">'</span></span> <span class="pl-c1">...</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> xmap(dispatcher, <span class="pl-s"><span class="pl-pds">'</span>ALPHA<span class="pl-pds">'</span></span>, on_alpha) <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> </pre></div>  <p>The reasons to use 'xmap' function instead of add_map are aestheticals.  The same occurs when firing events.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> spawn(dispatcher, <span class="pl-s"><span class="pl-pds">'</span>ALPHA<span class="pl-pds">'</span></span>) Event <span class="pl-c1">ALPHA</span> occured <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> spawn(dispatcher, <span class="pl-s"><span class="pl-pds">'</span>BETA<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>arg1<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>arg2<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>arg3<span class="pl-pds">'</span></span>) <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> </pre></div>  <h3><a id="user-content-event-creation" class="anchor" href="#event-creation" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Event creation</h3>  <p>Events can be any kind of python objects but it is interesting to have a reliable scheme  to define new events. Untwisted implements the 'get_event' function that returns a unique event.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">from</span> untwisted.event <span class="pl-k">import</span> get_event <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-c1">LOAD</span> <span class="pl-k">=</span> get_event() <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-c1">print</span> <span class="pl-c1">LOAD</span> <span class="pl-c1">24</span> <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-c1">FOUND</span> <span class="pl-k">=</span> get_event() <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-c1">print</span> <span class="pl-c1">FOUND</span> <span class="pl-c1">25</span> <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> </pre></div>  <p>These events are used for situations where the usage of strings wouldn't be interesting  or ambiguous in some circumstances.</p>  <h3><a id="user-content-spawning-events-from-handles" class="anchor" href="#spawning-events-from-handles" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Spawning events from handles</h3>  <p>Handles that are mapped to events can spawn events inside objects. </p>  <p>The code below clarifies better:</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">from</span> untwisted.dispatcher <span class="pl-k">import</span> Dispatcher <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">from</span> untwisted.event <span class="pl-k">import</span> <span class="pl-c1">LOAD</span> <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher <span class="pl-k">=</span> Dispatcher() <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">def</span> <span class="pl-en">on_load</span>(<span class="pl-smi">dispatcher</span>, <span class="pl-smi">data</span>): <span class="pl-c1">...</span>     cmd <span class="pl-k">=</span> data.split(<span class="pl-s"><span class="pl-pds">'</span> <span class="pl-pds">'</span></span>) <span class="pl-c1">...</span>     dispatcher.drive(cmd.pop(<span class="pl-c1">0</span>), cmd) <span class="pl-c1">...</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.add_map(<span class="pl-c1">LOAD</span>, on_load) <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> </pre></div>  <p>Let us drive a LOAD event inside that dispatcher object.  </p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">def</span> <span class="pl-en">on_add</span>(<span class="pl-smi">dispatcher</span>, <span class="pl-smi">args</span>): <span class="pl-c1">...</span>     <span class="pl-c1">print</span> <span class="pl-s"><span class="pl-pds">'</span>Sum:<span class="pl-pds">'</span></span>, <span class="pl-c1">sum</span>(<span class="pl-c1">map</span>(<span class="pl-c1">int</span>, args)) <span class="pl-c1">...</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.add_map(<span class="pl-s"><span class="pl-pds">'</span>add<span class="pl-pds">'</span></span>, on_add) <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.drive(<span class="pl-c1">LOAD</span>, <span class="pl-s"><span class="pl-pds">'</span>add 1 1 2<span class="pl-pds">'</span></span>) Sum: <span class="pl-c1">4</span></pre></div>  <p>It creates a new handle named 'on_add' and maps it to the event 'add'.</p>  <h3><a id="user-content-passing-additional-arguments-to-handles" class="anchor" href="#passing-additional-arguments-to-handles" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Passing additional arguments to handles</h3>  <p>There will occur situations that it is necessary to pass addional information to a handle that is called when an event occurs.  The example below examplifies:</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">from</span> untwisted.event <span class="pl-k">import</span> <span class="pl-c1">DONE</span> <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher <span class="pl-k">=</span> Dispatcher() <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">def</span> <span class="pl-en">on_done</span>(<span class="pl-smi">dispatcher</span>, <span class="pl-smi">data</span>, <span class="pl-smi">value</span>): <span class="pl-c1">...</span>     <span class="pl-c1">print</span> data, value <span class="pl-c1">...</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.add_map(<span class="pl-c1">DONE</span>, on_done, <span class="pl-c1">100</span>) <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.drive(<span class="pl-c1">DONE</span>, <span class="pl-s"><span class="pl-pds">'</span>Tau<span class="pl-pds">'</span></span>) Tau <span class="pl-c1">100</span> <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> </pre></div>  <p>That example looks useless under a perspective but is enough to explain the feature. You'll find yourself passing extra arguments to handles a lot of times in some applications.  Notice that if you call the method drive with more arguments then you'll get an exception.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.drive(<span class="pl-c1">DONE</span>, <span class="pl-c1">1000</span>, <span class="pl-c1">1200</span>) Traceback (most recent call last):   File <span class="pl-s"><span class="pl-pds">"</span>/usr/lib/python2.7/site-packages/untwisted/dispatcher.py<span class="pl-pds">"</span></span>, line <span class="pl-c1">34</span>, <span class="pl-k">in</span> process_base     seq <span class="pl-k">=</span> handle(<span class="pl-v">self</span>, <span class="pl-k">*</span>(args <span class="pl-k"> </span> data)) <span class="pl-c1">TypeError</span>: on_done() takes exactly <span class="pl-c1">3</span> arguments (<span class="pl-c1">4</span> given) <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> </pre></div>  <p>When it is not known the number of arguments of the event then it is useful to implement the handle with.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">def</span> <span class="pl-en">on_event</span>(<span class="pl-smi">dispatcher</span>, <span class="pl-k">*</span><span class="pl-smi">args</span>):     <span class="pl-k">pass</span></pre></div>  <h3><a id="user-content-unbinding-handles" class="anchor" href="#unbinding-handles" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Unbinding handles</h3>  <p>As it is useful to add mappings it is useful to remove them. Removing a mapping may avoid a chain of events of being processed, there are circumstances where that is necessary as well.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">from</span> untwisted.dispatcher <span class="pl-k">import</span> Dispatcher <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">from</span> untwisted.event <span class="pl-k">import</span> <span class="pl-c1">LOAD</span> <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span>  dispatcher <span class="pl-k">=</span> Dispatcher() <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">def</span> <span class="pl-en">on_load</span>(<span class="pl-smi">dispatcher</span>, <span class="pl-smi">data</span>): <span class="pl-c1">...</span>     <span class="pl-c1">print</span> <span class="pl-s"><span class="pl-pds">'</span>LOAD event occured:<span class="pl-pds">'</span></span>, data <span class="pl-c1">...</span>     dispatcher.del_map(<span class="pl-c1">LOAD</span>, on_load) <span class="pl-c1">...</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.add_map(<span class="pl-c1">LOAD</span>, on_load) <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.drive(<span class="pl-c1">LOAD</span>, <span class="pl-s"><span class="pl-pds">'</span>cd /glau<span class="pl-pds">'</span></span>) <span class="pl-c1">LOAD</span> event occured: cd <span class="pl-k">/</span>glau <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.drive(<span class="pl-c1">LOAD</span>, <span class="pl-s"><span class="pl-pds">'</span>ls<span class="pl-pds">'</span></span>) <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> </pre></div>  <p>The method 'del_map' is used to remove a mapping from a Dispatcher object. In the above code, the handle 'on_load' will be processed just once for the event LOAD.</p>  <h3><a id="user-content-exceptions-in-handles" class="anchor" href="#exceptions-in-handles" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Exceptions in handles</h3>  <p>When a given handle is called it will process the event arguments and eventually it may occur an exception inside the handle. The event loop can't stop due to that exception being raised because it is advantageous under some perspectives to keep the reactor processing other events. There will exist situations that it will not be advantageous to keep the reactor processing a given list of handles for a given event, in that case there are specific exceptions that can be raised to change the flow of the events it means avoiding some events to occur or having more events to occur. So, in untwisted, the flow of the events can be controlled with a set of specific exceptions.</p>  <p>The way of how untwisted is used to model applications doesn't permit to catch exceptions as it is usually done.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">from</span> untwisted.dispatcher <span class="pl-k">import</span> Dispatcher <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher <span class="pl-k">=</span> Dispatcher() <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">def</span> <span class="pl-en">handle</span>(<span class="pl-smi">dispatcher</span>, <span class="pl-smi">x</span>, <span class="pl-smi">y</span>): <span class="pl-c1">...</span>     <span class="pl-c1">print</span> x<span class="pl-k">/</span>y <span class="pl-c1">...</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.add_map(<span class="pl-s"><span class="pl-pds">'</span>div<span class="pl-pds">'</span></span>, handle) <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.drive(<span class="pl-s"><span class="pl-pds">'</span>div<span class="pl-pds">'</span></span>, <span class="pl-c1">1</span>, <span class="pl-c1">2</span>) <span class="pl-c1">0</span></pre></div>  <p>That's expected, what about if the event carried the values 1 and 0?</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.drive(<span class="pl-s"><span class="pl-pds">'</span>div<span class="pl-pds">'</span></span>, <span class="pl-c1">1</span>, <span class="pl-c1">0</span>) Traceback (most recent call last):   File <span class="pl-s"><span class="pl-pds">"</span>/usr/lib/python2.7/site-packages/untwisted/dispatcher.py<span class="pl-pds">"</span></span>, line <span class="pl-c1">34</span>, <span class="pl-k">in</span> process_base     seq <span class="pl-k">=</span> handle(<span class="pl-v">self</span>, <span class="pl-k">*</span>(args <span class="pl-k"> </span> data))   File <span class="pl-s"><span class="pl-pds">"</span>&lt;stdin&gt;<span class="pl-pds">"</span></span>, line <span class="pl-c1">2</span>, <span class="pl-k">in</span> handle <span class="pl-c1">ZeroDivisionError</span>: integer division <span class="pl-k">or</span> modulo by zero <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> </pre></div>  <p>When we call a function or class method that could throw an exception it is natural to use a try/except block to catch the exceptioin then decide what to do based on the exception type. When modelling applications using untwisted one would use the decorator 'handle_exception' to catch exceptions that might happen from handle calls.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">from</span> untwisted.dispatcher <span class="pl-k">import</span> Dispatcher <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">from</span> untwisted.tools <span class="pl-k">import</span> handle_exception <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher <span class="pl-k">=</span> Dispatcher() <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">@</span>handle_exception(<span class="pl-c1">ZeroDivisionError</span>) <span class="pl-c1">...</span> <span class="pl-k">def</span> <span class="pl-en">handle</span>(<span class="pl-smi">dispatcher</span>, <span class="pl-smi">x</span>, <span class="pl-smi">y</span>): <span class="pl-c1">...</span>     <span class="pl-c1">print</span> x<span class="pl-k">/</span>y <span class="pl-c1">...</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.add_map(<span class="pl-s"><span class="pl-pds">'</span>div<span class="pl-pds">'</span></span>, handle) <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> </pre></div>  <p>The decorator 'handle_exception' solves the problem of the unhandled exception. When spawning the 'div' event with values that could cause an exception it will not be printed.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.drive(<span class="pl-s"><span class="pl-pds">'</span>div<span class="pl-pds">'</span></span>, <span class="pl-c1">4</span>, <span class="pl-c1">2</span>) <span class="pl-c1">2</span> <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.drive(<span class="pl-s"><span class="pl-pds">'</span>div<span class="pl-pds">'</span></span>, <span class="pl-c1">1</span>, <span class="pl-c1">0</span>) <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> </pre></div>  <p>However, it is not the case that avoiding the exception of being printed is enough, it is important to have other parts of the code being noticed of the exception. The decorator 'handle_exception' turns an exception that occured inside a handle into an event of the type (handle, exception).</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">def</span> <span class="pl-en">on_zero_division_error</span>(<span class="pl-smi">dispatcher</span>, <span class="pl-smi">excpt</span>): <span class="pl-c1">...</span>     <span class="pl-c1">print</span> <span class="pl-s"><span class="pl-pds">'</span>The exception was thrown:<span class="pl-pds">'</span></span>, excpt <span class="pl-c1">...</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.add_map((handle, <span class="pl-c1">ZeroDivisionError</span>), on_zero_division_error) <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.drive(<span class="pl-s"><span class="pl-pds">'</span>div<span class="pl-pds">'</span></span>, <span class="pl-c1">1</span>, <span class="pl-c1">0</span>) The exception was thrown: integer division <span class="pl-k">or</span> modulo by zero</pre></div>  <p>In the code above, the handle 'on_zero_division-error' was defined to catch the exception 'ZeroDivisionError' that could occur inside the 'handle' function that does the division of two numbers when the 'div' event occurs. Using this approach it is possible to have one or more handles deciding what to do when an exception occurs at some point of the program it increases extensibility and turns modelling of applications more succint and modular.</p>  <h3><a id="user-content-the-kill-root-exceptions" class="anchor" href="#the-kill-root-exceptions" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>The Kill, Root exceptions</h3>  <h3><a id="user-content-handle-returns" class="anchor" href="#handle-returns" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Handle returns</h3>  <p>When handles are called on events, they aren't supposed to return a value that is advantaged by other parts of the program unless it is explicitly defined using the 'mapcall' decorator.</p>  <p>Consider the example below:</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">from</span> untwisted.dispatcher <span class="pl-k">import</span> Dispatcher <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher <span class="pl-k">=</span> Dispatcher() <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">def</span> <span class="pl-en">handle</span>(<span class="pl-smi">dispatcher</span>, <span class="pl-smi">x</span>, <span class="pl-smi">y</span>): <span class="pl-c1">...</span>     <span class="pl-k">return</span> x<span class="pl-k">/</span>y <span class="pl-c1">...</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.add_map(<span class="pl-s"><span class="pl-pds">'</span>div<span class="pl-pds">'</span></span>, handle) <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.drive(<span class="pl-s"><span class="pl-pds">'</span>div<span class="pl-pds">'</span></span>, <span class="pl-c1">4</span>, <span class="pl-c1">2</span>) <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> </pre></div>  <p>Nothing happened as expected. It is possible to turn handle into an event by using the 'mapcall' decorator. So, when handle is processed then an event is processed which corresponds to the handle function. The event carries the return value of the function handle. </p>  <p>Using 'mapcall' in the code above:</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">from</span> untwisted.dispatcher <span class="pl-k">import</span> Dispatcher <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">from</span> untwisted.tools <span class="pl-k">import</span> mapcall <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher <span class="pl-k">=</span> Dispatcher() <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">@</span>mapcall(<span class="pl-c1">ZeroDivisionError</span>) <span class="pl-c1">...</span> <span class="pl-k">def</span> <span class="pl-en">handle</span>(<span class="pl-smi">dispatcher</span>, <span class="pl-smi">x</span>, <span class="pl-smi">y</span>): <span class="pl-c1">...</span>     <span class="pl-k">return</span> x<span class="pl-k">/</span>y <span class="pl-c1">...</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">def</span> <span class="pl-en">on_handle</span>(<span class="pl-smi">dispatcher</span>, <span class="pl-smi">result</span>): <span class="pl-c1">...</span>     <span class="pl-c1">print</span> <span class="pl-s"><span class="pl-pds">'</span>Div:<span class="pl-pds">'</span></span>, result <span class="pl-c1">...</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.add_map(<span class="pl-s"><span class="pl-pds">'</span>div<span class="pl-pds">'</span></span>, handle) <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.add_map(handle, on_handle) <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.drive(<span class="pl-s"><span class="pl-pds">'</span>div<span class="pl-pds">'</span></span>, <span class="pl-c1">2</span>, <span class="pl-c1">4</span>) Div: <span class="pl-c1">0</span> <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.drive(<span class="pl-s"><span class="pl-pds">'</span>div<span class="pl-pds">'</span></span>, <span class="pl-c1">4</span>, <span class="pl-c1">2</span>) Div: <span class="pl-c1">2</span> <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> </pre></div>  <p>The mapcall decorator receives arguments that correspond to exceptions that could be raised by the 'handle' function. The 'handle' function is mapped to the event 'div', when 'div' happens handle is processed and its return value is carried into an event whose value is the 'handle' function. The code below maps the 'handle' function that turned into an event to the 'on_handle' function.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.add_map(handle, on_handle)</pre></div>  <p>What about if an exception occurs inside 'handle' function? </p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.drive(<span class="pl-s"><span class="pl-pds">'</span>div<span class="pl-pds">'</span></span>, <span class="pl-c1">1</span>, <span class="pl-c1">0</span>) <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> </pre></div>  <p>Well, the exception is automatically handled and turned into an event of the type:</p>  <div class="highlight highlight-source-python"><pre>(handle, <span class="pl-c1">ZeroDivisionError</span>)</pre></div>  <p>Whose argment carried is a ZeroDivisionError instance. it is possible to define a handle to deal with the exception that occured like it would be done using 'handle_exception' decorator.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">def</span> <span class="pl-en">on_zero_division_error</span>(<span class="pl-smi">dispatcher</span>, <span class="pl-smi">excpt</span>): <span class="pl-c1">...</span>     <span class="pl-c1">print</span> <span class="pl-s"><span class="pl-pds">'</span>The exception was thrown:<span class="pl-pds">'</span></span>, excpt <span class="pl-c1">...</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.add_map((handle, <span class="pl-c1">ZeroDivisionError</span>), on_zero_division_error) <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.drive(<span class="pl-s"><span class="pl-pds">'</span>div<span class="pl-pds">'</span></span>, <span class="pl-c1">1</span>, <span class="pl-c1">2</span>) Div: <span class="pl-c1">0</span> <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.drive(<span class="pl-s"><span class="pl-pds">'</span>div<span class="pl-pds">'</span></span>, <span class="pl-c1">1</span>, <span class="pl-c1">0</span>) The exception was thrown: integer division <span class="pl-k">or</span> modulo by zero <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> </pre></div>  <p>When using the 'mapcall' decorator and an exception occurs inside a handle then there is no event that corresponds to the handle return value but an event that corresponds to the exception that was raised.</p>  <p>It is interesting to notice that when using 'handle_exception' or 'mapcall' it could be possible to pass a set of exceptions like:</p>  <div class="highlight highlight-source-python"><pre><span class="pl-en">@mapcall</span>(<span class="pl-c1">ZeroDivisionError</span>, <span class="pl-c1">ValueError</span>) <span class="pl-k">def</span> <span class="pl-en">handle</span>(<span class="pl-smi">dispatcher</span>):     <span class="pl-k">raise</span> <span class="pl-c1">ValueError</span></pre></div>  <p>The example below would turn into events all possible exceptions that occured inside 'handle'.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-en">@mapcall</span>(<span class="pl-c1">Exception</span>)<span class="pl-ii">:</span> <span class="pl-k">def</span> <span class="pl-en">handle</span>(<span class="pl-smi">dispatcher</span>):     <span class="pl-k">raise</span> <span class="pl-c1">ValueError</span> </pre></div>  <h3><a id="user-content-handles-that-are-mapped-upon-events-and-produce-events" class="anchor" href="#handles-that-are-mapped-upon-events-and-produce-events" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Handles that are mapped upon events and produce events.</h3>  <h3><a id="user-content-dispatcher-flow-control" class="anchor" href="#dispatcher-flow-control" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Dispatcher flow control</h3>  <h3><a id="user-content-static-handles" class="anchor" href="#static-handles" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Static handles</h3>  <h3><a id="user-content-binding-static-handles-to-events" class="anchor" href="#binding-static-handles-to-events" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>binding static handles to events</h3>  <h3><a id="user-content-unbinding-static-handles-to-events" class="anchor" href="#unbinding-static-handles-to-events" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Unbinding static handles to events</h3>  <h1><a id="user-content-reactors" class="anchor" href="#reactors" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Reactors</h1>  <p>Untwisted reactor is an event loop that listen for events that are related to file descriptors. When objects that are associated with file descriptors are created in untwisted then they are registered in the reactor for reading and writting events.</p>  <p>Untwisted implements the following reactors.</p>  <p><strong>Select</strong></p>  <p>The select reactor can be used in Unix and Win32 platforms.</p>  <p><strong>Epoll</strong></p>  <p>The epoll reactor is used in Linux platforms, it is default in Linux.</p>  <p><strong>Poll</strong></p>  <p>It is used in Unix platforms (Not implemented yet).</p>  <h1><a id="user-content-super-socket-class" class="anchor" href="#super-socket-class" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Super socket class</h1>  <p>As objects can be associated with events and handles as seen previously, it is elegant and useful to think of a socket as an object that can throw events. The basic events associated to a socket are READ and WRITE. So, why not having a 'socket' class that has the features of the 'Dispatcher' class? That is what  the class defined in 'untwisted.network.SuperSocket' is. The 'SuperSocket' class abstracts the behavior of other classes. The 'SuperSocket' class holds a file descriptor that is associated with objects that can be associated with a file descriptor. When a 'SuperSocket' instance is created it registers itself in the untwisted reactor. </p>  <h1><a id="user-content-spin-class" class="anchor" href="#spin-class" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Spin class](#requestmethod)
 * [A word on handles</h1>  <h1><a id="user-content-basic-built-in-handles" class="anchor" href="#basic-built-in-handles" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Basic built-in handles](#a-word-on-handles)
 * [Basic Client/Server Applications</h1>  <h3><a id="user-content-a-simple-client-is_uppy" class="anchor" href="#a-simple-client-is_uppy" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>A simple Client (is_up.py)</h3>  <p>Let us think of a minimal application that receives from the command line two arguments, TCP server address and port number. Once the arguments are provided then the application tries to connect to the server then either notifies success or failure.</p>  <p>So, it is time to implement the code to do the basic imports at the beginning of the file.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">from</span> untwisted.network <span class="pl-k">import</span> core, Spin, xmap, die </pre></div>  <p>That line imports the 'core' module that holds an instance of the 'gear' class that corresponds to untwisted reactor.  The 'xmap' function is basically the same as 'Spin.add_map' method. The 'die' function stops the reactor from processing file descriptors.</p>  <p>It is now time to import the basic handles and events that will be used in the application.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">from</span> untwisted.iostd <span class="pl-k">import</span> Client, <span class="pl-c1">CONNECT</span>, <span class="pl-c1">CONNECT_ERR</span> <span class="pl-k">import</span> errno </pre></div>  <p>The 'Client' handle is a class that spawns the events CONNECT and CONNECT_ERR. The 'Client' handle will be attached to the 'Spin' instance to process the events to notify other handles of the connection status.</p>  <p>Implementing a function named 'create_connection' that will instantiate a 'Spin' instance then bind handles on the events.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">def</span> <span class="pl-en">create_connection</span>(<span class="pl-smi">addr</span>, <span class="pl-smi">port</span>):     con <span class="pl-k">=</span> Spin()     Client(con)</pre></div>  <p>The 'Client' handle will process either CONNECT or CONNECT_ERR events that corresponds to the socket status. Now, it is time to create the handles for these events.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">def</span> <span class="pl-en">on_connect</span>(<span class="pl-smi">con</span>, <span class="pl-smi">addr</span>, <span class="pl-smi">port</span>):     <span class="pl-c1">print</span> <span class="pl-s"><span class="pl-pds">'</span>Connected to <span class="pl-c1">\xs</span>:<span class="pl-c1">\xs</span> !<span class="pl-pds">'</span></span> <span class="pl-k">\x</span> (addr, port)  <span class="pl-k">def</span> <span class="pl-en">on_connect_err</span>(<span class="pl-smi">con</span>, <span class="pl-smi">err</span>, <span class="pl-smi">addr</span>, <span class="pl-smi">port</span>):     <span class="pl-c1">print</span> <span class="pl-s"><span class="pl-pds">"</span>Failed to connect to <span class="pl-c1">\xs</span>:<span class="pl-c1">\xs</span>, errcode <span class="pl-pds">"</span></span> <span class="pl-k">\x</span> (addr, port), errno.errorcode[err]</pre></div>  <p>Once the handles are implemented, it is time to map the events in the 'create_connection' function.</p>  <div class="highlight highlight-source-python"><pre>    xmap(con, <span class="pl-c1">CONNECT</span>, on_connect, addr, port)     xmap(con, <span class="pl-c1">CONNECT_ERR</span>, on_connect_err, addr, port)     xmap(con, <span class="pl-c1">CONNECT</span>, <span class="pl-k">lambda</span> <span class="pl-smi">con</span>: die())     xmap(con, <span class="pl-c1">CONNECT_ERR</span>, <span class="pl-k">lambda</span> <span class="pl-smi">con</span>, <span class="pl-smi">err</span>: die())</pre></div>  <p>The event CONNNECT only carries one argument that is the 'Spin' instance, at the code above it adds other two arguments to be passed to the 'on_connect' handle, the arguments are 'addr' and 'port'. The same occurs with CONNECT_ERR event that carries two arguments, they are the 'Spin' instance and the 'err' value that is an integer whose meaning is defined in the 'errno' module. The 'die' function is used to stop the reactor from processing the file descriptors.</p>  <p>The game is almost won, now! It is time to connect the socket to the addr and port. In the 'create_connection' function just add the line.</p>  <div class="highlight highlight-source-python"><pre>    con.connect_ex((addr, port))</pre></div>  <p>The method 'connect_ex' is used instead of the 'connect'.</p>  <p>Let us implement the code that gets the addr and the port number.</p>  <pre><code>if __name__ == '__main__':     import argparse     parser = argparse.ArgumentParser()     parser.add_argument('-a', '--addr', help='Address')     parser.add_argument('-p', '--port', type=int, help='Port')     args = parser.parse_args()     create_connection(args.addr, args.port) </code></pre>  <p>If we run the code it wouldn't work as expected because we need to execute the untwisted mainloop. So, we just add the statement below at the bottom of the file.</p>  <pre><code>    core.gear.mainloop() </code></pre>  <p>The complete source code is listed below.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">from</span> untwisted.network <span class="pl-k">import</span> core, Spin, xmap, die <span class="pl-k">from</span> untwisted.iostd <span class="pl-k">import</span> Client, <span class="pl-c1">CONNECT</span>, <span class="pl-c1">CONNECT_ERR</span> <span class="pl-k">import</span> errno  <span class="pl-k">def</span> <span class="pl-en">on_connect</span>(<span class="pl-smi">con</span>, <span class="pl-smi">addr</span>, <span class="pl-smi">port</span>):     <span class="pl-c1">print</span> <span class="pl-s"><span class="pl-pds">'</span>Connected to <span class="pl-c1">\xs</span>:<span class="pl-c1">\xs</span> !<span class="pl-pds">'</span></span> <span class="pl-k">\x</span> (addr, port)  <span class="pl-k">def</span> <span class="pl-en">on_connect_err</span>(<span class="pl-smi">con</span>, <span class="pl-smi">err</span>, <span class="pl-smi">addr</span>, <span class="pl-smi">port</span>):     <span class="pl-c1">print</span> <span class="pl-s"><span class="pl-pds">"</span>Failed to connect to <span class="pl-c1">\xs</span>:<span class="pl-c1">\xs</span>, errcode <span class="pl-pds">"</span></span> <span class="pl-k">\x</span> (addr, port), errno.errorcode[err]  <span class="pl-k">def</span> <span class="pl-en">create_connection</span>(<span class="pl-smi">addr</span>, <span class="pl-smi">port</span>):     con <span class="pl-k">=</span> Spin()     Client(con)     xmap(con, <span class="pl-c1">CONNECT</span>, on_connect, addr, port)     xmap(con, <span class="pl-c1">CONNECT_ERR</span>, on_connect_err, addr, port)     xmap(con, <span class="pl-c1">CONNECT</span>, <span class="pl-k">lambda</span> <span class="pl-smi">con</span>: die())     xmap(con, <span class="pl-c1">CONNECT_ERR</span>, <span class="pl-k">lambda</span> <span class="pl-smi">con</span>, <span class="pl-smi">err</span>: die())      con.connect_ex((addr, port))  <span class="pl-k">if</span> <span class="pl-c1">__name__</span> <span class="pl-k">==</span> <span class="pl-s"><span class="pl-pds">'</span>__main__<span class="pl-pds">'</span></span>:     <span class="pl-k">import</span> argparse     parser <span class="pl-k">=</span> argparse.ArgumentParser()     parser.add_argument(<span class="pl-s"><span class="pl-pds">'</span>-a<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>--addr<span class="pl-pds">'</span></span>, <span class="pl-v">help</span><span class="pl-k">=</span><span class="pl-s"><span class="pl-pds">'</span>Address<span class="pl-pds">'</span></span>)     parser.add_argument(<span class="pl-s"><span class="pl-pds">'</span>-p<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>--port<span class="pl-pds">'</span></span>, <span class="pl-v">type</span><span class="pl-k">=</span><span class="pl-c1">int</span>, <span class="pl-v">help</span><span class="pl-k">=</span><span class="pl-s"><span class="pl-pds">'</span>Port<span class="pl-pds">'</span></span>)     args <span class="pl-k">=</span> parser.parse_args()      create_connection(args.addr, args.port)     core.gear.mainloop()</pre></div>  <p>Saving that as a file named 'is_up.py' and testing we would get.</p>  <div class="highlight highlight-source-python"><pre>[tau<span class="pl-k">@</span><span class="pl-k">lambda</span> extra]<span class="pl-ii">$</span> python2 is_up.py -a www.google.com.br -p 90 Failed to connect to www.google.com.br:<span class="pl-c1">90</span>, errcode  <span class="pl-c1">ETIMEDOUT</span> [tau<span class="pl-k">@</span><span class="pl-k">lambda</span> extra]<span class="pl-ii">$</span> python2 is_up.py -a www.google.com.br -p 80 Connected to www.google.com.br:<span class="pl-c1">80</span> !</pre></div>  <h3><a id="user-content-msg-server-msg_serverpy" class="anchor" href="#msg-server-msg_serverpy" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Msg Server (msg_server.py)</h3>  <p>It is the implementation of a simple msg server that receives connections then prints whatever data the clients send. The application is listed below.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">from</span> untwisted.network <span class="pl-k">import</span> xmap, Spin, core <span class="pl-k">from</span> untwisted.iostd <span class="pl-k">import</span> Server, Stdout, Stdin, lose, <span class="pl-c1">ACCEPT</span>, <span class="pl-c1">LOAD</span>, <span class="pl-c1">CLOSE</span> <span class="pl-k">from</span> socket <span class="pl-k">import</span> socket, <span class="pl-c1">AF_INET</span>, <span class="pl-c1">SOCK_STREAM</span> <span class="pl-k">import</span> sys  <span class="pl-k">def</span> <span class="pl-en">setup</span>(<span class="pl-smi">server</span>, <span class="pl-smi">con</span>):     Stdin(con)     Stdout(con)     xmap(con, <span class="pl-c1">CLOSE</span>, <span class="pl-k">lambda</span> <span class="pl-smi">con</span>, <span class="pl-smi">err</span>: lose(con))     xmap(con, <span class="pl-c1">LOAD</span>, <span class="pl-k">lambda</span> <span class="pl-smi">con</span>, <span class="pl-smi">data</span>: sys.stdout.write(<span class="pl-s"><span class="pl-pds">'</span><span class="pl-c1">\xs</span><span class="pl-cce">
</span><span class="pl-pds">'</span></span> <span class="pl-k">\x</span> data))  <span class="pl-k">if</span> <span class="pl-c1">__name__</span> <span class="pl-k">==</span> <span class="pl-s"><span class="pl-pds">'</span>__main__<span class="pl-pds">'</span></span>:         <span class="pl-k">from</span> optparse <span class="pl-k">import</span> OptionParser      parser   <span class="pl-k">=</span> OptionParser()     parser.add_option(<span class="pl-s"><span class="pl-pds">"</span>-a<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>--addr<span class="pl-pds">"</span></span>, <span class="pl-v">dest</span><span class="pl-k">=</span><span class="pl-s"><span class="pl-pds">"</span>addr<span class="pl-pds">"</span></span>,                       <span class="pl-v">metavar</span><span class="pl-k">=</span><span class="pl-s"><span class="pl-pds">"</span>string<span class="pl-pds">"</span></span>, <span class="pl-v">default</span><span class="pl-k">=</span><span class="pl-s"><span class="pl-pds">'</span>0.0.0.0<span class="pl-pds">'</span></span>)      parser.add_option(<span class="pl-s"><span class="pl-pds">"</span>-p<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>--port<span class="pl-pds">"</span></span>, <span class="pl-v">dest</span><span class="pl-k">=</span><span class="pl-s"><span class="pl-pds">"</span>port<span class="pl-pds">"</span></span>,                       <span class="pl-v">type</span><span class="pl-k">=</span><span class="pl-s"><span class="pl-pds">"</span>int<span class="pl-pds">"</span></span>, <span class="pl-v">default</span><span class="pl-k">=</span><span class="pl-c1">1234</span>)      parser.add_option(<span class="pl-s"><span class="pl-pds">"</span>-b<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>--backlog<span class="pl-pds">"</span></span>, <span class="pl-v">dest</span><span class="pl-k">=</span><span class="pl-s"><span class="pl-pds">"</span>backlog<span class="pl-pds">"</span></span>,                       <span class="pl-v">type</span><span class="pl-k">=</span><span class="pl-s"><span class="pl-pds">"</span>int<span class="pl-pds">"</span></span>, <span class="pl-v">default</span><span class="pl-k">=</span><span class="pl-c1">5</span>)      (opt, args) <span class="pl-k">=</span> parser.parse_args()     sock   <span class="pl-k">=</span> socket(<span class="pl-c1">AF_INET</span>, <span class="pl-c1">SOCK_STREAM</span>)     server <span class="pl-k">=</span> Spin(sock)      server.bind((opt.addr, opt.port))     server.listen(opt.backlog)     Server(server)      xmap(server, <span class="pl-c1">ACCEPT</span>, setup)      core.gear.mainloop()</pre></div>  <p>The lines listed below are responsible by creating a socket then wrapping it with the 'Spin' class.</p>  <div class="highlight highlight-source-python"><pre>    sock   <span class="pl-k">=</span> socket(<span class="pl-c1">AF_INET</span>, <span class="pl-c1">SOCK_STREAM</span>)     server <span class="pl-k">=</span> Spin(sock) </pre></div>  <p>It just calls the method 'bind' and 'listen' as usually it is used when dealing with socket servers.</p>  <div class="highlight highlight-source-python"><pre>    server.bind((opt.addr, opt.port))     server.listen(opt.backlog)</pre></div>  <p>In the code below it installs the handle 'Server' that spawns the events ACCEPT, ACCEPT_ERR. The ACCEPT one means that a new connection has arrived.</p>  <div class="highlight highlight-source-python"><pre>    Server(server)     xmap(server, <span class="pl-c1">ACCEPT</span>, setup)</pre></div>  <p>The 'setup' function is called when a new connection has arrived, it installs the basic built in handles 'Stdin' and 'Stdout', these deal with sending and receiving data.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">def</span> <span class="pl-en">setup</span>(<span class="pl-smi">server</span>, <span class="pl-smi">con</span>):     Stdin(con)     Stdout(con)     xmap(con, <span class="pl-c1">CLOSE</span>, <span class="pl-k">lambda</span> <span class="pl-smi">con</span>, <span class="pl-smi">err</span>: lose(con))     xmap(con, <span class="pl-c1">LOAD</span>, <span class="pl-k">lambda</span> <span class="pl-smi">con</span>, <span class="pl-smi">data</span>: sys.stdout.write(<span class="pl-s"><span class="pl-pds">'</span><span class="pl-c1">\xs</span><span class="pl-cce">
</span><span class="pl-pds">'</span></span> <span class="pl-k">\x</span> data))</pre></div>  <p>In the 'setup' the line below maps the event CLOSE to the lambda that calls the function 'lose'. The function 'lose' is used to close the connection and unregister the socket from the reactor.</p>  <div class="highlight highlight-source-python"><pre>    xmap(con, <span class="pl-c1">CLOSE</span>, <span class="pl-k">lambda</span> <span class="pl-smi">con</span>, <span class="pl-smi">err</span>: lose(con))</pre></div>  <p>The line below just maps the event LOAD that is spawned by the handle 'Stdin' to a lambda that writes to stdout.</p>  <div class="highlight highlight-source-python"><pre>    xmap(con, <span class="pl-c1">LOAD</span>, <span class="pl-k">lambda</span> <span class="pl-smi">con</span>, <span class="pl-smi">data</span>: sys.stdout.write(<span class="pl-s"><span class="pl-pds">'</span><span class="pl-c1">\xs</span><span class="pl-cce">
</span><span class="pl-pds">'</span></span> <span class="pl-k">\x</span> data))</pre></div>  <p>Saving the file as 'msg_server.py' and running it with:</p>  <pre><code>python2 msg_server.py -a '0.0.0.0' -p 1235 -b 50 </code></pre>  <p>Then connecting from a telnet with:</p>  <pre><code>telnet localhost 1235 </code></pre>  <p>You'll get all the text that was sent from the telnet printed in the msg server window.</p>  <h3><a id="user-content-msg-client-msg_clientpy" class="anchor" href="#msg-client-msg_clientpy" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Msg Client (msg_client.py)</h3>  <p>This is the counter part of the msg server application. The program listed below is using essentially the basic features of the 'msg_server.py' one.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">from</span> untwisted.network <span class="pl-k">import</span> xmap, Spin, core <span class="pl-k">from</span> untwisted.iostd <span class="pl-k">import</span> Client, Stdout, Stdin, <span class="pl-c1">CONNECT</span>, <span class="pl-c1">DUMPED</span> <span class="pl-k">from</span> socket <span class="pl-k">import</span> socket, <span class="pl-c1">AF_INET</span>, <span class="pl-c1">SOCK_STREAM</span> <span class="pl-k">from</span> untwisted.core <span class="pl-k">import</span> die  <span class="pl-k">def</span> <span class="pl-en">setup</span>(<span class="pl-smi">con</span>, <span class="pl-smi">msg</span>):     Stdout(con)     Stdin(con)     con.dump(msg)     xmap(con, <span class="pl-c1">DUMPED</span>, <span class="pl-k">lambda</span> <span class="pl-smi">con</span>: die(<span class="pl-s"><span class="pl-pds">'</span>Msg dumped!<span class="pl-pds">'</span></span>))  <span class="pl-k">def</span> <span class="pl-en">create_connection</span>(<span class="pl-smi">addr</span>, <span class="pl-smi">port</span>, <span class="pl-smi">msg</span>):     sock <span class="pl-k">=</span> socket(<span class="pl-c1">AF_INET</span>, <span class="pl-c1">SOCK_STREAM</span>)     con  <span class="pl-k">=</span> Spin(sock)      Client(con)     con.connect_ex((addr, port))     xmap(con, <span class="pl-c1">CONNECT</span>, setup, msg)  <span class="pl-k">if</span> <span class="pl-c1">__name__</span> <span class="pl-k">==</span> <span class="pl-s"><span class="pl-pds">'</span>__main__<span class="pl-pds">'</span></span>:     <span class="pl-k">from</span> optparse <span class="pl-k">import</span> OptionParser      parser   <span class="pl-k">=</span> OptionParser()     parser.add_option(<span class="pl-s"><span class="pl-pds">"</span>-a<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>--addr<span class="pl-pds">"</span></span>, <span class="pl-v">dest</span><span class="pl-k">=</span><span class="pl-s"><span class="pl-pds">"</span>addr<span class="pl-pds">"</span></span>,                       <span class="pl-v">metavar</span><span class="pl-k">=</span><span class="pl-s"><span class="pl-pds">"</span>string<span class="pl-pds">"</span></span>, <span class="pl-v">default</span><span class="pl-k">=</span><span class="pl-s"><span class="pl-pds">'</span>localhost<span class="pl-pds">'</span></span>)      parser.add_option(<span class="pl-s"><span class="pl-pds">"</span>-p<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>--port<span class="pl-pds">"</span></span>, <span class="pl-v">dest</span><span class="pl-k">=</span><span class="pl-s"><span class="pl-pds">"</span>port<span class="pl-pds">"</span></span>,                       <span class="pl-v">type</span><span class="pl-k">=</span><span class="pl-s"><span class="pl-pds">"</span>int<span class="pl-pds">"</span></span>, <span class="pl-v">default</span><span class="pl-k">=</span><span class="pl-c1">1234</span>)      parser.add_option(<span class="pl-s"><span class="pl-pds">"</span>-m<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>--msg<span class="pl-pds">"</span></span>, <span class="pl-v">dest</span><span class="pl-k">=</span><span class="pl-s"><span class="pl-pds">"</span>msg<span class="pl-pds">"</span></span>,                       <span class="pl-v">metavar</span><span class="pl-k">=</span><span class="pl-s"><span class="pl-pds">"</span>string<span class="pl-pds">"</span></span>)      (opt, args) <span class="pl-k">=</span> parser.parse_args()     create_connection(opt.addr, opt.port, opt.msg)     core.gear.mainloop()</pre></div>  <p>The line below merely dumps the message that was specified by the user through the socket. The 'Stdin' handle monkey patch the method 'dump'.</p>  <div class="highlight highlight-source-python"><pre>    con.dump(msg)</pre></div>  <p>When all the data was sent then 'Stdin' handle spawns the event DUMPED in the Spin instance that it was added to.</p>  <pre><code>    xmap(con, DUMPED, lambda con: die('Msg dumped!')) </code></pre>  <p>When the event dumped happens then it calls die to stop the reactor then prints a msg on the screen.</p>  <p>Place the source code above inside a file named 'msg_client.py' then run the 'msg_server.py' with:</p>  <pre><code>python2 msg_server.py -a '0.0.0.0' -p 1235 -b 50 </code></pre>  <p>It is possible to send messages to the 'msg_server.py' instance by running 'msg_client.py' with.</p>  <pre><code>python2 msg_client.py -a 'localhost' -p 1234 -m 'it is gonna be cool' </code></pre>  <h3><a id="user-content-echo-server-echo_serverpy" class="anchor" href="#echo-server-echo_serverpy" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Echo Server (echo_server.py)</h3>  <p>The example below shows a simple echo server application that uses the shorthand function 'create_server'. Such a function instantiates a 'Spin' instance and installs the basic handles in the server socket and in the new incoming connection sockets. </p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">from</span> untwisted.network <span class="pl-k">import</span> Spin, xmap, core <span class="pl-k">from</span> untwisted.iostd <span class="pl-k">import</span> create_server, <span class="pl-c1">ACCEPT</span>, <span class="pl-c1">LOAD</span>  <span class="pl-k">class</span> <span class="pl-en">EchoServer</span>(<span class="pl-c1">object</span>):     <span class="pl-k">def</span> <span class="pl-c1">__init__</span>(<span class="pl-smi"><span class="pl-smi">self</span></span>, <span class="pl-smi">server</span>):         xmap(server, <span class="pl-c1">ACCEPT</span>, <span class="pl-k">lambda</span> <span class="pl-smi">server</span>, <span class="pl-smi">con</span>:                       xmap(con, <span class="pl-c1">LOAD</span>, <span class="pl-k">lambda</span> <span class="pl-smi">con</span>, <span class="pl-smi">data</span>: con.dump(data)))  <span class="pl-k">if</span> <span class="pl-c1">__name__</span> <span class="pl-k">==</span> <span class="pl-s"><span class="pl-pds">'</span>__main__<span class="pl-pds">'</span></span>:     EchoServer(create_server(<span class="pl-s"><span class="pl-pds">'</span>0.0.0.0<span class="pl-pds">'</span></span>, <span class="pl-c1">1234</span>, <span class="pl-c1">5</span>))     core.gear.mainloop()</pre></div>  <p>Consider the line:</p>  <div class="highlight highlight-source-python"><pre>        xmap(server, <span class="pl-c1">ACCEPT</span>, <span class="pl-k">lambda</span> <span class="pl-smi">server</span>, <span class="pl-smi">con</span>:                       xmap(con, <span class="pl-c1">LOAD</span>, <span class="pl-k">lambda</span> <span class="pl-smi">con</span>, <span class="pl-smi">data</span>: con.dump(data)))</pre></div>  <p>That basically adds a mapping 'LOAD -(str:data)-&gt; print' to the 'con' object that corresponds to the new connection. When the event LOAD happens in one of the cliet connections then it dumps back the data that was received.</p>  <h1><a id="user-content-splits" class="anchor" href="#splits" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Splits</h1>  <p>Application layer protocols are mostly based on string tokens, these tokens models the communication between client and server applications. An example is the HTTP protocol that uses '

' to separate HTTP headers from HTTP content in a HTTP request.</p>  <p>The fundamental idea of untwisted is providing a set of tools to parse application layer protocols into meaningful chunks of data then spawning events. These events can be used to model applications either in the client side or server side applications.</p>  <h3><a id="user-content-terminator-split" class="anchor" href="#terminator-split" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Terminator Split</h3>  <p>The 'Terminator' split is a handle that is processed on the LOAD event. It accumulates data that is carried with the LOAD event until a specific token appears. When the specified token appears in the data then it splits all the data that was accumulated into a list of chunks and it spawns the event Terminator.FOUND sequentially with each one of the chunks.</p>  <p>The best way to understand the Terminator handle is testing it in the python interpreter.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">from</span> untwisted.splits <span class="pl-k">import</span> Terminator <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">from</span> untwisted.dispatcher <span class="pl-k">import</span> Dispatcher <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">from</span> untwisted.event <span class="pl-k">import</span> <span class="pl-c1">LOAD</span> <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> con <span class="pl-k">=</span> Dispatcher() <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> terminator <span class="pl-k">=</span> Terminator(con, <span class="pl-v">delim</span><span class="pl-k">=</span><span class="pl-s"><span class="pl-pds">'</span>,<span class="pl-pds">'</span></span>)</pre></div>  <p>The code above instantiates a 'Dispatcher' instance named 'con' that simulates a 'Spin' socket. It installs the handle 'Terminator' with the delimiter ','. Whenever the LOAD event happens in the 'con' instance it will check for the token ',' if it appears then it splits the data into chunks that are delimited by ',' otherwise it accumulates the data.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">def</span> <span class="pl-en">on_found</span>(<span class="pl-smi">con</span>, <span class="pl-smi">data</span>): <span class="pl-c1">...</span>     <span class="pl-c1">print</span> <span class="pl-s"><span class="pl-pds">'</span>msg:<span class="pl-pds">'</span></span>, data <span class="pl-c1">...</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> con.add_map(Terminator.<span class="pl-c1">FOUND</span>, on_found) <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> </pre></div>  <p>When the event Terminator.FOUND happens then calls 'on_found' handle with the chunk.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> con.drive(<span class="pl-c1">LOAD</span>, <span class="pl-s"><span class="pl-pds">'</span>word1,word2,wor<span class="pl-pds">'</span></span>) msg: word1 msg: word2 <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> con.drive(<span class="pl-c1">LOAD</span>, <span class="pl-s"><span class="pl-pds">'</span>d3,word4<span class="pl-pds">'</span></span>) msg: word3 <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> con.drive(<span class="pl-c1">LOAD</span>, <span class="pl-s"><span class="pl-pds">'</span>,<span class="pl-pds">'</span></span>) msg: word4 <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> </pre></div>  <p>When 'Terminator' is installed in a Spin socket and a READ event is dispatched by the reactor then a LOAD event happens and the handle 'Terminator' is processed.</p>  <pre><code>READ -&gt; Stdout =&gt; LOAD -(str:data)-&gt; Terminator =(str:chk)=&gt; Terminator.FOUND </code></pre>  <h3><a id="user-content-calc-server-calc_serverpy" class="anchor" href="#calc-server-calc_serverpy" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Calc Server (calc_server.py)</h3>  <p>This example implements a simple application layer protocol that uses as token '
' to separate meaningful chunks of text. Clients would connect to the server by using a telnet then start sending commands to do computations.</p>  <p><strong>Example of commands</strong></p>  <pre><code>add 1 2 3 sub 0 2 div 4 2 2 4 </code></pre>  <p>The complete source code is listed below.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">from</span> untwisted.network <span class="pl-k">import</span> core, Spin, xmap, spawn <span class="pl-k">from</span> untwisted.iostd <span class="pl-k">import</span> Server, Stdin, Stdout, <span class="pl-c1">CLOSE</span>, <span class="pl-c1">ACCEPT</span> <span class="pl-k">from</span> untwisted.splits <span class="pl-k">import</span> Terminator <span class="pl-k">from</span> untwisted.tools <span class="pl-k">import</span> handle_exception <span class="pl-k">import</span> operator  <span class="pl-k">class</span> <span class="pl-en">CalcParser</span>(<span class="pl-c1">object</span>):     <span class="pl-k">def</span> <span class="pl-c1">__init__</span>(<span class="pl-smi"><span class="pl-smi">self</span></span>, <span class="pl-smi">client</span>):         xmap(client, Terminator.<span class="pl-c1">FOUND</span>, <span class="pl-v">self</span>.handle_found)      <span class="pl-en">@handle_exception</span>(<span class="pl-c1">ValueError</span>)     <span class="pl-k">def</span> <span class="pl-en">handle_found</span>(<span class="pl-smi">client</span>, <span class="pl-smi">data</span>):         op, args <span class="pl-k">=</span> data.split(<span class="pl-s"><span class="pl-pds">'</span> <span class="pl-pds">'</span></span>, <span class="pl-c1">1</span>)         args     <span class="pl-k">=</span> <span class="pl-c1">map</span>(<span class="pl-c1">float</span>, args.split(<span class="pl-s"><span class="pl-pds">'</span> <span class="pl-pds">'</span></span>))         spawn(client, op, args)  <span class="pl-k">class</span> <span class="pl-en">CalcServer</span>(<span class="pl-c1">object</span>):     <span class="pl-s"><span class="pl-pds">"""</span> </span> <span class="pl-s">    <span class="pl-pds">"""</span></span>      <span class="pl-k">def</span> <span class="pl-c1">__init__</span>(<span class="pl-smi"><span class="pl-smi">self</span></span>, <span class="pl-smi">server</span>):         xmap(server, <span class="pl-c1">ACCEPT</span>, <span class="pl-v">self</span>.handle_accept)      <span class="pl-k">def</span> <span class="pl-en">handle_accept</span>(<span class="pl-smi"><span class="pl-smi">self</span></span>, <span class="pl-smi">server</span>, <span class="pl-smi">client</span>):         Stdin(client)         Stdout(client)         Terminator(client, <span class="pl-v">delim</span><span class="pl-k">=</span><span class="pl-s"><span class="pl-pds">'</span><span class="pl-cce">
</span><span class="pl-pds">'</span></span>)         parser <span class="pl-k">=</span> CalcParser(client)          xmap(client, <span class="pl-s"><span class="pl-pds">'</span>add<span class="pl-pds">'</span></span>, <span class="pl-v">self</span>. on_add)             xmap(client, <span class="pl-s"><span class="pl-pds">'</span>sub<span class="pl-pds">'</span></span>, <span class="pl-v">self</span>.on_sub)             xmap(client, <span class="pl-s"><span class="pl-pds">'</span>mul<span class="pl-pds">'</span></span>, <span class="pl-v">self</span>.on_mul)             xmap(client, <span class="pl-s"><span class="pl-pds">'</span>div<span class="pl-pds">'</span></span>, <span class="pl-v">self</span>.on_div)             xmap(client, (parser.handle_found, <span class="pl-c1">ValueError</span>), <span class="pl-v">self</span>.on_error)              xmap(client, <span class="pl-c1">CLOSE</span>, <span class="pl-v">self</span>.handle_close)      <span class="pl-k">def</span> <span class="pl-en">on_add</span>(<span class="pl-smi"><span class="pl-smi">self</span></span>, <span class="pl-smi">client</span>, <span class="pl-smi">args</span>):         <span class="pl-v">self</span>.send_msg(client, <span class="pl-v">reduce</span>(operator.add, args, <span class="pl-c1">0</span>))      <span class="pl-k">def</span> <span class="pl-en">on_sub</span>(<span class="pl-smi"><span class="pl-smi">self</span></span>, <span class="pl-smi">client</span>, <span class="pl-smi">args</span>):         <span class="pl-v">self</span>.send_msg(client, <span class="pl-v">reduce</span>(operator.sub, args, <span class="pl-c1">0</span>))      <span class="pl-k">def</span> <span class="pl-en">on_div</span>(<span class="pl-smi"><span class="pl-smi">self</span></span>, <span class="pl-smi">client</span>, <span class="pl-smi">args</span>):         <span class="pl-v">self</span>.send_msg(client, <span class="pl-v">reduce</span>(operator.div, args, args.pop(<span class="pl-c1">0</span>)))      <span class="pl-k">def</span> <span class="pl-en">on_mul</span>(<span class="pl-smi"><span class="pl-smi">self</span></span>, <span class="pl-smi">client</span>, <span class="pl-smi">args</span>):         <span class="pl-v">self</span>.send_msg(client, <span class="pl-v">reduce</span>(operator.mul, args, args.pop(<span class="pl-c1">0</span>)))      <span class="pl-k">def</span> <span class="pl-en">on_error</span>(<span class="pl-smi"><span class="pl-smi">self</span></span>, <span class="pl-smi">client</span>, <span class="pl-smi">excpt</span>):         <span class="pl-v">self</span>.send_msg(client, excpt)      <span class="pl-k">def</span> <span class="pl-en">handle_close</span>(<span class="pl-smi"><span class="pl-smi">self</span></span>, <span class="pl-smi">client</span>, <span class="pl-smi">err</span>):         client.destroy()         client.close()      <span class="pl-k">def</span> <span class="pl-en">send_msg</span>(<span class="pl-smi"><span class="pl-smi">self</span></span>, <span class="pl-smi">client</span>, <span class="pl-smi">msg</span>):         client.dump(<span class="pl-s"><span class="pl-pds">'</span><span class="pl-c1">\xs</span><span class="pl-cce">
</span><span class="pl-pds">'</span></span> <span class="pl-k">\x</span> msg)  <span class="pl-k">if</span> <span class="pl-c1">__name__</span> <span class="pl-k">==</span> <span class="pl-s"><span class="pl-pds">'</span>__main__<span class="pl-pds">'</span></span>:     server <span class="pl-k">=</span> Spin()     server.bind((<span class="pl-s"><span class="pl-pds">'</span><span class="pl-pds">'</span></span>, <span class="pl-c1">1234</span>))     server.listen(<span class="pl-c1">5</span>)      Server(server)     CalcServer(server)     core.gear.mainloop()</pre></div>  <p>The code below implements the handle 'CalcParser' that is processed when Terminator.FOUND is processed.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">class</span> <span class="pl-en">CalcParser</span>(<span class="pl-c1">object</span>):     <span class="pl-k">def</span> <span class="pl-c1">__init__</span>(<span class="pl-smi"><span class="pl-smi">self</span></span>, <span class="pl-smi">client</span>):         xmap(client, Terminator.<span class="pl-c1">FOUND</span>, <span class="pl-v">self</span>.handle_found)      <span class="pl-en">@handle_exception</span>(<span class="pl-c1">ValueError</span>)     <span class="pl-k">def</span> <span class="pl-en">handle_found</span>(<span class="pl-smi">client</span>, <span class="pl-smi">data</span>):         op, args <span class="pl-k">=</span> data.split(<span class="pl-s"><span class="pl-pds">'</span> <span class="pl-pds">'</span></span>, <span class="pl-c1">1</span>)         args     <span class="pl-k">=</span> <span class="pl-c1">map</span>(<span class="pl-c1">float</span>, args.split(<span class="pl-s"><span class="pl-pds">'</span> <span class="pl-pds">'</span></span>))         spawn(client, op, args)</pre></div>  <p>When one of the clients sends a message like:</p>  <pre><code>cmd arg0 arg1 arg2 ...
 </code></pre>  <p>The Terminator.FOUND event will be processed then 'handle_found' will be processed and it will receive that string. The string will be split using ' ' as token and the first chunk will turn into an event, the remaining chunks will be converted to float numbers.</p>  <p>So, if one of the clients sends:</p>  <pre><code>add 1 2 </code></pre>  <p>It will occur an event named 'add' and it will carry the arguments (1, 2). Whatever handle that is mapped to the event 'add' will be processed. </p>  <p>The 'handle_exception' decorator is used to get an event-exception like (CalcParser.handle_found, ValueError). If one of the clients sends a message like:</p>  <pre><code>add 1 2 x </code></pre>  <p>It will raise an exception 'ValueError' inside handle_found then it will be turned into an event that can be trigged by other handles. In the example, the event (CalcParser.handle_found, ValueError) was mapped to the handle 'on_error' that sends back the exception to the client.</p>  <p>The code below is used to destroy the 'Spin' instance then close the underlying socket.</p>  <div class="highlight highlight-source-python"><pre>    <span class="pl-k">def</span> <span class="pl-en">handle_close</span>(<span class="pl-smi"><span class="pl-smi">self</span></span>, <span class="pl-smi">client</span>, <span class="pl-smi">err</span>):         client.destroy()         client.close()</pre></div>  <p>Saving the file as 'calc_server.py' and running it with:</p>  <pre><code>python2 calc_server.py </code></pre>  <p>Then connecting to the server with:</p>  <pre><code>tee &gt;(telnet localhost 1234) Trying ::1... Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. add 1 2 3.0 sub 2 -1 -1.0 div 2 2 2 0.5 add 2 x 0 could not convert string to float: x add 1 0 2323 2324.0 add 2 0 lksjc could not convert string to float: lksjc </code></pre>  <h1><a id="user-content-timers" class="anchor" href="#timers" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Timers</h1>  <p>Timers are a way to get handles executed after a given interval of time. </p>  <p>Let us test how it works.</p>  <div class="highlight highlight-source-python"><pre>Python <span class="pl-c1">2.7</span>.11 (default, Dec  <span class="pl-c1">6</span> <span class="pl-c1">2015</span>, <span class="pl-c1">15</span>:<span class="pl-c1">43</span>:<span class="pl-c1">46</span>)  [<span class="pl-c1">GCC</span> <span class="pl-c1">5.2</span>.0] on linux2 Type <span class="pl-s"><span class="pl-pds">"</span>help<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>copyright<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>credits<span class="pl-pds">"</span></span> <span class="pl-k">or</span> <span class="pl-s"><span class="pl-pds">"</span>license<span class="pl-pds">"</span></span> <span class="pl-k">for</span> more information. <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">from</span> untwisted.timer <span class="pl-k">import</span> Timer <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">from</span> untwisted <span class="pl-k">import</span> core <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">def</span> <span class="pl-en">handle</span>(<span class="pl-smi">msg</span>): <span class="pl-c1">...</span>     <span class="pl-c1">print</span> msg <span class="pl-c1">...</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> timer <span class="pl-k">=</span> Timer(<span class="pl-c1">10</span>, handle, <span class="pl-s"><span class="pl-pds">'</span>hello world<span class="pl-pds">'</span></span>) <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> core.gear.mainloop() hello world</pre></div>  <p>The 'Timer' object is used to execute a handle just once. It is possible to cancel the handle call by calling the method 'Timer.cancel'.</p>  <p>The 'Sched' object is used to get a handle executed periodically.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">from</span> untwisted.timer <span class="pl-k">import</span> Sched <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">from</span> untwisted <span class="pl-k">import</span> core <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">def</span> <span class="pl-en">handle</span>(<span class="pl-smi">msg</span>): <span class="pl-c1">...</span>     <span class="pl-c1">print</span> msg <span class="pl-c1">...</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> timer <span class="pl-k">=</span> Sched(<span class="pl-c1">2</span>, handle, <span class="pl-s"><span class="pl-pds">'</span>hello world<span class="pl-pds">'</span></span>) <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> core.gear.mainloop() hello world hello world hello world hello world hello world</pre></div>  <p>The exception 'CancelCall' that is defined in the 'untwisted.timer' module can be raised in order to get the handle call canceled.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">from</span> untwisted.timer <span class="pl-k">import</span> Sched, CancelCall <span class="pl-k">from</span> untwisted <span class="pl-k">import</span> core  <span class="pl-k">def</span> <span class="pl-en">handle</span>(<span class="pl-k">*</span><span class="pl-smi">args</span>):     <span class="pl-k">if</span> some_condition:         <span class="pl-k">raise</span> CancelCall  timer <span class="pl-k">=</span> Sched(inc, handle, arg0, arg1, <span class="pl-c1">...</span>) core.gear.mainloop()</pre></div>  <h1><a id="user-content-coroutines" class="anchor" href="#coroutines" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Coroutines</h1>  <p>Untwisted coroutines are used from handles to stop code execution until a given event happens with some 'Dispatcher' instance.</p>  <p>Let us play with untwisted coroutines from the interpreter.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">from</span> untwisted.dispatcher <span class="pl-k">import</span> Dispatcher <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">from</span> untwisted.tools <span class="pl-k">import</span> coroutine <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">from</span> untwisted.event <span class="pl-k">import</span> get_event <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">@</span>coroutine <span class="pl-c1">...</span> <span class="pl-k">def</span> <span class="pl-en">handle</span>(<span class="pl-smi">dispatcher</span>): <span class="pl-c1">...</span>     value, <span class="pl-k">=</span> <span class="pl-k">yield</span> dispatcher, <span class="pl-s"><span class="pl-pds">'</span>cond0<span class="pl-pds">'</span></span> <span class="pl-c1">...</span>     <span class="pl-c1">print</span> <span class="pl-s"><span class="pl-pds">'</span>Value:<span class="pl-pds">'</span></span>, value <span class="pl-c1">...</span>     value, <span class="pl-k">=</span> <span class="pl-k">yield</span> dispatcher, <span class="pl-s"><span class="pl-pds">'</span>cond1<span class="pl-pds">'</span></span> <span class="pl-c1">...</span>     <span class="pl-c1">print</span> <span class="pl-s"><span class="pl-pds">'</span>Value:<span class="pl-pds">'</span></span>, value <span class="pl-c1">...</span>     value, <span class="pl-k">=</span> <span class="pl-k">yield</span> dispatcher, <span class="pl-s"><span class="pl-pds">'</span>cond2<span class="pl-pds">'</span></span> <span class="pl-c1">...</span>     <span class="pl-c1">print</span> <span class="pl-s"><span class="pl-pds">'</span>Value:<span class="pl-pds">'</span></span>, value <span class="pl-c1">...</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher <span class="pl-k">=</span> Dispatcher() <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> handle(dispatcher) <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.drive(<span class="pl-s"><span class="pl-pds">'</span>cond0<span class="pl-pds">'</span></span>, <span class="pl-c1">10</span>) Value: <span class="pl-c1">10</span> <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.drive(<span class="pl-s"><span class="pl-pds">'</span>cond1<span class="pl-pds">'</span></span>, <span class="pl-c1">20</span>) Value: <span class="pl-c1">20</span> <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.drive(<span class="pl-s"><span class="pl-pds">'</span>cond2<span class="pl-pds">'</span></span>, <span class="pl-c1">30</span>) Value: <span class="pl-c1">30</span> <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.drive(<span class="pl-s"><span class="pl-pds">'</span>cond0<span class="pl-pds">'</span></span>, <span class="pl-c1">40</span>) <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> </pre></div>  <p>The 'handle' function receives a 'dispatcher' instance then uses the 'yield' statement to wait for incoming events from the 'dispatcher' instance. When the events occur then the code is processed.</p>  <p>A more complicated example would be:</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">from</span> untwisted.dispatcher <span class="pl-k">import</span> Dispatcher <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">from</span> untwisted.tools <span class="pl-k">import</span> coroutine <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">from</span> untwisted.event <span class="pl-k">import</span> <span class="pl-c1">LOAD</span>, <span class="pl-c1">DUMPED</span> <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> <span class="pl-k">@</span>coroutine <span class="pl-c1">...</span> <span class="pl-k">def</span> <span class="pl-en">handle</span>(<span class="pl-smi">dispatcher</span>, <span class="pl-smi">number</span>): <span class="pl-c1">...</span>     <span class="pl-c1">print</span> <span class="pl-s"><span class="pl-pds">'</span>coroutine started!<span class="pl-pds">'</span></span> <span class="pl-c1">...</span>     <span class="pl-k">while</span> <span class="pl-c1">True</span>: <span class="pl-c1">...</span>         value, <span class="pl-k">=</span> <span class="pl-k">yield</span> dispatcher, <span class="pl-c1">LOAD</span> <span class="pl-c1">...</span>         <span class="pl-k">if</span> value <span class="pl-k">&gt;</span> number: <span class="pl-c1">...</span>             <span class="pl-k">break</span> <span class="pl-c1">...</span>     <span class="pl-c1">print</span> <span class="pl-s"><span class="pl-pds">'</span>number<span class="pl-pds">'</span></span>, number <span class="pl-c1">...</span>     <span class="pl-c1">print</span> <span class="pl-s"><span class="pl-pds">'</span>Value:<span class="pl-pds">'</span></span>, value <span class="pl-c1">...</span>  <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher <span class="pl-k">=</span> Dispatcher() <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.add_map(<span class="pl-c1">DUMPED</span>, handle) <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.drive(<span class="pl-c1">DUMPED</span>, <span class="pl-c1">20</span>) coroutine started! <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.drive(<span class="pl-c1">LOAD</span>, <span class="pl-c1">10</span>) <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.drive(<span class="pl-c1">LOAD</span>, <span class="pl-c1">15</span>) <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> dispatcher.drive(<span class="pl-c1">LOAD</span>, <span class="pl-c1">30</span>) number <span class="pl-c1">20</span> Value: <span class="pl-c1">30</span> <span class="pl-k">&gt;&gt;</span><span class="pl-k">&gt;</span> </pre></div>  <p>When the event DUMPED is processed then 'handle' is processed and it waits for the event LOAD to happen from the 'dispatcher' instance. When the LOAD happens then it checks whether the value it carried matches the condition if it matches then it breaks the while loop.</p>  <h3><a id="user-content-a-simple-chat-server-chat_serverpy" class="anchor" href="#a-simple-chat-server-chat_serverpy" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>A simple chat server (chat_server.py)</h3>  <p>The chat server source that is listed below is a neat example of how coroutines can turn into a powerful tool.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">from</span> untwisted.network <span class="pl-k">import</span> core, Spin, xmap <span class="pl-k">from</span> untwisted.iostd <span class="pl-k">import</span> create_server, <span class="pl-c1">ACCEPT</span>, <span class="pl-c1">CLOSE</span>, lose <span class="pl-k">from</span> untwisted.splits <span class="pl-k">import</span> Terminator <span class="pl-k">from</span> untwisted.tools <span class="pl-k">import</span> coroutine  <span class="pl-k">class</span> <span class="pl-en">ChatServer</span>(<span class="pl-c1">object</span>):     <span class="pl-k">def</span> <span class="pl-c1">__init__</span>(<span class="pl-smi"><span class="pl-smi">self</span></span>, <span class="pl-smi">server</span>):         xmap(server, <span class="pl-c1">ACCEPT</span>, <span class="pl-v">self</span>.handle_accept)         <span class="pl-v">self</span>.pool <span class="pl-k">=</span> []      <span class="pl-en">@coroutine</span>     <span class="pl-k">def</span> <span class="pl-en">handle_accept</span>(<span class="pl-smi"><span class="pl-smi">self</span></span>, <span class="pl-smi">server</span>, <span class="pl-smi">client</span>):         Terminator(client, <span class="pl-v">delim</span><span class="pl-k">=</span><span class="pl-s"><span class="pl-pds">'</span><span class="pl-cce">
</span><span class="pl-pds">'</span></span>)         xmap(client, <span class="pl-c1">CLOSE</span>, <span class="pl-k">lambda</span> <span class="pl-smi">client</span>, <span class="pl-smi">err</span>: <span class="pl-v">self</span>.pool.remove(client))          client.dump(<span class="pl-s"><span class="pl-pds">'</span>Type a nick.<span class="pl-cce">
</span>Nick:<span class="pl-pds">'</span></span>)             client.nick, <span class="pl-k">=</span> <span class="pl-k">yield</span> client, Terminator.<span class="pl-c1">FOUND</span>          xmap(client, Terminator.<span class="pl-c1">FOUND</span>, <span class="pl-v">self</span>.echo_msg)         <span class="pl-v">self</span>.pool.append(client)      <span class="pl-k">def</span> <span class="pl-en">echo_msg</span>(<span class="pl-smi"><span class="pl-smi">self</span></span>, <span class="pl-smi">client</span>, <span class="pl-smi">data</span>):         <span class="pl-k">for</span> ind <span class="pl-k">in</span> <span class="pl-v">self</span>.pool:             <span class="pl-k">if</span> <span class="pl-k">not</span> ind <span class="pl-k">is</span> client:                 ind.dump(<span class="pl-s"><span class="pl-pds">'</span><span class="pl-c1">\xs</span>:<span class="pl-c1">\xs</span><span class="pl-cce">
</span><span class="pl-pds">'</span></span> <span class="pl-k">\x</span> (client.nick, data))  <span class="pl-k">if</span> <span class="pl-c1">__name__</span> <span class="pl-k">==</span> <span class="pl-s"><span class="pl-pds">'</span>__main__<span class="pl-pds">'</span></span>:     server <span class="pl-k">=</span> create_server(<span class="pl-s"><span class="pl-pds">'</span><span class="pl-pds">'</span></span>, <span class="pl-c1">1234</span>, <span class="pl-c1">5</span>)     ChatServer(server)     core.gear.mainloop()</pre></div>  <p>When clients connect to the server it asks for a nickname to be sent. The implementation uses untwisted coroutines to wait for a Terminator.FOUND event to set the user's nickname to its corresponding 'Spin' instance.</p>  <p>After the nick being set in the user socket instance then it maps the event Terminator.FOUND to the method 'echo_msg' that echoes any msg to other users.</p>  <p><strong>Testing</strong></p>  <p>Run the chat server with:</p>  <pre><code>python chat_server.py </code></pre>  <p>Connect from a telnet with:</p>  <pre><code>telnet 'localhost' 1234 </code></pre>  <h1><a id="user-content-threads" class="anchor" href="#threads" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Threads</h1>  <p>Untwisted reactor is implemented on top of a non blocking design that uses  select, poll  functions to wait for I/O completion. The code that is being executed in the untwisted reactor thread can't hang otherwise the reactor scales poorly. In situations where heavy computations need to be done it is needed to use threads.</p>  <h3><a id="user-content-job-class" class="anchor" href="#job-class" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Job class</h3>  <p>The job class constructor takes a function that is executed inside a new thread.</p>  <h3><a id="user-content-a-basic-example-sumpy" class="anchor" href="#a-basic-example-sumpy" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>A basic example (sum.py)</h3>  <p>The example below spawns some threads that perform simple calculations.</p>  <div class="highlight highlight-source-python"><pre><span class="pl-k">from</span> untwisted.network <span class="pl-k">import</span> core, xmap <span class="pl-k">from</span> untwisted.job <span class="pl-k">import</span> Job, <span class="pl-c1">DONE</span> <span class="pl-k">import</span> time  <span class="pl-k">def</span> <span class="pl-c1">sum</span>(<span class="pl-smi">x</span>, <span class="pl-smi">y</span>):     time.sleep(<span class="pl-c1">3</span>)     <span class="pl-k">return</span> x <span class="pl-k"> </span> y  <span class="pl-k">def</span> <span class="pl-en">show</span>(<span class="pl-smi">job</span>, <span class="pl-smi">result</span>):     <span class="pl-c1">print</span> result  <span class="pl-k">for</span> ind <span class="pl-k">in</span> <span class="pl-v">xrange</span>(<span class="pl-c1">100</span>):     job <span class="pl-k">=</span> Job(<span class="pl-c1">sum</span>, ind, <span class="pl-c1">1000</span>)     xmap(job, <span class="pl-c1">DONE</span>, show)  core.gear.mainloop()</pre></div>  <p>The function <strong>sum</strong> is called with two arguments then processed in a new thread when it returns the <strong>show</strong> function is called with the <strong>sum</strong> return value and the <strong>Job</strong> instance.</p>  <h1><a id="user-content-spawning-processes" class="anchor" href="#spawning-processes" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Spawning processes</h1>  <p>Processes are created with the <strong>Expect</strong> class it uses threads to read and write to the process.</p>  <h3><a id="user-content-expect-class" class="anchor" href="#expect-class" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Expect class</h3>  <p>The expect class takes the name of the process and arguments it should be started witn. It inherits from <strong>Dispatcher</strong> as well.</p>  <div class="highlight highlight-source-python"><pre>expect <span class="pl-k">=</span> Expect(<span class="pl-s"><span class="pl-pds">'</span>process_name<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>arg0<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>arg1<span class="pl-pds">'</span></span>, <span class="pl-c1">...</span>)</pre></div>  <h3><a id="user-content-a-basic-example-spawn_processpy" class="anchor" href="#a-basic-example-spawn_processpy" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>A basic example (spawn_process.py)](#basic-clientserver-applications)
 * [Tasks</h1>  <h3><a id="user-content-task-class" class="anchor" href="#task-class" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Task class</h3>  <h3><a id="user-content-a-port-scan-port_scanpy" class="anchor" href="#a-port-scan-port_scanpy" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>A Port Scan (port_scan.py)</h3>  <h1><a id="user-content-basic-ssl-clientserver-applications" class="anchor" href="#basic-ssl-clientserver-applications" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Basic SSL Client/Server Applications</h1>  <h1><a id="user-content-the-irc-client-plugin" class="anchor" href="#the-irc-client-plugin" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>The IRC Client plugin</h1>  <h1><a id="user-content-reactor-flow-control" class="anchor" href="#reactor-flow-control" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Reactor flow control</h1>  <h3><a id="user-content-the-root-exception" class="anchor" href="#the-root-exception" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>The Root exception</h3>  <h3><a id="user-content-the-kill-exception" class="anchor" href="#the-kill-exception" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>The Kill exception</h3>  <h1><a id="user-content-debugging" class="anchor" href="#debugging" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Debugging</h1>  <h1><a id="user-content-tests" class="anchor" href="#tests" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Tests</h1> </article>   </div>  </div>  <button type="button" data-facebox="#jump-to-line" data-facebox-class="linejump" data-hotkey="l" class="hidden">Jump to Line</button> <div id="jump-to-line" style="display:none">   <!-- </textarea> --><!-- '"` --><form accept-charset="UTF-8" action="" class="js-jump-to-line-form" method="get"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /></div>     <input class="form-control linejump-input js-jump-to-line-field" type="text" placeholder="Jump to line&hellip;" aria-label="Jump to line" autofocus>     <button type="submit" class="btn">Go</button> </form></div>    </div>   <div class="modal-backdrop"></div> </div>       </div>   </div>      </div>          <div class="container site-footer-container">   <div class="site-footer" role="contentinfo">     <ul class="site-footer-links right">         <li><a href="https://status.github.com/" data-ga-click="Footer, go to status, text:status">Status</a></li>       <li><a href="https://developer.github.com" data-ga-click="Footer, go to api, text:api">API</a></li>       <li><a href="https://training.github.com" data-ga-click="Footer, go to training, text:training">Training</a></li>       <li><a href="https://shop.github.com" data-ga-click="Footer, go to shop, text:shop">Shop</a></li>         <li><a href="https://github.com/blog" data-ga-click="Footer, go to blog, text:blog">Blog</a></li>         <li><a href="https://github.com/about" data-ga-click="Footer, go to about, text:about">About</a></li>      </ul>      <a href="https://github.com" aria-label="Homepage" class="site-footer-mark">       <svg aria-hidden="true" class="octicon octicon-mark-github" height="24" title="GitHub " version="1.1" viewBox="0 0 16 16" width="24"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59 0.4 0.07 0.55-0.17 0.55-0.38 0-0.19-0.01-0.82-0.01-1.49-2.01 0.37-2.53-0.49-2.69-0.94-0.09-0.23-0.48-0.94-0.82-1.13-0.28-0.15-0.68-0.52-0.01-0.53 0.63-0.01 1.08 0.58 1.23 0.82 0.72 1.21 1.87 0.87 2.33 0.66 0.07-0.52 0.28-0.87 0.51-1.07-1.78-0.2-3.64-0.89-3.64-3.95 0-0.87 0.31-1.59 0.82-2.15-0.08-0.2-0.36-1.02 0.08-2.12 0 0 0.67-0.21 2.2 0.82 0.64-0.18 1.32-0.27 2-0.27 0.68 0 1.36 0.09 2 0.27 1.53-1.04 2.2-0.82 2.2-0.82 0.44 1.1 0.16 1.92 0.08 2.12 0.51 0.56 0.82 1.27 0.82 2.15 0 3.07-1.87 3.75-3.65 3.95 0.29 0.25 0.54 0.73 0.54 1.48 0 1.07-0.01 1.93-0.01 2.2 0 0.21 0.15 0.46 0.55 0.38C13.71 14.53 16 11.53 16 8 16 3.58 12.42 0 8 0z"></path></svg> </a>     <ul class="site-footer-links">       <li>&copy; 2016 <span title="0.05493s from github-fe138-cp1-prd.iad.github.net">GitHub</span>, Inc.</li>         <li><a href="https://github.com/site/terms" data-ga-click="Footer, go to terms, text:terms">Terms</a></li>         <li><a href="https://github.com/site/privacy" data-ga-click="Footer, go to privacy, text:privacy">Privacy</a></li>         <li><a href="https://github.com/security" data-ga-click="Footer, go to security, text:security">Security</a></li>         <li><a href="https://github.com/contact" data-ga-click="Footer, go to contact, text:contact">Contact</a></li>         <li><a href="https://help.github.com" data-ga-click="Footer, go to help, text:help">Help</a></li>     </ul>   </div> </div>                   <div id="ajax-error-message" class="ajax-error-message flash flash-error">       <svg aria-hidden="true" class="octicon octicon-alert" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M15.72 12.5l-6.85-11.98C8.69 0.21 8.36 0.02 8 0.02s-0.69 0.19-0.87 0.5l-6.85 11.98c-0.18 0.31-0.18 0.69 0 1C0.47 13.81 0.8 14 1.15 14h13.7c0.36 0 0.69-0.19 0.86-0.5S15.89 12.81 15.72 12.5zM9 12H7V10h2V12zM9 9H7V5h2V9z"></path></svg>       <button type="button" class="flash-close js-flash-close js-ajax-error-dismiss" aria-label="Dismiss error">         <svg aria-hidden="true" class="octicon octicon-x" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M7.48 8l3.75 3.75-1.48 1.48-3.75-3.75-3.75 3.75-1.48-1.48 3.75-3.75L0.77 4.25l1.48-1.48 3.75 3.75 3.75-3.75 1.48 1.48-3.75 3.75z"></path></svg>       </button>       Something went wrong with that request. Please try again.     </div>         <script crossorigin="anonymous" src="https://assets-cdn.github.com/assets/compat-7db58f8b7b91111107fac755dd8b178fe7db0f209ced51fc339c446ad3f8da2b.js"></script>       <script crossorigin="anonymous" src="https://assets-cdn.github.com/assets/frameworks-5c2c698a5a7dbecfbfed7180198b5cc5bc21d0588392269449bed16d124f0ea3.js"></script>       <script async="async" crossorigin="anonymous" src="https://assets-cdn.github.com/assets/github-bf0bf1cd49adbab6c52f3af0eab40c89621e0b56532eff5e7c943008c79e21ec.js"></script>                                 <div class="js-stale-session-flash stale-session-flash flash flash-warn flash-banner hidden">       <svg aria-hidden="true" class="octicon octicon-alert" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M15.72 12.5l-6.85-11.98C8.69 0.21 8.36 0.02 8 0.02s-0.69 0.19-0.87 0.5l-6.85 11.98c-0.18 0.31-0.18 0.69 0 1C0.47 13.81 0.8 14 1.15 14h13.7c0.36 0 0.69-0.19 0.86-0.5S15.89 12.81 15.72 12.5zM9 12H7V10h2V12zM9 9H7V5h2V9z"></path></svg>       <span class="signed-in-tab-flash">You signed in with another tab or window. <a href="">Reload</a> to refresh your session.</span>       <span class="signed-out-tab-flash">You signed out in another tab or window. <a href="">Reload</a> to refresh your session.</span>     </div>     <div class="facebox" id="facebox" style="display:none;">   <div class="facebox-popup">     <div class="facebox-content" role="dialog" aria-labelledby="facebox-header" aria-describedby="facebox-description">     </div>     <button type="button" class="facebox-close js-facebox-close" aria-label="Close modal">       <svg aria-hidden="true" class="octicon octicon-x" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M7.48 8l3.75 3.75-1.48 1.48-3.75-3.75-3.75 3.75-1.48-1.48 3.75-3.75L0.77 4.25l1.48-1.48 3.75 3.75 3.75-3.75 1.48 1.48-3.75 3.75z"></path></svg>     </button>   </div> </div>    </body> ](#tasks)

Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc)
[tau@lambda ~]$     
ekalinin commented 8 years ago

What OS do you use?

iogf commented 8 years ago

i'm on an arch linux.

ekalinin commented 8 years ago

Ok, I'm on Ubuntu 15.10. And it's work for me. Let's check versions of internally used tools. Here's my stats:

➥ uname -m
x86_64
➥ curl --version | head -n 1
curl 7.43.0 (x86_64-pc-linux-gnu) libcurl/7.43.0 GnuTLS/3.3.15 zlib/1.2.8 libidn/1.28 librtmp/2.3
➥ grep --version | head -n 1
grep (GNU grep) 2.21
➥ sed --version | head -n 1
sed (GNU sed) 4.2.2
➥ awk -W version
mawk 1.3.3 Nov 1996, Copyright (C) Michael D. Brennan

compiled limits:
max NF             32767
sprintf buffer      2040

Would you be able to show versions of the same tools on your OS?

PS: there's a go-based version of this tool:

It more robust and reliable. And it has precompiled binaries. You can try it.

iogf commented 8 years ago
$ uname -a
Linux lambda 4.4.1-2-ARCH #1 SMP PREEMPT Wed Feb 3 13:12:33 UTC 2016 x86_64 GNU/Linux
$ curl --version | head -n 1
curl 7.47.1 (x86_64-pc-linux-gnu) libcurl/7.47.1 OpenSSL/1.0.2f zlib/1.2.8 libidn/1.32 libssh2/1.6.0
$ grep --version | head -n 1
grep (GNU grep) 2.23
$ awk -W version
GNU Awk 4.1.3, API: 1.1 (GNU MPFR 3.1.3-p5, GNU MP 6.1.0)
Copyright (C) 1989, 1991-2015 Free Software Foundation.
# ...
hasufell commented 8 years ago

same here, unusable that way

ekalinin commented 8 years ago

hey @hasufell

Would you be able to show the output of the commands:

Thanks!

hasufell commented 8 years ago
$ uname -a
Linux localhost 3.18.26+ #4 SMP Fri Feb 26 13:11:53 CET 2016 x86_64 GNU/Linux
$ curl --version | head -n 1
curl 7.49.1 (x86_64-pc-linux-gnu) libcurl/7.49.1 LibreSSL/2.0.0 zlib/1.2.8 libssh2/1.7.0
$ grep --version | head -n 1
grep (GNU grep) 2.25
$ sed --version | head -n 1
sed (GNU sed) 4.2.2
$ awk -W version
GNU Awk 4.1.3, API: 1.1 (GNU MPFR 3.1.4, GNU MP 6.1.0)
ekalinin commented 8 years ago

Seems, GNU Awk is a root of the problem.