<?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: Using usage.Options</title><link href="../howto/stylesheet.css" type="text/css" rel="stylesheet" /></head><body bgcolor="white"><h1 class="title">Using usage.Options</h1><div class="toc"><ol><li><a href="#auto0">Introduction</a></li><li><a href="#auto1">Boolean Options</a></li><ul><li><a href="#auto2">Inheritance, Or: How I Learned to Stop Worrying and Love the Superclass</a></li></ul><li><a href="#auto3">Parameters</a></li><li><a href="#auto4">Option Subcommands</a></li><li><a href="#auto5">Generic Code For Options</a></li><li><a href="#auto6">Parsing Arguments</a></li><li><a href="#auto7">Post Processing</a></li></ol></div><div class="content"><span></span><h2>Introduction<a name="auto0"></a></h2><p>There is frequently a need for programs to parse a UNIX-like command line program: options preceded by <code>-</code> or <code>--</code>, sometimes followed by a parameter, followed by a list of arguments. The <code class="API">twisted.python.usage</code> provides a class, <code>Options</code>, to facilitate such parsing.</p><p>While Python has the <code>getopt</code> module for doing this, it provides a very low level of abstraction for options. Twisted has a higher level of abstraction, in the class <code class="API">twisted.python.usage.Options</code>. It uses Python's reflection facilities to provide an easy to use yet flexible interface to the command line. While most command line processors either force the application writer to write her own loops, or have arbitrary limitations on the command line (the most common one being not being able to have more then one instance of a specific option, thus rendering the idiom <code class="shell">program -v -v -v</code> impossible), Twisted allows the programmer to decide how much control she wants.</p><p>The <code>Options</code> class is used by subclassing. Since a lot of time it will be used in the <code class="API">twisted.tap</code> package, where the local conventions require the specific options parsing class to also be called <code>Options</code>, it is usually imported with</p><pre class="python"> <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> </pre><h2>Boolean Options<a name="auto1"></a></h2><p>For simple boolean options, define the attribute <code>optFlags</code> like this:</p><pre class="python"> <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">optFlags</span> = [[<span class="py-src-string">"fast"</span>, <span class="py-src-string">"f"</span>, <span class="py-src-string">"Act quickly"</span>], [<span class="py-src-string">"safe"</span>, <span class="py-src-string">"s"</span>, <span class="py-src-string">"Act safely"</span>]] </pre><p><code>optFlags</code> should be a list of 3-lists. The first element is the long name, and will be used on the command line as <code>--fast</code>. The second one is the short name, and will be used on the command line as <code>-f</code>. The last element is a description of the flag and will be used to generate the usage information text. The long name also determines the name of the key that will be set on the Options instance. Its value will be 1 if the option was seen, 0 otherwise. Here is an example for usage:</p><pre class="python"> <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">optFlags</span> = [ [<span class="py-src-string">"fast"</span>, <span class="py-src-string">"f"</span>, <span class="py-src-string">"Act quickly"</span>], [<span class="py-src-string">"good"</span>, <span class="py-src-string">"g"</span>, <span class="py-src-string">"Act well"</span>], [<span class="py-src-string">"cheap"</span>, <span class="py-src-string">"c"</span>, <span class="py-src-string">"Act cheaply"</span>] ] <span class="py-src-variable">command_line</span> = [<span class="py-src-string">"-g"</span>, <span class="py-src-string">"--fast"</span>] <span class="py-src-variable">options</span> = <span class="py-src-variable">Options</span>() <span class="py-src-keyword">try</span>: <span class="py-src-variable">options</span>.<span class="py-src-variable">parseOptions</span>(<span class="py-src-variable">command_line</span>) <span class="py-src-keyword">except</span> <span class="py-src-variable">usage</span>.<span class="py-src-variable">UsageError</span>, <span class="py-src-variable">errortext</span>: <span class="py-src-keyword">print</span> <span class="py-src-string">'%s: %s'</span> % (<span class="py-src-variable">sys</span>.<span class="py-src-variable">argv</span>[<span class="py-src-number">0</span>], <span class="py-src-variable">errortext</span>) <span class="py-src-keyword">print</span> <span class="py-src-string">'%s: Try --help for usage details.'</span> % (<span class="py-src-variable">sys</span>.<span class="py-src-variable">argv</span>[<span class="py-src-number">0</span>]) <span class="py-src-variable">sys</span>.<span class="py-src-variable">exit</span>(<span class="py-src-number">1</span>) <span class="py-src-keyword">if</span> <span class="py-src-variable">options</span>[<span class="py-src-string">'fast'</span>]: <span class="py-src-keyword">print</span> <span class="py-src-string">"fast"</span>, <span class="py-src-keyword">if</span> <span class="py-src-variable">options</span>[<span class="py-src-string">'good'</span>]: <span class="py-src-keyword">print</span> <span class="py-src-string">"good"</span>, <span class="py-src-keyword">if</span> <span class="py-src-variable">options</span>[<span class="py-src-string">'cheap'</span>]: <span class="py-src-keyword">print</span> <span class="py-src-string">"cheap"</span>, <span class="py-src-keyword">print</span> </pre><p>The above will print <code>fast good</code>.</p><p>Note here that Options fully supports the mapping interface. You can access it mostly just like you can access any other dict. Options are stored as mapping items in the Options instance: parameters as 'paramname': 'value' and flags as 'flagname': 1 or 0.</p><h3>Inheritance, Or: How I Learned to Stop Worrying and Love the Superclass<a name="auto2"></a></h3><p>Sometimes there is a need for several option processors with a unifying core. Perhaps you want all your commands to understand <code>-q</code>/<code>--quiet</code> means to be quiet, or something similar. On the face of it, this looks impossible: in Python, the subclass's <code>optFlags</code> would shadow the superclass's. However, <code>usage.Options</code> uses special reflection code to get all of the <code>optFlags</code> defined in the hierarchy. So the following:</p><pre class="python"> <span class="py-src-keyword">class</span> <span class="py-src-identifier">BaseOptions</span>(<span class="py-src-parameter">usage</span>.<span class="py-src-parameter">Options</span>): <span class="py-src-variable">optFlags</span> = [[<span class="py-src-string">"quiet"</span>, <span class="py-src-string">"q"</span>, <span class="py-src-variable">None</span>]] <span class="py-src-keyword">class</span> <span class="py-src-identifier">SpecificOptions</span>(<span class="py-src-parameter">BaseOptions</span>): <span class="py-src-variable">optFlags</span> = [ [<span class="py-src-string">"fast"</span>, <span class="py-src-string">"f"</span>, <span class="py-src-variable">None</span>], [<span class="py-src-string">"good"</span>, <span class="py-src-string">"g"</span>, <span class="py-src-variable">None</span>], [<span class="py-src-string">"cheap"</span>, <span class="py-src-string">"c"</span>, <span class="py-src-variable">None</span>] ] </pre><p>Is the same as: </p><pre class="python"> <span class="py-src-keyword">class</span> <span class="py-src-identifier">SpecificOptions</span>(<span class="py-src-parameter">BaseOptions</span>): <span class="py-src-variable">optFlags</span> = [ [<span class="py-src-string">"quiet"</span>, <span class="py-src-string">"q"</span>, <span class="py-src-string">"Silence output"</span>], [<span class="py-src-string">"fast"</span>, <span class="py-src-string">"f"</span>, <span class="py-src-string">"Run quickly"</span>], [<span class="py-src-string">"good"</span>, <span class="py-src-string">"g"</span>, <span class="py-src-string">"Don't validate input"</span>], [<span class="py-src-string">"cheap"</span>, <span class="py-src-string">"c"</span>, <span class="py-src-string">"Use cheap resources"</span>] ] </pre><h2>Parameters<a name="auto3"></a></h2><p>Parameters are specified using the attribute <code>optParameters</code>. They <em>must</em> be given a default. If you want to make sure you got the parameter from the command line, give a non-string default. Since the command line only has strings, this is completely reliable.</p><p>Here is an example:</p><pre class="python"> <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">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">optFlags</span> = [ [<span class="py-src-string">"fast"</span>, <span class="py-src-string">"f"</span>, <span class="py-src-string">"Run quickly"</span>], [<span class="py-src-string">"good"</span>, <span class="py-src-string">"g"</span>, <span class="py-src-string">"Don't validate input"</span>], [<span class="py-src-string">"cheap"</span>, <span class="py-src-string">"c"</span>, <span class="py-src-string">"Use cheap resources"</span>] ] <span class="py-src-variable">optParameters</span> = [[<span class="py-src-string">"user"</span>, <span class="py-src-string">"u"</span>, <span class="py-src-variable">None</span>, <span class="py-src-string">"The user name"</span>]] <span class="py-src-variable">config</span> = <span class="py-src-variable">Options</span>() <span class="py-src-keyword">try</span>: <span class="py-src-variable">config</span>.<span class="py-src-variable">parseOptions</span>() <span class="py-src-comment"># When given no argument, parses sys.argv[1:]</span> <span class="py-src-keyword">except</span> <span class="py-src-variable">usage</span>.<span class="py-src-variable">UsageError</span>, <span class="py-src-variable">errortext</span>: <span class="py-src-keyword">print</span> <span class="py-src-string">'%s: %s'</span> % (<span class="py-src-variable">sys</span>.<span class="py-src-variable">argv</span>[<span class="py-src-number">0</span>], <span class="py-src-variable">errortext</span>) <span class="py-src-keyword">print</span> <span class="py-src-string">'%s: Try --help for usage details.'</span> % (<span class="py-src-variable">sys</span>.<span class="py-src-variable">argv</span>[<span class="py-src-number">0</span>]) <span class="py-src-variable">sys</span>.<span class="py-src-variable">exit</span>(<span class="py-src-number">1</span>) <span class="py-src-keyword">if</span> <span class="py-src-variable">config</span>[<span class="py-src-string">'user'</span>] <span class="py-src-keyword">is</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">None</span>: <span class="py-src-keyword">print</span> <span class="py-src-string">"Hello"</span>, <span class="py-src-variable">config</span>[<span class="py-src-string">'user'</span>] <span class="py-src-keyword">print</span> <span class="py-src-string">"So, you want it:"</span> <span class="py-src-keyword">if</span> <span class="py-src-variable">config</span>[<span class="py-src-string">'fast'</span>]: <span class="py-src-keyword">print</span> <span class="py-src-string">"fast"</span>, <span class="py-src-keyword">if</span> <span class="py-src-variable">config</span>[<span class="py-src-string">'good'</span>]: <span class="py-src-keyword">print</span> <span class="py-src-string">"good"</span>, <span class="py-src-keyword">if</span> <span class="py-src-variable">config</span>[<span class="py-src-string">'cheap'</span>]: <span class="py-src-keyword">print</span> <span class="py-src-string">"cheap"</span>, <span class="py-src-keyword">print</span> </pre><p>Like <code>optFlags</code>, <code>optParameters</code> works smoothly with inheritance.</p><h2>Option Subcommands<a name="auto4"></a></h2><p>It is useful, on occassion, to group a set of options together based on the logical <q>action</q> to which they belong. For this, the <code>usage.Options</code> class allows you to define a set of <q>subcommands</q>, each of which can provide its own <code>usage.Options</code> instance to handle its particular options.</p><p>Here is an example for an Options class that might parse options like those the cvs program takes</p><pre class="python"> <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">class</span> <span class="py-src-identifier">ImportOptions</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">'module'</span>, <span class="py-src-string">'m'</span>, <span class="py-src-variable">None</span>, <span class="py-src-variable">None</span>], [<span class="py-src-string">'vendor'</span>, <span class="py-src-string">'v'</span>, <span class="py-src-variable">None</span>, <span class="py-src-variable">None</span>], [<span class="py-src-string">'release'</span>, <span class="py-src-string">'r'</span>, <span class="py-src-variable">None</span>] ] <span class="py-src-keyword">class</span> <span class="py-src-identifier">CheckoutOptions</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">'module'</span>, <span class="py-src-string">'m'</span>, <span class="py-src-variable">None</span>, <span class="py-src-variable">None</span>], [<span class="py-src-string">'tag'</span>, <span class="py-src-string">'r'</span>, <span class="py-src-variable">None</span>, <span class="py-src-variable">None</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">subCommands</span> = [[<span class="py-src-string">'import'</span>, <span class="py-src-variable">None</span>, <span class="py-src-variable">ImportOptions</span>, <span class="py-src-string">"Do an Import"</span>], [<span class="py-src-string">'checkout'</span>, <span class="py-src-variable">None</span>, <span class="py-src-variable">CheckoutOptions</span>, <span class="py-src-string">"Do a Checkout"</span>]] <span class="py-src-variable">optParameters</span> = [ [<span class="py-src-string">'compression'</span>, <span class="py-src-string">'z'</span>, <span class="py-src-number">0</span>, <span class="py-src-string">'Use compression'</span>], [<span class="py-src-string">'repository'</span>, <span class="py-src-string">'r'</span>, <span class="py-src-variable">None</span>, <span class="py-src-string">'Specify an alternate repository'</span>] ] <span class="py-src-variable">config</span> = <span class="py-src-variable">Options</span>(); <span class="py-src-variable">config</span>.<span class="py-src-variable">parseOptions</span>() <span class="py-src-keyword">if</span> <span class="py-src-variable">config</span>.<span class="py-src-variable">subCommand</span> == <span class="py-src-string">'import'</span>: <span class="py-src-variable">doImport</span>(<span class="py-src-variable">config</span>.<span class="py-src-variable">subOptions</span>) <span class="py-src-keyword">elif</span> <span class="py-src-variable">config</span>.<span class="py-src-variable">subCommand</span> == <span class="py-src-string">'checkout'</span>: <span class="py-src-variable">doCheckout</span>(<span class="py-src-variable">config</span>.<span class="py-src-variable">subOptions</span>) </pre><p>The <code>subCommands</code> attribute of <code>Options</code> directs the parser to the two other <code>Options</code> subclasses when the strings <code>"import"</code> or <code>"checkout"</code> are present on the command line. All options after the given command string are passed to the specified Options subclass for further parsing. Only one subcommand may be specified at a time. After parsing has completed, the Options instance has two new attributes - <code>subCommand</code> and <code> subOptions</code> - which hold the command string and the Options instance used to parse the remaining options.</p><h2>Generic Code For Options<a name="auto5"></a></h2><p>Sometimes, just setting an attribute on the basis of the options is not flexible enough. In those cases, Twisted does not even attempt to provide abstractions such as <q>counts</q> or <q>lists</q>, but rathers lets you call your own method, which will be called whenever the option is encountered.</p><p>Here is an example of counting verbosity</p><pre class="python"> <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">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-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>): <span class="py-src-variable">usage</span>.<span class="py-src-variable">Options</span>.<span class="py-src-variable">__init__</span>(<span class="py-src-variable">self</span>) <span class="py-src-variable">self</span>[<span class="py-src-string">'verbosity'</span>] = <span class="py-src-number">0</span> <span class="py-src-comment"># default</span> <span class="py-src-keyword">def</span> <span class="py-src-identifier">opt_verbose</span>(<span class="py-src-parameter">self</span>): <span class="py-src-variable">self</span>[<span class="py-src-string">'verbosity'</span>] = <span class="py-src-variable">self</span>[<span class="py-src-string">'verbosity'</span>]+<span class="py-src-number">1</span> <span class="py-src-keyword">def</span> <span class="py-src-identifier">opt_quiet</span>(<span class="py-src-parameter">self</span>): <span class="py-src-variable">self</span>[<span class="py-src-string">'verbosity'</span>] = <span class="py-src-variable">self</span>[<span class="py-src-string">'verbosity'</span>]-<span class="py-src-number">1</span> <span class="py-src-variable">opt_v</span> = <span class="py-src-variable">opt_verbose</span> <span class="py-src-variable">opt_q</span> = <span class="py-src-variable">opt_quiet</span> </pre><p>Command lines that look like <code class="shell">command -v -v -v -v</code> will increase verbosity to 4, while <code class="shell">command -q -q -q</code> will decrease verbosity to -3. </p><p>The <code base="twisted.python" class="API">usage.Options</code> class knows that these are parameter-less options, since the methods do not receive an argument. Here is an example for a method with a parameter:</p><pre class="python"> <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">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-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>): <span class="py-src-variable">usage</span>.<span class="py-src-variable">Options</span>.<span class="py-src-variable">__init__</span>(<span class="py-src-variable">self</span>) <span class="py-src-variable">self</span>[<span class="py-src-string">'symbols'</span>] = [] <span class="py-src-keyword">def</span> <span class="py-src-identifier">opt_define</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">symbol</span>): <span class="py-src-variable">self</span>[<span class="py-src-string">'symbols'</span>].<span class="py-src-variable">append</span>(<span class="py-src-variable">symbol</span>) <span class="py-src-variable">opt_D</span> = <span class="py-src-variable">opt_define</span> </pre><p>This example is useful for the common idiom of having <code>command -DFOO -DBAR</code> to define symbols.</p><h2>Parsing Arguments<a name="auto6"></a></h2><p><code>usage.Options</code> does not stop helping when the last parameter is gone. All the other arguments are sent into a function which should deal with them. Here is an example for a <code>cmp</code> like command.</p><pre class="python"> <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">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">"max_differences"</span>, <span class="py-src-string">"d"</span>, <span class="py-src-number">1</span>, <span class="py-src-variable">None</span>]] <span class="py-src-keyword">def</span> <span class="py-src-identifier">parseArgs</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">origin</span>, <span class="py-src-parameter">changed</span>): <span class="py-src-variable">self</span>[<span class="py-src-string">'origin'</span>] = <span class="py-src-variable">origin</span> <span class="py-src-variable">self</span>[<span class="py-src-string">'changed'</span>] = <span class="py-src-variable">changed</span> </pre><p>The command should look like <code>command origin changed</code>.</p><p>If you want to have a variable number of left-over arguments, just use <code>def parseArgs(self, *args):</code>. This is useful for commands like the UNIX <code>cat(1)</code>.</p><h2>Post Processing<a name="auto7"></a></h2><p>Sometimes, you want to perform post processing of options to patch up inconsistencies, and the like. Here is an example:</p><pre class="python"> <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">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">optFlags</span> = [ [<span class="py-src-string">"fast"</span>, <span class="py-src-string">"f"</span>, <span class="py-src-string">"Run quickly"</span>], [<span class="py-src-string">"good"</span>, <span class="py-src-string">"g"</span>, <span class="py-src-string">"Don't validate input"</span>], [<span class="py-src-string">"cheap"</span>, <span class="py-src-string">"c"</span>, <span class="py-src-string">"Use cheap resources"</span>] ] <span class="py-src-keyword">def</span> <span class="py-src-identifier">postOptions</span>(<span class="py-src-parameter">self</span>): <span class="py-src-keyword">if</span> <span class="py-src-variable">self</span>[<span class="py-src-string">'fast'</span>] <span class="py-src-keyword">and</span> <span class="py-src-variable">self</span>[<span class="py-src-string">'good'</span>] <span class="py-src-keyword">and</span> <span class="py-src-variable">self</span>[<span class="py-src-string">'cheap'</span>]: <span class="py-src-keyword">raise</span> <span class="py-src-variable">usage</span>.<span class="py-src-variable">UsageError</span>, <span class="py-src-string">"can't have it all, brother"</span> </pre></div><p><a href="../howto/index.html">Index</a></p><span class="version">Version: 2.5.0</span></body></html>