<?xml version="1.0"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><title>Twisted Documentation: Writing a Twisted Application Plugin for twistd</title><link href="../howto/stylesheet.css" type="text/css" rel="stylesheet" /></head><body bgcolor="white"><h1 class="title">Writing a Twisted Application Plugin for twistd</h1><div class="toc"><ol><li><a href="#auto0">Goals</a></li><li><a href="#auto1">A note on .tap files</a></li><li><a href="#auto2">Alternatives to TAP</a></li><li><a href="#auto3">Creating the plugin</a></li><li><a href="#auto4">Conclusion</a></li></ol></div><div class="content"><span></span><p>This document describes writing extension subcommands for the <code>twistd</code> command, as a way to facilitate the deployment of your applications. <em>(This feature was added in Twisted 2.5)</em></p><p>The target audience of this document are those that have developed a Twisted application which needs a command line-based deployment mechanism.</p><p>There are a few prerequisites to understanding this document:</p><ul><li>A basic understanding of the Twisted Plugin System (i.e., the <code class="API">twisted.plugin</code> module) is necessary, however, step-by-step instructions will be given. Reading <a href="plugin.html">The Twisted Plugin System</a> is recommended, in particular the <q>Extending an Existing Program</q> section.</li><li>The <a href="application.html">Application</a> infrastructure is used in Twisted Application Plugins; in particular, you should know how to expose your program's functionality as a Service.</li><li>In order to parse command line arguments, the Twisted Application Plugin system relies on <code>twisted.python.usage</code>, which is documented in <a href="options.html">Using usage.Options</a>.</li></ul><h2>Goals<a name="auto0"></a></h2><p>After reading this document, the reader should be able to expose their Service-using application as a subcommand of <code>twistd</code>, taking into consideration whatever was passed on the command line.</p><h2>A note on .tap files<a name="auto1"></a></h2><p>Readers may be confused about a historical file type associated with Twisted, the <code>.tap</code> file. This was a kind of file that was generated by a program named <code>mktap</code> and which <code>twistd</code> can read. <code>.tap</code> files are deprecated; this document has nothing to do with them, although the technology described herein is very closely related to the old system. <q>TAP</q>, in the modern Twisted vernacular, means <q>Twisted Application Plugin</q>. </p><h2>Alternatives to TAP<a name="auto2"></a></h2><p>The major alternative to the TAP mechanism is the <code>.tac</code> file, which is a simple script to be used with the twistd <code>-y/--python</code> parameter. The TAP plugin system exists to offer a more extensible command-line-driven interface to your application. For more information on <code>.tac</code> files, see the document <a href="application.html">Using the Twisted Application Framework</a>.</p><h2>Creating the plugin<a name="auto3"></a></h2><p>The following directory structure is assumed of your project:</p><ul><li><strong>MyProject</strong> - Top level directory <ul><li><strong>myproject</strong> - Python package <ul><li><strong>__init__.py</strong></li></ul></li></ul></li></ul><p> During development of your project, Twisted plugins can be loaded from a special directory in your project, assuming your top level directory ends up in sys.path. Create a directory named <code>twisted</code> containing a directory named <code>plugins</code>, and add a file named <code>myproject.py</code> to it. This file will contain your plugin. Note that you should <em>not</em> add any __init__.py files to this directory structure. </p><p> In this file, define an object which <em>provides</em> the interfaces <code class="API">twisted.plugin.IPlugin</code> and <code class="API">twisted.application.service.IServiceMaker</code>. </p><p>The <code>tapname</code> attribute of your IServiceMaker provider will be used as the subcommand name in a command like <code class="shell">twistd [subcommand] [args...]</code>, and the <code>options</code> attribute (which should be a <code base="twisted.python" class="API">usage.Options</code> subclass) will be used to parse the given args.</p><pre class="python"> <span class="py-src-keyword">from</span> <span class="py-src-variable">zope</span>.<span class="py-src-variable">interface</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">implements</span> <span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">python</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">usage</span> <span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">plugin</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">IPlugin</span> <span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">application</span>.<span class="py-src-variable">service</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">IServiceMaker</span> <span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">application</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">internet</span> <span class="py-src-keyword">from</span> <span class="py-src-variable">myproject</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">MyFactory</span> <span class="py-src-keyword">class</span> <span class="py-src-identifier">Options</span>(<span class="py-src-parameter">usage</span>.<span class="py-src-parameter">Options</span>): <span class="py-src-variable">optParameters</span> = [[<span class="py-src-string">"port"</span>, <span class="py-src-string">"p"</span>, <span class="py-src-number">1235</span>, <span class="py-src-string">"The port number to listen on."</span>]] <span class="py-src-keyword">class</span> <span class="py-src-identifier">MyServiceMaker</span>(<span class="py-src-parameter">object</span>): <span class="py-src-variable">implements</span>(<span class="py-src-variable">IServiceMaker</span>, <span class="py-src-variable">IPlugin</span>) <span class="py-src-variable">tapname</span> = <span class="py-src-string">"myproject"</span> <span class="py-src-variable">description</span> = <span class="py-src-string">"Run this! It'll make your dog happy."</span> <span class="py-src-variable">options</span> = <span class="py-src-variable">Options</span> <span class="py-src-keyword">def</span> <span class="py-src-identifier">makeService</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">options</span>): <span class="py-src-string">""" Construct a TCPServer from a factory defined in myproject. """</span> <span class="py-src-keyword">return</span> <span class="py-src-variable">internet</span>.<span class="py-src-variable">TCPServer</span>(<span class="py-src-variable">int</span>(<span class="py-src-variable">options</span>[<span class="py-src-string">"port"</span>]), <span class="py-src-variable">MyFactory</span>()) <span class="py-src-comment"># Now construct an object which *provides* the relevant interfaces </span> <span class="py-src-comment"># The name of this variable is irrelevant, as long as there is *some* </span><span class="py-src-comment"># name bound to a provider of IPlugin and IServiceMaker. </span> <span class="py-src-variable">serviceMaker</span> = <span class="py-src-variable">MyServiceMaker</span>() </pre><p> Now running <code class="shell">twistd --help</code> should print <code>myproject</code> in the list of available subcommands, followed by the description that we specified in the plugin. <code class="shell">twistd -n myproject</code> would, assuming we defined a <code>MyFactory</code> factory inside <code>myproject</code>, start a listening server on port 1235 with that factory. </p><h2>Conclusion<a name="auto4"></a></h2><p>You should now be able to</p><ul><li>Create a twistd plugin</li><li>Use it from your development environment</li><li>Install it correctly and use it in deployment</li></ul></div><p><a href="../howto/index.html">Index</a></p><span class="version">Version: 2.5.0</span></body></html>