summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichele Simionato <michele.simionato@gmail.com>2010-06-01 13:22:00 +0200
committerMichele Simionato <michele.simionato@gmail.com>2010-06-01 13:22:00 +0200
commit7ee9559aa9313824ea327111b7287b716172c286 (patch)
treedef050dfc4dfc55848be93dcd5725b50a4fb85b3
parent97dcd8ebb064319da3060d9795d4943b88870cd3 (diff)
downloadmicheles-7ee9559aa9313824ea327111b7287b716172c286.tar.gz
Removed the clap project remnants
-rw-r--r--clap/article/annotations.py8
-rw-r--r--clap/article/article.html410
-rw-r--r--clap/article/article.pdf2418
-rw-r--r--clap/article/article.txt442
l---------clap/article/clap.py1
-rw-r--r--clap/article/example1.py13
-rw-r--r--clap/article/example10.py14
-rw-r--r--clap/article/example11.py12
-rw-r--r--clap/article/example2.py10
-rw-r--r--clap/article/example3.py6
-rw-r--r--clap/article/example4.py14
-rw-r--r--clap/article/example4_.py8
-rw-r--r--clap/article/example5.py8
-rw-r--r--clap/article/example6.py12
-rw-r--r--clap/article/example7.py9
-rw-r--r--clap/article/example8.py7
-rw-r--r--clap/article/example9.py7
-rw-r--r--clap/doc.html187
-rw-r--r--clap/doc.txt82
-rw-r--r--clap/example.py20
-rw-r--r--clap/example.txt31
-rw-r--r--plac/README.txt (renamed from clap/README.txt)20
-rw-r--r--plac/plac.py (renamed from clap/clap.py)46
-rw-r--r--plac/setup.py29
-rw-r--r--plac/test_plac.py (renamed from clap/test_clap.py)55
25 files changed, 98 insertions, 3771 deletions
diff --git a/clap/article/annotations.py b/clap/article/annotations.py
deleted file mode 100644
index c84cc04..0000000
--- a/clap/article/annotations.py
+++ /dev/null
@@ -1,8 +0,0 @@
-class Positional(object):
- def __init__(self, help='', type=None, choices=None, metavar=None):
- self.help = help
- self.kind = 'positional'
- self.abbrev = None
- self.type = type
- self.choices = choices
- self.metavar = metavar
diff --git a/clap/article/article.html b/clap/article/article.html
deleted file mode 100644
index 65d0c68..0000000
--- a/clap/article/article.html
+++ /dev/null
@@ -1,410 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!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" xml:lang="en" lang="en">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
-<title></title>
-<style type="text/css">
-
-.highlight { background: #f8f8f8; }
-.highlight .c { color: #408080; font-style: italic } /* Comment */
-.highlight .err { border: 1px solid #FF0000 } /* Error */
-.highlight .k { color: #008000; font-weight: bold } /* Keyword */
-.highlight .o { color: #666666 } /* Operator */
-.highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */
-.highlight .cp { color: #BC7A00 } /* Comment.Preproc */
-.highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */
-.highlight .cs { color: #408080; font-style: italic } /* Comment.Special */
-.highlight .gd { color: #A00000 } /* Generic.Deleted */
-.highlight .ge { font-style: italic } /* Generic.Emph */
-.highlight .gr { color: #FF0000 } /* Generic.Error */
-.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
-.highlight .gi { color: #00A000 } /* Generic.Inserted */
-.highlight .go { color: #808080 } /* Generic.Output */
-.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
-.highlight .gs { font-weight: bold } /* Generic.Strong */
-.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
-.highlight .gt { color: #0040D0 } /* Generic.Traceback */
-.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
-.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
-.highlight .kp { color: #008000 } /* Keyword.Pseudo */
-.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
-.highlight .kt { color: #008000; font-weight: bold } /* Keyword.Type */
-.highlight .m { color: #666666 } /* Literal.Number */
-.highlight .s { color: #BA2121 } /* Literal.String */
-.highlight .na { color: #7D9029 } /* Name.Attribute */
-.highlight .nb { color: #008000 } /* Name.Builtin */
-.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */
-.highlight .no { color: #880000 } /* Name.Constant */
-.highlight .nd { color: #AA22FF } /* Name.Decorator */
-.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
-.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
-.highlight .nf { color: #0000FF } /* Name.Function */
-.highlight .nl { color: #A0A000 } /* Name.Label */
-.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
-.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
-.highlight .nv { color: #19177C } /* Name.Variable */
-.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
-.highlight .w { color: #bbbbbb } /* Text.Whitespace */
-.highlight .mf { color: #666666 } /* Literal.Number.Float */
-.highlight .mh { color: #666666 } /* Literal.Number.Hex */
-.highlight .mi { color: #666666 } /* Literal.Number.Integer */
-.highlight .mo { color: #666666 } /* Literal.Number.Oct */
-.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */
-.highlight .sc { color: #BA2121 } /* Literal.String.Char */
-.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
-.highlight .s2 { color: #BA2121 } /* Literal.String.Double */
-.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
-.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */
-.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
-.highlight .sx { color: #008000 } /* Literal.String.Other */
-.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
-.highlight .s1 { color: #BA2121 } /* Literal.String.Single */
-.highlight .ss { color: #19177C } /* Literal.String.Symbol */
-.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */
-.highlight .vc { color: #19177C } /* Name.Variable.Class */
-.highlight .vg { color: #19177C } /* Name.Variable.Global */
-.highlight .vi { color: #19177C } /* Name.Variable.Instance */
-.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
-
-</style>
-</head>
-<body>
-<div class="document">
-
-
-<div class="section" id="the-easiest-command-line-arguments-parser-in-the-python-world">
-<h1>The easiest command line arguments parser in the Python world</h1>
-<p>Today I want to announce to the general public the birth of my latest
-project, which aims to be the easiest command line arguments
-parser in the Python world: <a class="reference external" href="http://www.welton.it/articles/scalable_systems">clap</a>.</p>
-<p><a class="reference external" href="http://www.welton.it/articles/scalable_systems">clap</a> is designed to be <a class="reference external" href="http://www.welton.it/articles/scalable_systems">downwardly scalable</a>, i.e. to be trivially simple
-to use for trivial use cases, while being surprisingly scalable upwards
-for less trivial use cases. Still, <a class="reference external" href="http://www.welton.it/articles/scalable_systems">clap</a> is not intended to
-be an industrial strength command line parsing module. Its
-capabilities are limited by design. If you need more power, by all means
-use the parsing modules in the standard library. Still, I have been using
-Python for 8 years and never once I had to use the full power of the
-standard library modules.</p>
-<p>Actually I am prettu much convinced that features provided by <tt class="docutils literal">clap</tt>
-aee more than enough for 99.9% of the typical use cases of a scripter
-working in a Unix-like environment. I am targetting here programmers,
-sysadmins, scientists and in general people writing throw-away scripts
-for themselves, choosing to use a command line interface because it is
-the quick and simple. Such users are not interested in features,
-they just want to be able to write a simple command line tool from a
-simple specification, not to build a command line parser by
-hand. Unfortunately, the current modules in the standard library
-forces them to go the hard way. They are designed to implement
-power user tools for programmers or system administrators, and
-they have a non-trivial learning curve.</p>
-<p>This is why, even if there is no want of command line arguments
-parsers in Python world, sometime like <a class="reference external" href="http://www.welton.it/articles/scalable_systems">clap</a> was still lacking.</p>
-<p>The standard library alone contains three different modules for the
-parsing of command line options: <a class="reference external" href="http://docs.python.org/library/getopt.html">getopt</a> (from the stone age),
-<a class="reference external" href="http://docs.python.org/library/optparse.html">optparse</a> (from Python 2.3) and <a class="reference external" href="http://argparse.googlecode.com">argparse</a> (from Python 2.7). All of
-them are quite powerful and especially <a class="reference external" href="http://argparse.googlecode.com">argparse</a> is an industrial
-strength solution; <a class="reference external" href="http://www.welton.it/articles/scalable_systems">clap</a> is just a nice and simple wrapper over
-<a class="reference external" href="http://argparse.googlecode.com">argparse</a>, hiding most of the complexity while retaining most of
-the power.</p>
-</div>
-<div class="section" id="the-importance-of-scaling-down">
-<h1>The importance of scaling down</h1>
-<p>An ex-coworket of mine, David Welton, once wrote a nice article about
-the importance of <a class="reference external" href="http://www.welton.it/articles/scalable_systems">scaling down</a>: most people are concerned with the
-possibility of scaling up, but we should also be concerned with the
-issue of scaling down: in other worlds, simple things should be kept
-simple. To be concrete, let me start with the simplest possible
-thing: a script that takes a single argument and does something to it.
-It cannot get more trivial than that (discarding the possibility of
-a script without command line arguments, where there is nothing to parse),
-nevertheless it is a use case <em>extremely important</em>:
-I need to write scripts like that nearly every day, I wrote hundreds
-of them in the last few years and I have never been happy. Here is
-a typical example:</p>
-<blockquote>
-<pre class="literal-block">
-def main(dsn):
- &quot;Do something with the database&quot;
- print(dsn)
-
-if __name__ == '__main__':
- import sys
- n = len(sys.argv[1:])
- if n == 0:
- sys.exit('usage: python %s dsn' % sys.argv[0])
- elif n == 1:
- main(sys.argv[1])
- else:
- sys.exit('Unrecognized arguments: %s' % ' '.join(sys.argv[2:]))
-
-</pre>
-</blockquote>
-<p>As you see the whole <tt class="docutils literal">if __name__ == '__main__'</tt> block (10 lines
-counting an empty line) is essentially boilerplate that should not exists.
-Actually I think the Python language should recognize the
-main function and perform trivial arguments parsing behind the
-scenes; unfortunaly this is unlikely to happen. Therefore I have
-been writing boilerplate like this for years, and every time
-I <em>hate</em> having to check for the <tt class="docutils literal">IndexError</tt> by hand, and I hate having
-to write always the same usage message. The purpose of using a
-scripting language is convenience and trivial things should be
-trivial. Unfortunately the standard library modules do not help
-for this use case, which may be trivial, but it is still
-incredibly common. Using <a class="reference external" href="http://docs.python.org/library/getopt.html">getopt</a> and <a class="reference external" href="http://docs.python.org/library/optparse.html">optparse</a> does not help,
-since they are intended to manage options and not positional arguments;
-the <a class="reference external" href="http://argparse.googlecode.com">argparse</a> module helps a bit and it is able to reduce the
-boilerplate from 10 lines to 7 lines:</p>
-<blockquote>
-<pre class="literal-block">
-def main(dsn):
- &quot;Do something on the database&quot;
- print(dsn)
-
-if __name__ == '__main__':
- import argparse
- p = argparse.ArgumentParser()
- p.add_argument('dsn')
- arg = p.parse_args()
- main(arg.dsn)
-
-</pre>
-</blockquote>
-<p>However saving a three lines does not justify introducing the external
-dependency (most people will not switch Python 2.7, currenctly in beta
-for many years).
-Moreover, it just feels too complex to instantiate a class and to
-define a parser by hand for such a trivial task.</p>
-<p>The <a class="reference external" href="http://www.welton.it/articles/scalable_systems">clap</a> module works pretty well when scaling down, and it is able
-to reduce the ten lines of boiler plate to two lines. With the
-<a class="reference external" href="http://www.welton.it/articles/scalable_systems">clap</a> module all you need to write is</p>
-<blockquote>
-<pre class="literal-block">
-def main(dsn):
- &quot;Do something with the database&quot;
- print(dsn)
-
-if __name__ == '__main__':
- import clap; clap.call(main)
-
-</pre>
-</blockquote>
-<p>As an additional bonus she <a class="reference external" href="http://www.welton.it/articles/scalable_systems">clap</a> module automatically recognizes the help flag:</p>
-<blockquote>
-# python example1.py -h</blockquote>
-<p>This is only the tip of the iceberg, as you will see.</p>
-</div>
-<div class="section" id="optional-arguments">
-<h1>Optional arguments</h1>
-<p>I have encountered this use case at work hundreds of times:</p>
-<blockquote>
-<pre class="literal-block">
-def main(dsn):
- &quot;Do something on the database&quot;
- print(dsn)
-
-if __name__ == '__main__':
- import argparse
- p = argparse.ArgumentParser()
- p.add_argument('dsn')
- arg = p.parse_args()
- main(arg.dsn)
-
-</pre>
-</blockquote>
-<p>9 lines of boilerplate are removed.</p>
-<p>Finally, often you want to pass a variable number of arguments to
-your command line script. Here is an example, a script which runs
-on the database a series of .sql scripts:</p>
-<blockquote>
-<pre class="literal-block">
-from datetime import datetime
-
-def main(dsn, *scripts):
- &quot;Run the given scripts on the database&quot;
- for script in scripts:
- print('executing %s' % script)
-
-if __name__ == '__main__':
- if len(sys.argv) &lt; 2:
- sys.exit('usage: python %s dsn script.sql ...' % sys.argv[0])
- main(sys.argv[1:])
-
-</pre>
-</blockquote>
-<p>Using <a class="reference external" href="http://www.welton.it/articles/scalable_systems">clap</a>, you can just replace the <tt class="docutils literal">__main__</tt> block with the usual
-<tt class="docutils literal">import clap; clap.call(main)</tt>. The importanting is that you get a
-much nicer usage message:</p>
-<pre class="literal-block">
-usage: example7.py [-h] dsn [scripts [scripts ...]]
-
-positional arguments:
- dsn
- scripts
-
-optional arguments:
- -h, --help show this help message and exit
-</pre>
-</div>
-<div class="section" id="options-and-flags">
-<h1>Options and flags</h1>
-<p>It is surprising how little command line scripts with options
-I have written over the years (probably less than a hundred),
-compared to the number of scripts with positional arguments
-(I certainly have written more than a thousand of them).
-Still, this use case is quite common and cannot be neglected.
-The standard library modules (all of them) are quite verbose
-when it comes to specifying the options and frankly I have
-never used them directly. Instead, I have always relied on
-an old recipe of mine, the <a class="reference external" href="http://code.activestate.com/recipes/278844-parsing-the-command-line/">optionparse</a> recipe, which provides a
-convenient wrapper over <a class="reference external" href="http://code.activestate.com/recipes/278844-parsing-the-command-line/">optionparse</a> or I have just performed the
-parsing by hand in the simplest cases.</p>
-<p><a class="reference external" href="http://www.welton.it/articles/scalable_systems">clap</a> is inspired to the <a class="reference external" href="http://code.activestate.com/recipes/278844-parsing-the-command-line/">optionparse</a> recipe, in the sense that
-it delivers the programmer from the burden of writing the
-parser for the options by hand, but is less of a hack: instead
-of extracting the parser from the docstring of the module, it
-extracts it from the signature of the <tt class="docutils literal">main</tt> function.</p>
-<p>The idea is to leverage on the <cite>function annotations</cite> concept, a new
-feature of Python 3. An example is worth a thousand words, so here
-it is:</p>
-<blockquote>
-<pre class="literal-block">
-def main(command: (&quot;SQL query&quot;, 'option-c'), dsn):
- if command:
- print('executing %s on %s' % (command, dsn))
-
-if __name__ == '__main__':
- import clap; clap.call(main)
-
-</pre>
-</blockquote>
-<p>As you see, the argument <tt class="docutils literal">command</tt> has been annotated with the
-tuple <tt class="docutils literal">(&quot;SQL query&quot;, <span class="pre">'option-c')</span></tt>: the first string is the
-help string which will appear in the usage message, whereas the
-second string tells <a class="reference external" href="http://www.welton.it/articles/scalable_systems">clap</a> that <tt class="docutils literal">command</tt> is an option and that
-it can be abbreviated with the letter <tt class="docutils literal">c</tt>. Of course, it also
-possible to use the long option format, by prefixing the option
-with <tt class="docutils literal"><span class="pre">--command=</span></tt>. The resulting usage message is the following:</p>
-<pre class="literal-block">
-$ python3 example8.py -h
-usage: example8.py [-h] [-c COMMAND] dsn
-
-positional arguments:
- dsn
-
-optional arguments:
- -h, --help show this help message and exit
- -c COMMAND, --command COMMAND
- SQL query
-</pre>
-<p>Here are two examples of usage:</p>
-<pre class="literal-block">
-$ python3 example8.py -c&quot;select * from table&quot; dsn
-executing select * from table on dsn
-
-$ python3 example8.py --command=&quot;select * from table&quot; dsn
-executing select * from table on dsn
-</pre>
-<p>Notice that if the option is not passed, the variable <tt class="docutils literal">command</tt>
-will get the value <tt class="docutils literal">None</tt>.</p>
-<p>Even positional argument can be annotated, but it makes no sense to
-specify the &quot;option-c&quot; string, so you can skip it and write:</p>
-<pre class="literal-block">
-def main(command: (&quot;SQL query&quot;, 'option-c'), dsn: (&quot;Database dsn&quot;,)):
- ...
-</pre>
-<p>Alternatively, you can write <tt class="docutils literal">(&quot;Database dsn&quot;, None)</tt>. In both cases
-the usage message now will show a nice help string on the right hand side
-of the <tt class="docutils literal">dsn</tt> positional argument. varargs (starred-arguments) can also
-be annotated:</p>
-<pre class="literal-block">
-def main(dsn: (&quot;Database dsn&quot;,), *scripts: (&quot;SQL scripts&quot;,)):
- ...
-</pre>
-<p>is a valid signature for <a class="reference external" href="http://www.welton.it/articles/scalable_systems">clap</a>, which will recognize the help strings
-for both <tt class="docutils literal">dsn</tt> and <tt class="docutils literal">scripts</tt>.</p>
-<p><a class="reference external" href="http://www.welton.it/articles/scalable_systems">clap</a> also recognizes flags, i.e. boolean options which are
-True if they are passed to the command line and False if they are absent.
-Here is an example:</p>
-<pre class="literal-block">
-$ python3 example9.py -v dsn
-connecting to dsn
-</pre>
-<p>For consistency with the way the usage message is printed, I suggest to
-follow the FOP convention: in the <tt class="docutils literal">main</tt> function write first
-the flag arguments, then the option arguments and finally the positional
-arguments. This is a convention and you are not forced to use it, but
-it makes sense to put the position arguments at the end, since they
-may be default arguments and varargs. In this document I will always use
-the FOP convention.</p>
-</div>
-<div class="section" id="clap-is-also-for-people-not-using-python-3">
-<h1>clap is also for people not using Python 3</h1>
-<p>I do not use Python 3. At work we are just starting to think about
-migrating to Python 2.6. I think it will take years before we even
-think to migrate to Python 3. I am pretty much sure most Pythonistas
-are in the same situation. Therefore <a class="reference external" href="http://www.welton.it/articles/scalable_systems">clap</a> provides a way to work
-with function annotations even in Python 2.X (including Python 2.3).
-There is no magic involved; you just need to add the annotations
-by hand. For instance</p>
-<pre class="literal-block">
-def main(dsn: (&quot;Database dsn&quot;,), *scripts: (&quot;SQL scripts&quot;,)):
-</pre>
-<p>becomes:</p>
-<pre class="literal-block">
-def main(dsn, *scripts):
- ...
-main.__annotations__ = dict(
-dsn= (&quot;Database dsn&quot;,),
-scripts=(&quot;SQL scripts&quot;,))
-</pre>
-<p>One should be careful to much the keys of the annotations dictionary
-with the names of the arguments in the annotated function; for lazy
-people with Python 2.4 available the simplest way is to use the
-<tt class="docutils literal">clap.annotations</tt> decorator that performs the check for you.</p>
-<pre class="literal-block">
-&#64;annotations(
-dsn= (&quot;Database dsn&quot;,),
-scripts=(&quot;SQL scripts&quot;,))
-def main(dsn, *scripts):
- ...
-</pre>
-<p>In the rest of this article I will assume that you are using Python 2.X with
-X &gt;= 4 and I will use the <tt class="docutils literal">clap.annotations</tt> decorator.</p>
-</div>
-<div class="section" id="advanced-usage">
-<h1>Advanced usage</h1>
-<p>One of the goals of clap is to have a learning curve of <em>minutes</em>, compared
-to the learning curve of <em>hours</em> of <a class="reference external" href="http://argparse.googlecode.com">argparse</a>. That does not mean
-that I have removed all the advanced features of <a class="reference external" href="http://argparse.googlecode.com">argparse</a>. Actually
-a lot of <a class="reference external" href="http://argparse.googlecode.com">argparse</a> power persists in <a class="reference external" href="http://www.welton.it/articles/scalable_systems">clap</a>: in particular, the
-<tt class="docutils literal">type</tt>, <tt class="docutils literal">choices</tt> and <tt class="docutils literal">metavar</tt> concepts are there.
-Here is an example showing all of them:</p>
-<blockquote>
-<pre class="literal-block">
-import clap
-
-&#64;clap.annotations(
-operator=(&quot;The name of an operator&quot;, None, str, ['add', 'mul']),
-numbers=(&quot;A number&quot;, None, float, None, &quot;n&quot;))
-def main(operator, *numbers):
- op = getattr(float, '__%s__' % operator)
- result = dict(add=0.0, mul=1.0)[operator]
- for n in numbers:
- result = op(result, n)
- print(result)
-
-if __name__ == '__main__':
- clap.call(main)
-
-</pre>
-</blockquote>
-<p>Let me begin by discussing the <tt class="docutils literal">type</tt> feature: given any callable
-taking a string in input a returning any Python object, it is possible
-to automagically convert the parsed arguments with the callable, simply
-by listing it in the annotation</p>
-</div>
-</div>
-</body>
-</html>
diff --git a/clap/article/article.pdf b/clap/article/article.pdf
deleted file mode 100644
index cb3f3dc..0000000
--- a/clap/article/article.pdf
+++ /dev/null
@@ -1,2418 +0,0 @@
-%PDF-1.3
-%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com
-% 'BasicFonts': class PDFDictionary
-1 0 obj
-% The standard fonts dictionary
-<< /F1 2 0 R
- /F2 3 0 R
- /F3 14 0 R
- /F4 16 0 R
- /F5 17 0 R >>
-endobj
-% 'F1': class PDFType1Font
-2 0 obj
-% Font Helvetica
-<< /BaseFont /Helvetica
- /Encoding /WinAnsiEncoding
- /Name /F1
- /Subtype /Type1
- /Type /Font >>
-endobj
-% 'F2': class PDFType1Font
-3 0 obj
-% Font Helvetica-Bold
-<< /BaseFont /Helvetica-Bold
- /Encoding /WinAnsiEncoding
- /Name /F2
- /Subtype /Type1
- /Type /Font >>
-endobj
-% 'Annot.NUMBER1': class PDFDictionary
-4 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://docs.python.org/library/getopt.html) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 361.1228
- 686.5936
- 392.9767
- 698.5936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER2': class PDFDictionary
-5 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://docs.python.org/library/optparse.html) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 493.6727
- 686.5936
- 531.3087
- 698.5936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER3': class PDFDictionary
-6 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://argparse.googlecode.com) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 164.0504
- 674.5936
- 206.7572
- 686.5936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER4': class PDFDictionary
-7 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://argparse.googlecode.com) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 493.1227
- 674.5936
- 532.1158
- 686.5936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER5': class PDFDictionary
-8 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://www.welton.it/articles/scalable_systems) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 95.71512
- 632.5936
- 114.0551
- 644.5936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER6': class PDFDictionary
-9 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://www.welton.it/articles/scalable_systems) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 120.9573
- 632.5936
- 143.4195
- 644.5936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER7': class PDFDictionary
-10 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://www.welton.it/articles/scalable_systems) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 227.1684
- 632.5936
- 320.7606
- 644.5936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER8': class PDFDictionary
-11 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://www.welton.it/articles/scalable_systems) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 337.6822
- 620.5936
- 359.0965
- 632.5936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER9': class PDFDictionary
-12 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://argparse.googlecode.com) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 490.3427
- 620.5936
- 529.8027
- 632.5936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER10': class PDFDictionary
-13 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://www.welton.it/articles/scalable_systems) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 346.3284
- 608.5936
- 367.4652
- 620.5936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'F3': class PDFType1Font
-14 0 obj
-% Font Courier
-<< /BaseFont /Courier
- /Encoding /WinAnsiEncoding
- /Name /F3
- /Subtype /Type1
- /Type /Font >>
-endobj
-% 'Annot.NUMBER11': class PDFDictionary
-15 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://www.welton.it/articles/scalable_systems) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 471.0489
- 407.5936
- 529.8027
- 419.5936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'F4': class PDFType1Font
-16 0 obj
-% Font Helvetica-Oblique
-<< /BaseFont /Helvetica-Oblique
- /Encoding /WinAnsiEncoding
- /Name /F4
- /Subtype /Type1
- /Type /Font >>
-endobj
-% 'F5': class PDFType1Font
-17 0 obj
-% Font Times-Roman
-<< /BaseFont /Times-Roman
- /Encoding /WinAnsiEncoding
- /Name /F5
- /Subtype /Type1
- /Type /Font >>
-endobj
-% 'Page1': class PDFPage
-18 0 obj
-% Page dictionary
-<< /Annots [ 4 0 R
- 5 0 R
- 6 0 R
- 7 0 R
- 8 0 R
- 9 0 R
- 10 0 R
- 11 0 R
- 12 0 R
- 13 0 R
- 15 0 R ]
- /Contents 69 0 R
- /MediaBox [ 0
- 0
- 595.2756
- 841.8898 ]
- /Parent 68 0 R
- /Resources << /Font 1 0 R
- /ProcSet [ /PDF
- /Text
- /ImageB
- /ImageC
- /ImageI ] >>
- /Rotate 0
- /Trans << >>
- /Type /Page >>
-endobj
-% 'Annot.NUMBER12': class PDFDictionary
-19 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://docs.python.org/library/getopt.html) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 504.7827
- 756.5936
- 532.1006
- 768.5936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER13': class PDFDictionary
-20 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://docs.python.org/library/optparse.html) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 82.40665
- 744.5936
- 124.3504
- 756.5936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER14': class PDFDictionary
-21 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://argparse.googlecode.com) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 62.69291
- 732.5936
- 104.9329
- 744.5936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER15': class PDFDictionary
-22 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://www.welton.it/articles/scalable_systems) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 83.82606
- 533.3936
- 106.0692
- 545.3936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER16': class PDFDictionary
-23 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://www.welton.it/articles/scalable_systems) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 243.8829
- 521.3936
- 265.0029
- 533.3936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER17': class PDFDictionary
-24 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://www.welton.it/articles/scalable_systems) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 83.6329
- 412.1936
- 105.6829
- 424.1936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER18': class PDFDictionary
-25 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://argparse.googlecode.com) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 421.9727
- 412.1936
- 465.1427
- 424.1936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER19': class PDFDictionary
-26 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://www.welton.it/articles/scalable_systems) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 211.6529
- 262.9936
- 232.7729
- 274.9936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Page2': class PDFPage
-27 0 obj
-% Page dictionary
-<< /Annots [ 19 0 R
- 20 0 R
- 21 0 R
- 22 0 R
- 23 0 R
- 24 0 R
- 25 0 R
- 26 0 R ]
- /Contents 70 0 R
- /MediaBox [ 0
- 0
- 595.2756
- 841.8898 ]
- /Parent 68 0 R
- /Resources << /Font 1 0 R
- /ProcSet [ /PDF
- /Text
- /ImageB
- /ImageC
- /ImageI ] >>
- /Rotate 0
- /Trans << >>
- /Type /Page >>
-endobj
-% 'Annot.NUMBER20': class PDFDictionary
-28 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://www.welton.it/articles/scalable_systems) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 85.47291
- 665.3936
- 106.5929
- 677.3936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER21': class PDFDictionary
-29 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://www.welton.it/articles/scalable_systems) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 62.69291
- 450.9936
- 84.20915
- 462.9936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER22': class PDFDictionary
-30 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://www.welton.it/articles/scalable_systems) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 97.95597
- 257.7936
- 116.296
- 269.7936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER23': class PDFDictionary
-31 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://www.welton.it/articles/scalable_systems) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 446.6187
- 96.59362
- 464.9587
- 108.5936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Page3': class PDFPage
-32 0 obj
-% Page dictionary
-<< /Annots [ 28 0 R
- 29 0 R
- 30 0 R
- 31 0 R ]
- /Contents 71 0 R
- /MediaBox [ 0
- 0
- 595.2756
- 841.8898 ]
- /Parent 68 0 R
- /Resources << /Font 1 0 R
- /ProcSet [ /PDF
- /Text
- /ImageB
- /ImageC
- /ImageI ] >>
- /Rotate 0
- /Trans << >>
- /Type /Page >>
-endobj
-% 'Annot.NUMBER24': class PDFDictionary
-33 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://code.activestate.com/recipes/278844-parsing-the-command-line/) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 446.8103
- 681.5936
- 502.5727
- 693.5936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER25': class PDFDictionary
-34 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://code.activestate.com/recipes/278844-parsing-the-command-line/) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 260.18
- 669.5936
- 312.43
- 681.5936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER26': class PDFDictionary
-35 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://www.welton.it/articles/scalable_systems) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 62.69291
- 639.5936
- 84.28901
- 651.5936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER27': class PDFDictionary
-36 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://code.activestate.com/recipes/278844-parsing-the-command-line/) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 161.7834
- 639.5936
- 217.2895
- 651.5936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER28': class PDFDictionary
-37 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://www.welton.it/articles/scalable_systems) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 133.1479
- 440.3936
- 154.4129
- 452.3936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Page4': class PDFPage
-38 0 obj
-% Page dictionary
-<< /Annots [ 33 0 R
- 34 0 R
- 35 0 R
- 36 0 R
- 37 0 R ]
- /Contents 72 0 R
- /MediaBox [ 0
- 0
- 595.2756
- 841.8898 ]
- /Parent 68 0 R
- /Resources << /Font 1 0 R
- /ProcSet [ /PDF
- /Text
- /ImageB
- /ImageC
- /ImageI ] >>
- /Rotate 0
- /Trans << >>
- /Type /Page >>
-endobj
-% 'Annot.NUMBER29': class PDFDictionary
-39 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://www.welton.it/articles/scalable_systems) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 185.8554
- 711.3936
- 207.616
- 723.3936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER30': class PDFDictionary
-40 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://www.welton.it/articles/scalable_systems) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 162.7329
- 556.9936
- 181.0729
- 568.9936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER31': class PDFDictionary
-41 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://www.welton.it/articles/scalable_systems) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 62.69291
- 479.7936
- 84.57878
- 491.7936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER32': class PDFDictionary
-42 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://www.welton.it/articles/scalable_systems) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 185.1229
- 150.3936
- 208.3329
- 162.3936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Page5': class PDFPage
-43 0 obj
-% Page dictionary
-<< /Annots [ 39 0 R
- 40 0 R
- 41 0 R
- 42 0 R ]
- /Contents 73 0 R
- /MediaBox [ 0
- 0
- 595.2756
- 841.8898 ]
- /Parent 68 0 R
- /Resources << /Font 1 0 R
- /ProcSet [ /PDF
- /Text
- /ImageB
- /ImageC
- /ImageI ] >>
- /Rotate 0
- /Trans << >>
- /Type /Page >>
-endobj
-% 'Annot.NUMBER33': class PDFDictionary
-44 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://argparse.googlecode.com) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 62.69291
- 455.1936
- 102.1529
- 467.1936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER34': class PDFDictionary
-45 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://argparse.googlecode.com) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 418.9683
- 455.1936
- 458.4283
- 467.1936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER35': class PDFDictionary
-46 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://argparse.googlecode.com) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 62.69291
- 443.1936
- 106.4622
- 455.1936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER36': class PDFDictionary
-47 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://www.welton.it/articles/scalable_systems) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 188.85
- 443.1936
- 207.19
- 455.1936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER37': class PDFDictionary
-48 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://argparse.googlecode.com) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 407.8229
- 263.1936
- 450.0629
- 275.1936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Page6': class PDFPage
-49 0 obj
-% Page dictionary
-<< /Annots [ 44 0 R
- 45 0 R
- 46 0 R
- 47 0 R
- 48 0 R ]
- /Contents 74 0 R
- /MediaBox [ 0
- 0
- 595.2756
- 841.8898 ]
- /Parent 68 0 R
- /Resources << /Font 1 0 R
- /ProcSet [ /PDF
- /Text
- /ImageB
- /ImageC
- /ImageI ] >>
- /Rotate 0
- /Trans << >>
- /Type /Page >>
-endobj
-% 'Annot.NUMBER38': class PDFDictionary
-50 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://www.welton.it/articles/scalable_systems) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 62.69291
- 475.0549
- 84.7414
- 487.0549 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER39': class PDFDictionary
-51 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://argparse.googlecode.com) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 136.4369
- 475.0549
- 179.6054
- 487.0549 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER40': class PDFDictionary
-52 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://argparse.googlecode.com/svn/tags/r11/doc/ArgumentParser.html) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 62.69291
- 463.0549
- 138.3111
- 475.0549 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER41': class PDFDictionary
-53 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://www.welton.it/articles/scalable_systems) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 127.9872
- 325.8549
- 149.3819
- 337.8549 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER42': class PDFDictionary
-54 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://argparse.googlecode.com) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 480.5388
- 313.8549
- 524.2427
- 325.8549 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER43': class PDFDictionary
-55 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://argparse.googlecode.com/svn/tags/r11/doc/ArgumentParser.html) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 225.5228
- 283.8549
- 301.2571
- 295.8549 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER44': class PDFDictionary
-56 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://www.welton.it/articles/scalable_systems) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 62.69291
- 116.6549
- 84.35423
- 128.6549 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Page7': class PDFPage
-57 0 obj
-% Page dictionary
-<< /Annots [ 50 0 R
- 51 0 R
- 52 0 R
- 53 0 R
- 54 0 R
- 55 0 R
- 56 0 R ]
- /Contents 75 0 R
- /MediaBox [ 0
- 0
- 595.2756
- 841.8898 ]
- /Parent 68 0 R
- /Resources << /Font 1 0 R
- /ProcSet [ /PDF
- /Text
- /ImageB
- /ImageC
- /ImageI ] >>
- /Rotate 0
- /Trans << >>
- /Type /Page >>
-endobj
-% 'Page8': class PDFPage
-58 0 obj
-% Page dictionary
-<< /Contents 76 0 R
- /MediaBox [ 0
- 0
- 595.2756
- 841.8898 ]
- /Parent 68 0 R
- /Resources << /Font 1 0 R
- /ProcSet [ /PDF
- /Text
- /ImageB
- /ImageC
- /ImageI ] >>
- /Rotate 0
- /Trans << >>
- /Type /Page >>
-endobj
-% 'R59': class PDFCatalog
-59 0 obj
-% Document Root
-<< /Outlines 61 0 R
- /PageLabels 77 0 R
- /PageMode /UseNone
- /Pages 68 0 R
- /Type /Catalog >>
-endobj
-% 'R60': class PDFInfo
-60 0 obj
-<< /Author ()
- /CreationDate (D:20100531105058-01'00')
- /Keywords ()
- /Producer (ReportLab http://www.reportlab.com)
- /Subject (\(unspecified\))
- /Title (The Easiest Command Line Arguments Parser in the World) >>
-endobj
-% 'R61': class PDFOutlines
-61 0 obj
-<< /Count 6
- /First 62 0 R
- /Last 67 0 R
- /Type /Outlines >>
-endobj
-% 'Outline.0': class OutlineEntryObject
-62 0 obj
-<< /Dest [ 18 0 R
- /XYZ
- 62.69291
- 443.0236
- 0 ]
- /Next 63 0 R
- /Parent 61 0 R
- /Title (The importance of scaling down) >>
-endobj
-% 'Outline.1': class OutlineEntryObject
-63 0 obj
-<< /Dest [ 27 0 R
- /XYZ
- 62.69291
- 247.4236
- 0 ]
- /Next 64 0 R
- /Parent 61 0 R
- /Prev 62 0 R
- /Title (Positional default arguments) >>
-endobj
-% 'Outline.2': class OutlineEntryObject
-64 0 obj
-<< /Dest [ 38 0 R
- /XYZ
- 62.69291
- 765.0236
- 0 ]
- /Next 65 0 R
- /Parent 61 0 R
- /Prev 63 0 R
- /Title (Options and flags) >>
-endobj
-% 'Outline.3': class OutlineEntryObject
-65 0 obj
-<< /Dest [ 43 0 R
- /XYZ
- 62.69291
- 209.8236
- 0 ]
- /Next 66 0 R
- /Parent 61 0 R
- /Prev 64 0 R
- /Title (clap for people not using Python 3) >>
-endobj
-% 'Outline.4': class OutlineEntryObject
-66 0 obj
-<< /Dest [ 49 0 R
- /XYZ
- 62.69291
- 502.6236
- 0 ]
- /Next 67 0 R
- /Parent 61 0 R
- /Prev 65 0 R
- /Title (Advanced usage) >>
-endobj
-% 'Outline.5': class OutlineEntryObject
-67 0 obj
-<< /Dest [ 57 0 R
- /XYZ
- 62.69291
- 510.4849
- 0 ]
- /Parent 61 0 R
- /Prev 66 0 R
- /Title (A few notes on the underlying implementation) >>
-endobj
-% 'R68': class PDFPages
-68 0 obj
-% page tree
-<< /Count 8
- /Kids [ 18 0 R
- 27 0 R
- 32 0 R
- 38 0 R
- 43 0 R
- 49 0 R
- 57 0 R
- 58 0 R ]
- /Type /Pages >>
-endobj
-% 'R69': class PDFStream
-69 0 obj
-% page stream
-<< /Length 6154 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
-q
-1 0 0 1 62.69291 717.0236 cm
-q
-BT 1 0 0 1 0 33.64 Tm 3.214882 0 Td 24 TL /F2 20 Tf 0 0 0 rg (The Easiest Command Line Arguments Parser in) Tj T* 185.62 0 Td (the World) Tj T* -188.8349 0 Td ET
-Q
-Q
-q
-1 0 0 1 62.69291 647.0236 cm
-q
-BT 1 0 0 1 0 52.82 Tm .05061 Tw 12 TL /F1 10 Tf 0 0 0 rg (There is no want of command line arguments parsers in Python world. The standard library alone contains) Tj T* 0 Tw 1.273984 Tw (three different modules for the parsing of command line options: ) Tj 0 0 .501961 rg (getopt ) Tj 0 0 0 rg (\(from the stone age\), ) Tj 0 0 .501961 rg (optparse) Tj T* 0 Tw .46686 Tw 0 0 0 rg (\(from Python 2.3\) and ) Tj 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (\(from Python 2.7\). All of them are quite powerful and especially ) Tj 0 0 .501961 rg (argparse) Tj T* 0 Tw .847485 Tw 0 0 0 rg (is an industrial strength solution; unfortunately, all of them have a non-zero learning curve and a certain) Tj T* 0 Tw (verbosity.) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 557.0236 cm
-q
-BT 1 0 0 1 0 76.82 Tm 1.342209 Tw 12 TL /F1 10 Tf 0 0 0 rg (Enters ) Tj 0 0 .501961 rg (clap) Tj 0 0 0 rg (. ) Tj 0 0 .501961 rg (clap ) Tj 0 0 0 rg (is designed to be ) Tj 0 0 .501961 rg (downwardly scalable) Tj 0 0 0 rg (, i.e. to be trivially simple to use for trivial use) Tj T* 0 Tw .29436 Tw (cases, and to have a next-to-zero learning curve. Technically ) Tj 0 0 .501961 rg (clap ) Tj 0 0 0 rg (is just a simple wrapper over ) Tj 0 0 .501961 rg (argparse) Tj 0 0 0 rg (,) Tj T* 0 Tw .01686 Tw (hiding most of the complexity while retaining most of the power. ) Tj 0 0 .501961 rg (clap ) Tj 0 0 0 rg (is surprisingly scalable upwards even) Tj T* 0 Tw .569398 Tw (for non-trivial use cases, but it is not intended to be an industrial strength command line parsing module.) Tj T* 0 Tw .07104 Tw (Its capabilities are limited by design. If you need more power, by all means use the parsing modules in the) Tj T* 0 Tw .51237 Tw (standard library. Still, I have been using Python for 8 years and never once I had to use the full power of) Tj T* 0 Tw (the standard library modules.) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 455.0236 cm
-q
-BT 1 0 0 1 0 88.82 Tm .536457 Tw 12 TL /F1 10 Tf 0 0 0 rg (Actually I am pretty much convinced that features provided by ) Tj /F3 10 Tf (clap ) Tj /F1 10 Tf (are more than enough for 99.9% of) Tj T* 0 Tw .60811 Tw (the typical use cases of a scripter working in a Unix-like environment. I am targetting here programmers,) Tj T* 0 Tw .337126 Tw (sys-admins, scientists and in general people writing throw-away scripts for themselves, choosing to use a) Tj T* 0 Tw .242339 Tw (command line interface because it is the quick and simple. Such users are not interested in features, they) Tj T* 0 Tw 2.177882 Tw (just want to be able to write a simple command line tool from a simple specification, not to build a) Tj T* 0 Tw .014985 Tw (command line parser by hand. Unfortunately, the current modules in the standard library forces them to go) Tj T* 0 Tw 4.664269 Tw (the hard way. They are designed to implement power user tools for programmers or system) Tj T* 0 Tw (administrators, and they have a non-trivial learning curve.) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 422.0236 cm
-q
-BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (The importance of scaling down) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 320.0236 cm
-q
-BT 1 0 0 1 0 88.82 Tm .953735 Tw 12 TL /F1 10 Tf 0 0 0 rg (An ex-coworker of mine, David Welton, once wrote a nice article about the importance of ) Tj 0 0 .501961 rg (scaling down) Tj 0 0 0 rg (:) Tj T* 0 Tw 1.026457 Tw (most people are concerned with the possibility of scaling up, but we should also be concerned with the) Tj T* 0 Tw .754987 Tw (issue of scaling down: in other worlds, simple things should be kept simple. To be concrete, let me start) Tj T* 0 Tw .567765 Tw (with the simplest possible thing: a script that takes a single argument and does something to it. It cannot) Tj T* 0 Tw 1.314651 Tw (get more trivial than that \(discarding the possibility of a script without command line arguments, where) Tj T* 0 Tw .188935 Tw (there is nothing to parse\), nevertheless it is a use case ) Tj /F4 10 Tf (extremely common) Tj /F1 10 Tf (: I need to write scripts like that) Tj T* 0 Tw .539513 Tw (nearly every day, I wrote hundreds of them in the last few years and I have never been happy. Here is a) Tj T* 0 Tw (typical example of code I have been writing by hand for years:) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 314.0236 cm
-Q
-q
-1 0 0 1 62.69291 144.8236 cm
-0 0 0 rg
-BT /F5 10 Tf 12 TL ET
-BT 1 0 0 1 0 2 Tm T* ET
-q
-1 0 0 1 20 0 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 448.6898 168 re B*
-Q
-q
-0 0 0 rg
-BT 1 0 0 1 0 149.71 Tm /F3 10 Tf 12 TL (def main\(dsn\):) Tj T* ( "Do something with the database") Tj T* ( print\(dsn\)) Tj T* T* (if __name__ == '__main__':) Tj T* ( import sys) Tj T* ( n = len\(sys.argv[1:]\)) Tj T* ( if n == 0:) Tj T* ( sys.exit\('usage: python %s dsn' % sys.argv[0]\)) Tj T* ( elif n == 1:) Tj T* ( main\(sys.argv[1]\)) Tj T* ( else:) Tj T* ( sys.exit\('Unrecognized arguments: %s' % ' '.join\(sys.argv[2:]\)\)) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-Q
-Q
-q
-1 0 0 1 62.69291 144.8236 cm
-Q
-q
-1 0 0 1 62.69291 78.82362 cm
-q
-BT 1 0 0 1 0 52.82 Tm .880651 Tw 12 TL /F1 10 Tf 0 0 0 rg (As you see the whole ) Tj /F3 10 Tf (if __name__ == '__main__' ) Tj /F1 10 Tf (block \(nine lines\) is essentially boilerplate that ) Tj T* 0 Tw 1.125318 Tw (should not exists. Actually I think the Python language should recognize the main function and perform ) Tj T* 0 Tw 1.385984 Tw (trivial arguments parsing behind the scenes; unfortunaly this is unlikely to happen. I have been writing ) Tj T* 0 Tw 1.767356 Tw (boilerplate like this in hundreds of scripts for years, and every time I ) Tj /F4 10 Tf (hate ) Tj /F1 10 Tf (it. The purpose of using a ) Tj T* 0 Tw 1.47229 Tw (scripting language is convenience and trivial things should be trivial. Unfortunately the standard library) Tj T* 0 Tw ET
-Q
-Q
-
-endstream
-
-endobj
-% 'R70': class PDFStream
-70 0 obj
-% page stream
-<< /Length 4633 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
-q
-1 0 0 1 62.69291 729.0236 cm
-q
-BT 1 0 0 1 0 28.82 Tm .482093 Tw 12 TL /F1 10 Tf 0 0 0 rg (modules do not help for this use case, which may be trivial, but it is still incredibly common. Using ) Tj 0 0 .501961 rg (getopt) Tj T* 0 Tw .253735 Tw 0 0 0 rg (and ) Tj 0 0 .501961 rg (optparse ) Tj 0 0 0 rg (does not help, since they are intended to manage options and not positional arguments; the) Tj T* 0 Tw 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (module helps a bit and it is able to reduce the boilerplate from nine lines to six lines:) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 723.0236 cm
-Q
-q
-1 0 0 1 62.69291 589.8236 cm
-0 0 0 rg
-BT /F5 10 Tf 12 TL ET
-BT 1 0 0 1 0 2 Tm T* ET
-q
-1 0 0 1 20 0 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 448.6898 132 re B*
-Q
-q
-0 0 0 rg
-BT 1 0 0 1 0 113.71 Tm /F3 10 Tf 12 TL (def main\(dsn\):) Tj T* ( "Do something on the database") Tj T* ( print\(dsn\)) Tj T* T* (if __name__ == '__main__':) Tj T* ( import argparse) Tj T* ( p = argparse.ArgumentParser\(\)) Tj T* ( p.add_argument\('dsn'\)) Tj T* ( arg = p.parse_args\(\)) Tj T* ( main\(arg.dsn\)) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-Q
-Q
-q
-1 0 0 1 62.69291 589.8236 cm
-Q
-q
-1 0 0 1 62.69291 547.8236 cm
-q
-0 0 0 rg
-BT 1 0 0 1 0 28.82 Tm /F1 10 Tf 12 TL 1.644269 Tw (However saving three lines does not justify introducing the external dependency: most people will not) Tj T* 0 Tw .276303 Tw (switch Python 2.7, which at the time of this writing is just about to be released, for many years. Moreover,) Tj T* 0 Tw (it just feels too complex to instantiate a class and to define a parser by hand for such a trivial task.) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 517.8236 cm
-q
-BT 1 0 0 1 0 16.82 Tm 1.123145 Tw 12 TL /F1 10 Tf 0 0 0 rg (The ) Tj 0 0 .501961 rg (clap ) Tj 0 0 0 rg (module is designed to manage well such use cases, and it is able to reduce the original nine) Tj T* 0 Tw (lines of boiler plate to two lines. With the ) Tj 0 0 .501961 rg (clap ) Tj 0 0 0 rg (module all you need to write is) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 511.8236 cm
-Q
-q
-1 0 0 1 62.69291 426.6236 cm
-0 0 0 rg
-BT /F5 10 Tf 12 TL ET
-BT 1 0 0 1 0 2 Tm T* ET
-q
-1 0 0 1 20 0 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 448.6898 84 re B*
-Q
-q
-0 0 0 rg
-BT 1 0 0 1 0 65.71 Tm /F3 10 Tf 12 TL (def main\(dsn\):) Tj T* ( "Do something with the database") Tj T* ( print\(dsn\)) Tj T* ( ) Tj T* (if __name__ == '__main__':) Tj T* ( import clap; clap.call\(main\)) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-Q
-Q
-q
-1 0 0 1 62.69291 426.6236 cm
-Q
-q
-1 0 0 1 62.69291 396.6236 cm
-q
-BT 1 0 0 1 0 16.82 Tm .929986 Tw 12 TL /F1 10 Tf 0 0 0 rg (The ) Tj 0 0 .501961 rg (clap ) Tj 0 0 0 rg (module provides for free \(actually the work is done by the underlying ) Tj 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (module\) a nice) Tj T* 0 Tw (usage message:) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 279.4236 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 468.6898 108 re B*
-Q
-q
-0 0 0 rg
-BT 1 0 0 1 0 89.71 Tm /F3 10 Tf 12 TL ($ python example3.py -h) Tj T* (usage: example3.py [-h] dsn) Tj T* T* (positional arguments:) Tj T* ( dsn) Tj T* T* (optional arguments:) Tj T* ( -h, --help show this help message and exit) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-1 0 0 1 62.69291 259.4236 cm
-q
-BT 1 0 0 1 0 4.82 Tm 12 TL /F1 10 Tf 0 0 0 rg (This is only the tip of the iceberg: ) Tj 0 0 .501961 rg (clap ) Tj 0 0 0 rg (is able to do much more than that.) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 226.4236 cm
-q
-BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Positional default arguments) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 208.4236 cm
-q
-0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (I have encountered this use case at work hundreds of times:) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 202.4236 cm
-Q
-q
-1 0 0 1 62.69291 76.86614 cm
-0 0 0 rg
-BT /F5 10 Tf 12 TL ET
-BT 1 0 0 1 0 2 Tm T* ET
-q
-1 0 0 1 20 0 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 442.6898 108 re B*
-Q
-q
-BT 1 0 0 1 0 89.71 Tm 12 TL /F3 10 Tf 0 0 0 rg (from datetime import datetime) Tj T* T* (def main\(dsn, table='product', today=datetime.today\(\)\):) Tj T* ( "Do something on the database") Tj T* ( print\(dsn, table, today\)) Tj T* T* (if __name__ == '__main__':) Tj T* ( import sys) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-Q
-Q
-
-endstream
-
-endobj
-% 'R71': class PDFStream
-71 0 obj
-% page stream
-<< /Length 4390 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
-q
-1 0 0 1 62.69291 679.8236 cm
-0 0 0 rg
-BT /F5 10 Tf 12 TL ET
-BT 1 0 0 1 0 2 Tm T* ET
-q
-1 0 0 1 20 0 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 442.6898 84 re B*
-Q
-q
-BT 1 0 0 1 0 65.71 Tm 12 TL /F3 10 Tf 0 0 0 rg ( args = sys.argv[1:]) Tj T* ( if not args:) Tj T* ( sys.exit\('usage: python %s dsn' % sys.argv[0]\)) Tj T* ( elif len\(args\) ) Tj (>) Tj ( 2:) Tj T* ( sys.exit\('Unrecognized arguments: %s' % ' '.join\(argv[2:]\)\)) Tj T* ( main\(*args\)) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-Q
-Q
-q
-1 0 0 1 62.69291 679.8236 cm
-Q
-q
-1 0 0 1 62.69291 661.8236 cm
-q
-BT 1 0 0 1 0 4.82 Tm 12 TL /F1 10 Tf 0 0 0 rg (With ) Tj 0 0 .501961 rg (clap ) Tj 0 0 0 rg (the entire ) Tj /F3 10 Tf (__main__ ) Tj /F1 10 Tf (block reduces to the usual two lines:) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 616.6236 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 468.6898 36 re B*
-Q
-q
-0 0 0 rg
-BT 1 0 0 1 0 17.71 Tm /F3 10 Tf 12 TL (if __name__ == '__main__':) Tj T* ( import clap; clap.call\(main\)) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-1 0 0 1 62.69291 596.6236 cm
-q
-0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (In other words, six lines of boilerplate have been removed, and I have the usage message for free:) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 467.4236 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 468.6898 120 re B*
-Q
-q
-0 0 0 rg
-BT 1 0 0 1 0 101.71 Tm /F3 10 Tf 12 TL (usage: example4_.py [-h] dsn [table] [today]) Tj T* T* (positional arguments:) Tj T* ( dsn) Tj T* ( table) Tj T* ( today) Tj T* T* (optional arguments:) Tj T* ( -h, --help show this help message and exit) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-1 0 0 1 62.69291 435.4236 cm
-q
-BT 1 0 0 1 0 16.82 Tm .396235 Tw 12 TL /F1 10 Tf 0 0 .501961 rg (clap ) Tj 0 0 0 rg (manages transparently even the case when you want to pass a variable number of arguments. Here) Tj T* 0 Tw (is an example, a script running on a database a series of ) Tj /F3 10 Tf (.sql ) Tj /F1 10 Tf (scripts:) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 429.4236 cm
-Q
-q
-1 0 0 1 62.69291 272.2236 cm
-0 0 0 rg
-BT /F5 10 Tf 12 TL ET
-BT 1 0 0 1 0 2 Tm T* ET
-q
-1 0 0 1 20 0 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 448.6898 156 re B*
-Q
-q
-BT 1 0 0 1 0 137.71 Tm 12 TL /F3 10 Tf 0 0 0 rg (from datetime import datetime) Tj T* T* (def main\(dsn, *scripts\):) Tj T* ( "Run the given scripts on the database") Tj T* ( for script in scripts:) Tj T* ( print\('executing %s' % script\)) Tj T* T* (if __name__ == '__main__':) Tj T* ( import sys) Tj T* ( if len\(sys.argv\) ) Tj (<) Tj ( 2:) Tj T* ( sys.exit\('usage: python %s dsn script.sql ...' % sys.argv[0]\)) Tj T* ( main\(sys.argv[1:]\)) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-Q
-Q
-q
-1 0 0 1 62.69291 272.2236 cm
-Q
-q
-1 0 0 1 62.69291 242.2236 cm
-q
-BT 1 0 0 1 0 16.82 Tm 6.923059 Tw 12 TL /F1 10 Tf 0 0 0 rg (Using ) Tj 0 0 .501961 rg (clap) Tj 0 0 0 rg (, you can just replace the ) Tj /F3 10 Tf (__main__ ) Tj /F1 10 Tf (block with the usual ) Tj /F3 10 Tf (import clap;) Tj T* 0 Tw (clap.call\(main\) ) Tj /F1 10 Tf (and you get the following usage message:) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 125.0236 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 468.6898 108 re B*
-Q
-q
-0 0 0 rg
-BT 1 0 0 1 0 89.71 Tm /F3 10 Tf 12 TL (usage: example7.py [-h] dsn [scripts [scripts ...]]) Tj T* T* (positional arguments:) Tj T* ( dsn) Tj T* ( scripts) Tj T* T* (optional arguments:) Tj T* ( -h, --help show this help message and exit) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-1 0 0 1 62.69291 81.02362 cm
-q
-BT 1 0 0 1 0 28.82 Tm .92881 Tw 12 TL /F1 10 Tf 0 0 0 rg (The examples here should have made clear that ) Tj /F4 10 Tf (clap is able to figure out the command line arguments) Tj T* 0 Tw .928488 Tw (parser to use from the signature of the main function) Tj /F1 10 Tf (. This is the whole idea behind ) Tj 0 0 .501961 rg (clap) Tj 0 0 0 rg (: if my intent is) Tj T* 0 Tw (clear, let's the machine takes care of the details.) Tj T* ET
-Q
-Q
-
-endstream
-
-endobj
-% 'R72': class PDFStream
-72 0 obj
-% page stream
-<< /Length 5415 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
-q
-1 0 0 1 62.69291 744.0236 cm
-q
-BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Options and flags) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 654.0236 cm
-q
-BT 1 0 0 1 0 76.82 Tm .046098 Tw 12 TL /F1 10 Tf 0 0 0 rg (It is surprising how few command line scripts with options I have written over the years \(probably less than) Tj T* 0 Tw 1.165984 Tw (a hundred\), compared to the number of scripts with positional arguments \(I certainly have written more) Tj T* 0 Tw 1.221163 Tw (than a thousand of them\). Still, this use case is quite common and cannot be neglected. The standard) Tj T* 0 Tw .446098 Tw (library modules \(all of them\) are quite verbose when it comes to specifying the options and frankly I have) Tj T* 0 Tw .732339 Tw (never used them directly. Instead, I have always relied on an old recipe of mine, the ) Tj 0 0 .501961 rg (optionparse ) Tj 0 0 0 rg (recipe,) Tj T* 0 Tw 1.32784 Tw (which provides a convenient wrapper over ) Tj 0 0 .501961 rg (optionparse) Tj 0 0 0 rg (. Alternatively, in the simplest cases, I have just) Tj T* 0 Tw (performed the parsing by hand, instead of manually building a suitable OptionParser.) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 612.0236 cm
-q
-BT 1 0 0 1 0 28.82 Tm .476098 Tw 12 TL /F1 10 Tf 0 0 .501961 rg (clap ) Tj 0 0 0 rg (is inspired to the ) Tj 0 0 .501961 rg (optionparse ) Tj 0 0 0 rg (recipe, in the sense that it delivers the programmer from the burden of) Tj T* 0 Tw .011488 Tw (writing the parser, but is less of a hack: instead of extracting the parser from the docstring of the module, it) Tj T* 0 Tw (extracts it from the signature of the ) Tj /F3 10 Tf (main ) Tj /F1 10 Tf (function.) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 582.0236 cm
-q
-BT 1 0 0 1 0 16.82 Tm .319987 Tw 12 TL /F1 10 Tf 0 0 0 rg (The idea comes from the ) Tj /F4 10 Tf (function annotations ) Tj /F1 10 Tf (concept, a new feature of Python 3. An example is worth a) Tj T* 0 Tw (thousand words, so here it is:) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 576.0236 cm
-Q
-q
-1 0 0 1 62.69291 478.8236 cm
-0 0 0 rg
-BT /F5 10 Tf 12 TL ET
-BT 1 0 0 1 0 2 Tm T* ET
-q
-1 0 0 1 20 0 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 448.6898 96 re B*
-Q
-q
-0 0 0 rg
-BT 1 0 0 1 0 77.71 Tm /F3 10 Tf 12 TL (def main\(command: \("SQL query", 'option', 'c'\), dsn\):) Tj T* ( if command:) Tj T* ( print\('executing %s on %s' % \(command, dsn\)\)) Tj T* ( # ...) Tj T* T* (if __name__ == '__main__':) Tj T* ( import clap; clap.call\(main\)) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-Q
-Q
-q
-1 0 0 1 62.69291 478.8236 cm
-Q
-q
-1 0 0 1 62.69291 412.8236 cm
-q
-BT 1 0 0 1 0 52.82 Tm .789983 Tw 12 TL /F1 10 Tf 0 0 0 rg (As you see, the argument ) Tj /F3 10 Tf (command ) Tj /F1 10 Tf (has been annotated with the tuple ) Tj /F3 10 Tf (\("SQL query", 'option',) Tj T* 0 Tw .593876 Tw ('c'\)) Tj /F1 10 Tf (: the first string is the help string which will appear in the usage message, whereas the second and) Tj T* 0 Tw .144988 Tw (third strings tell ) Tj 0 0 .501961 rg (clap ) Tj 0 0 0 rg (that ) Tj /F3 10 Tf (command ) Tj /F1 10 Tf (is an option and that it can be abbreviated with the letter ) Tj /F3 10 Tf (c) Tj /F1 10 Tf (. Of course,) Tj T* 0 Tw 1.543735 Tw (it also possible to use the long option format, by prefixing the option with ) Tj /F3 10 Tf (--command=) Tj /F1 10 Tf (. The resulting) Tj T* 0 Tw (usage message is the following:) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 271.6236 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 468.6898 132 re B*
-Q
-q
-0 0 0 rg
-BT 1 0 0 1 0 113.71 Tm /F3 10 Tf 12 TL ($ python3 example8.py -h) Tj T* (usage: example8.py [-h] [-c COMMAND] dsn) Tj T* T* (positional arguments:) Tj T* ( dsn) Tj T* T* (optional arguments:) Tj T* ( -h, --help show this help message and exit) Tj T* ( -c COMMAND, --command COMMAND) Tj T* ( SQL query) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-1 0 0 1 62.69291 251.6236 cm
-q
-0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (Here are two examples of usage:) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 170.4236 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 468.6898 72 re B*
-Q
-q
-0 0 0 rg
-BT 1 0 0 1 0 53.71 Tm /F3 10 Tf 12 TL ($ python3 example8.py -c"select * from table" dsn) Tj T* (executing select * from table on dsn) Tj T* T* ($ python3 example8.py --command="select * from table" dsn) Tj T* (executing select * from table on dsn) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-1 0 0 1 62.69291 150.4236 cm
-q
-BT 1 0 0 1 0 4.82 Tm 12 TL /F1 10 Tf 0 0 0 rg (Notice that if the option is not passed, the variable ) Tj /F3 10 Tf (command ) Tj /F1 10 Tf (will get the value ) Tj /F3 10 Tf (None) Tj /F1 10 Tf (.) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 132.4236 cm
-q
-0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (Even positional argument can be annotated:) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 87.22362 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 468.6898 36 re B*
-Q
-q
-0 0 0 rg
-BT 1 0 0 1 0 17.71 Tm /F3 10 Tf 12 TL (def main\(command: \("SQL query", 'option', 'c'\),) Tj T* ( dsn: \("Database dsn", 'positional', None\)\):) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-
-endstream
-
-endobj
-% 'R73': class PDFStream
-73 0 obj
-% page stream
-<< /Length 5431 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
-q
-1 0 0 1 62.69291 739.8236 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 468.6898 24 re B*
-Q
-q
-0 0 0 rg
-BT 1 0 0 1 0 5.71 Tm /F3 10 Tf 12 TL ( ...) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-1 0 0 1 62.69291 695.8236 cm
-q
-BT 1 0 0 1 0 28.82 Tm 3.203318 Tw 12 TL /F1 10 Tf 0 0 0 rg (Of course explicit is better than implicit, an no special cases are special enough, but sometimes) Tj T* 0 Tw .64061 Tw (practicality beats purity, so ) Tj 0 0 .501961 rg (clap ) Tj 0 0 0 rg (is smart enough to convert help messages into tuples internally; in other) Tj T* 0 Tw (words, you can just write "Database dsn" instead of ) Tj /F3 10 Tf (\("Database dsn", 'positional', None\)) Tj /F1 10 Tf (:) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 650.6236 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 468.6898 36 re B*
-Q
-q
-0 0 0 rg
-BT 1 0 0 1 0 17.71 Tm /F3 10 Tf 12 TL (def main\(command: \("SQL query", 'option', 'c'\), dsn: "Database dsn"\):) Tj T* ( ...) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-1 0 0 1 62.69291 618.6236 cm
-q
-BT 1 0 0 1 0 16.82 Tm .171988 Tw 12 TL /F1 10 Tf 0 0 0 rg (In both cases the usage message will show a nice help string on the right hand side of the ) Tj /F3 10 Tf (dsn ) Tj /F1 10 Tf (positional) Tj T* 0 Tw (argument. varargs \(starred-arguments\) can also be annotated:) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 573.4236 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 468.6898 36 re B*
-Q
-q
-0 0 0 rg
-BT 1 0 0 1 0 17.71 Tm /F3 10 Tf 12 TL (def main\(dsn: "Database dsn", *scripts: "SQL scripts"\):) Tj T* ( ...) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-1 0 0 1 62.69291 553.4236 cm
-q
-BT 1 0 0 1 0 4.82 Tm 12 TL /F1 10 Tf 0 0 0 rg (is a valid signature for ) Tj 0 0 .501961 rg (clap) Tj 0 0 0 rg (, which will recognize the help strings for both ) Tj /F3 10 Tf (dsn ) Tj /F1 10 Tf (and ) Tj /F3 10 Tf (scripts) Tj /F1 10 Tf (:) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 496.2236 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 468.6898 48 re B*
-Q
-q
-0 0 0 rg
-BT 1 0 0 1 0 29.71 Tm /F3 10 Tf 12 TL (positional arguments:) Tj T* ( dsn Database dsn) Tj T* ( scripts SQL scripts) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-1 0 0 1 62.69291 464.2236 cm
-q
-BT 1 0 0 1 0 16.82 Tm .765868 Tw 12 TL /F1 10 Tf 0 0 .501961 rg (clap ) Tj 0 0 0 rg (also recognizes flags, i.e. boolean options which are ) Tj /F3 10 Tf (True ) Tj /F1 10 Tf (if they are passed to the command line) Tj T* 0 Tw (and ) Tj /F3 10 Tf (False ) Tj /F1 10 Tf (if they are absent. Here is an example:) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 419.0236 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 468.6898 36 re B*
-Q
-q
-0 0 0 rg
-BT 1 0 0 1 0 17.71 Tm /F3 10 Tf 12 TL ($ python3 example9.py -v dsn) Tj T* (connecting to dsn) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-1 0 0 1 62.69291 289.8236 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 468.6898 120 re B*
-Q
-q
-0 0 0 rg
-BT 1 0 0 1 0 101.71 Tm /F3 10 Tf 12 TL ($ python3 example9.py -h) Tj T* (usage: example9.py [-h] [-v] dsn) Tj T* T* (positional arguments:) Tj T* ( dsn connection string) Tj T* T* (optional arguments:) Tj T* ( -h, --help show this help message and exit) Tj T* ( -v, --verbose prints more info) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-1 0 0 1 62.69291 221.8236 cm
-q
-BT 1 0 0 1 0 52.82 Tm 5.832651 Tw 12 TL /F1 10 Tf 0 0 0 rg (For consistency with the way the usage message is printed, I suggest you to follow the) Tj T* 0 Tw 1.686905 Tw (Flag-Option-Positional \(FOP\) convention: in the ) Tj /F3 10 Tf (main ) Tj /F1 10 Tf (function write first the flag arguments, then the) Tj T* 0 Tw .404692 Tw (option arguments and finally the positional arguments. This is just a convention and you are not forced to) Tj T* 0 Tw .478409 Tw (use it, but it makes sense to put the position arguments at the end, since they may be default arguments) Tj T* 0 Tw (and varargs.) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 188.8236 cm
-q
-BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (clap for people not using Python 3) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 122.8236 cm
-q
-BT 1 0 0 1 0 52.82 Tm .12999 Tw 12 TL /F1 10 Tf 0 0 0 rg (I do not use Python 3. At work we are just starting to think about migrating to Python 2.6. I think it will take) Tj T* 0 Tw 1.269988 Tw (years before we even think to migrate to Python 3. I am pretty much sure most Pythonistas are in the) Tj T* 0 Tw 2.089984 Tw (same situation. Therefore ) Tj 0 0 .501961 rg (clap ) Tj 0 0 0 rg (provides a way to work with function annotations even in Python 2.X) Tj T* 0 Tw 1.352339 Tw (\(including Python 2.3\). There is no magic involved; you just need to add the annotations by hand. For) Tj T* 0 Tw (instance) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 89.62362 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 468.6898 24 re B*
-Q
-q
-0 0 0 rg
-BT 1 0 0 1 0 5.71 Tm /F3 10 Tf 12 TL (def main\(dsn: "Database dsn", *scripts: "SQL scripts"\):) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-
-endstream
-
-endobj
-% 'R74': class PDFStream
-74 0 obj
-% page stream
-<< /Length 5574 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
-q
-1 0 0 1 62.69291 753.0236 cm
-q
-0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (becomes:) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 671.8236 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 468.6898 72 re B*
-Q
-q
-0 0 0 rg
-BT 1 0 0 1 0 53.71 Tm /F3 10 Tf 12 TL (def main\(dsn, *scripts\):) Tj T* ( ...) Tj T* (main.__annotations__ = dict\() Tj T* (dsn="Database dsn",) Tj T* (scripts="SQL scripts"\)) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-1 0 0 1 62.69291 627.8236 cm
-q
-BT 1 0 0 1 0 28.82 Tm .412765 Tw 12 TL /F1 10 Tf 0 0 0 rg (One should be careful to much the keys of the annotations dictionary with the names of the arguments in) Tj T* 0 Tw 3.347485 Tw (the annotated function; for lazy people with Python 2.4 available the simplest way is to use the) Tj T* 0 Tw /F3 10 Tf (clap.annotations ) Tj /F1 10 Tf (decorator that performs the check for you.) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 546.6236 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 468.6898 72 re B*
-Q
-q
-0 0 0 rg
-BT 1 0 0 1 0 53.71 Tm /F3 10 Tf 12 TL (@annotations\() Tj T* (dsn="Database dsn",) Tj T* (scripts="SQL scripts"\)) Tj T* (def main\(dsn, *scripts\):) Tj T* ( ...) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-1 0 0 1 62.69291 514.6236 cm
-q
-BT 1 0 0 1 0 16.82 Tm 1.422164 Tw 12 TL /F1 10 Tf 0 0 0 rg (In the rest of this article I will assume that you are using Python 2.X with ) Tj /F3 10 Tf (X >) Tj (= 4 ) Tj /F1 10 Tf (and I will use the) Tj T* 0 Tw /F3 10 Tf (clap.annotations ) Tj /F1 10 Tf (decorator.) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 481.6236 cm
-q
-BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Advanced usage) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 427.6236 cm
-q
-BT 1 0 0 1 0 40.82 Tm .115703 Tw 12 TL /F1 10 Tf 0 0 0 rg (One of the goals of clap is to have a learning curve of ) Tj /F4 10 Tf (minutes) Tj /F1 10 Tf (, compared to the learning curve of ) Tj /F4 10 Tf (hours ) Tj /F1 10 Tf (of) Tj T* 0 Tw .196098 Tw 0 0 .501961 rg (argparse) Tj 0 0 0 rg (. That does not mean that I have removed all the advanced features of ) Tj 0 0 .501961 rg (argparse) Tj 0 0 0 rg (. Actually a lot of) Tj T* 0 Tw 1.529269 Tw 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (power persists in ) Tj 0 0 .501961 rg (clap) Tj 0 0 0 rg (: in particular, the ) Tj /F3 10 Tf (type) Tj /F1 10 Tf (, ) Tj /F3 10 Tf (choices ) Tj /F1 10 Tf (and ) Tj /F3 10 Tf (metavar ) Tj /F1 10 Tf (concepts are there.) Tj T* 0 Tw (Until now, I have only showed simple annotations, but in general an annotation is a 5-tuple of the form) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 421.6236 cm
-Q
-q
-1 0 0 1 62.69291 409.6236 cm
-0 0 0 rg
-BT /F5 10 Tf 12 TL ET
-BT 1 0 0 1 0 2 Tm T* ET
-q
-1 0 0 1 20 0 cm
-q
-0 0 0 rg
-BT 1 0 0 1 0 5.71 Tm /F3 10 Tf 12 TL (\(help, kind, abbrev, type, choices, metavar\)) Tj T* ET
-Q
-Q
-q
-Q
-Q
-q
-1 0 0 1 62.69291 409.6236 cm
-Q
-q
-1 0 0 1 62.69291 367.6236 cm
-q
-BT 1 0 0 1 0 28.82 Tm 3.38811 Tw 12 TL /F1 10 Tf 0 0 0 rg (where ) Tj /F3 10 Tf (help ) Tj /F1 10 Tf (is the help message, ) Tj /F3 10 Tf (kind ) Tj /F1 10 Tf (is one of {"flag", "option ", "positional"}, ) Tj /F3 10 Tf (abbrev ) Tj /F1 10 Tf (is a) Tj T* 0 Tw 2.203735 Tw (one-character string, ) Tj /F3 10 Tf (type ) Tj /F1 10 Tf (is callable taking a string in input, choices is a sequence of values and) Tj T* 0 Tw /F3 10 Tf (metavar ) Tj /F1 10 Tf (is a string.) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 337.6236 cm
-q
-BT 1 0 0 1 0 16.82 Tm .006654 Tw 12 TL /F3 10 Tf 0 0 0 rg (type ) Tj /F1 10 Tf (is used to automagically convert the arguments from string to any Python type; by default there is no) Tj T* 0 Tw (convertion i.e. ) Tj /F3 10 Tf (type=None) Tj /F1 10 Tf (.) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 307.6236 cm
-q
-BT 1 0 0 1 0 16.82 Tm 2.904692 Tw 12 TL /F3 10 Tf 0 0 0 rg (choices ) Tj /F1 10 Tf (is used to restrict the number of the valid options; by default there is no restriction i.e.) Tj T* 0 Tw /F3 10 Tf (choices=None) Tj /F1 10 Tf (.) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 277.6236 cm
-q
-BT 1 0 0 1 0 16.82 Tm 1.071751 Tw 12 TL /F3 10 Tf 0 0 0 rg (metavar ) Tj /F1 10 Tf (is used to change the argument name in the usage message \(and only there\); by default the) Tj T* 0 Tw (metavar is equal to the name of the argument.) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 259.6236 cm
-q
-BT 1 0 0 1 0 4.82 Tm 12 TL /F1 10 Tf 0 0 0 rg (Here is an example showing all of such features \(shamelessly stolen from the ) Tj 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (documentation\):) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 253.6236 cm
-Q
-q
-1 0 0 1 62.69291 84.21376 cm
-0 0 0 rg
-BT /F5 10 Tf 12 TL ET
-BT 1 0 0 1 0 2 Tm T* ET
-q
-1 0 0 1 20 0 cm
-q
-q
-.934933 0 0 .934933 0 0 cm
-q
-1 0 0 1 6.6 7.059329 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 480 180 re B*
-Q
-q
-0 0 0 rg
-BT 1 0 0 1 0 161.71 Tm /F3 10 Tf 12 TL (import clap) Tj T* T* (@clap.annotations\() Tj T* (operator=\("The name of an operator", 'positional', None, str, ['add', 'mul']\),) Tj T* (numbers=\("A number", 'positional', None, float, None, "n"\)\)) Tj T* (def main\(operator, *numbers\):) Tj T* ( op = getattr\(float, '__%s__' % operator\)) Tj T* ( result = dict\(add=0.0, mul=1.0\)[operator]) Tj T* ( for n in numbers:) Tj T* ( result = op\(result, n\)) Tj T* ( print\(result\)) Tj T* T* (if __name__ == '__main__':) Tj T* ( clap.call\(main\)) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-Q
-Q
-q
-1 0 0 1 62.69291 84.21376 cm
-Q
-
-endstream
-
-endobj
-% 'R75': class PDFStream
-75 0 obj
-% page stream
-<< /Length 5160 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
-q
-1 0 0 1 62.69291 753.0236 cm
-q
-0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (Here is the usage for the script:) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 635.8236 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 468.6898 108 re B*
-Q
-q
-0 0 0 rg
-BT 1 0 0 1 0 89.71 Tm /F3 10 Tf 12 TL (usage: example10.py [-h] {add,mul} [n [n ...]]) Tj T* T* (positional arguments:) Tj T* ( {add,mul} The name of an operator) Tj T* ( n A number) Tj T* T* (optional arguments:) Tj T* ( -h, --help show this help message and exit) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-1 0 0 1 62.69291 615.8236 cm
-q
-0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (Here are a couple of examples of use:) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 522.4849 cm
-q
-q
-.87797 0 0 .87797 0 0 cm
-q
-1 0 0 1 6.6 7.517338 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 534 96 re B*
-Q
-q
-0 0 0 rg
-BT 1 0 0 1 0 77.71 Tm /F3 10 Tf 12 TL ($ python example10.py add 1 2 3 4) Tj T* (10.0) Tj T* ($ python example10.py mul 1 2 3 4) Tj T* (24.0) Tj T* ($ python example10.py ad 1 2 3 4 # a mispelling error) Tj T* (usage: example10.py [-h] {add,mul} [n [n ...]]) Tj T* (example10.py: error: argument operator: invalid choice: 'ad' \(choose from 'add', 'mul'\)) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-1 0 0 1 62.69291 489.4849 cm
-q
-BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (A few notes on the underlying implementation) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 423.4849 cm
-q
-BT 1 0 0 1 0 52.82 Tm .928488 Tw 12 TL /F1 10 Tf 0 0 .501961 rg (clap ) Tj 0 0 0 rg (relies on a ) Tj 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (for all of the heavy lifting work. It is possible to pass options to the underlying) Tj T* 0 Tw .03816 Tw 0 0 .501961 rg (ArgumentParser ) Tj 0 0 0 rg (object \(currently it accepts the default arguments ) Tj /F3 10 Tf (prog) Tj /F1 10 Tf (, ) Tj /F3 10 Tf (usage) Tj /F1 10 Tf (, ) Tj /F3 10 Tf (description) Tj /F1 10 Tf (, ) Tj /F3 10 Tf (epilog) Tj /F1 10 Tf (,) Tj T* 0 Tw 18.21744 Tw /F3 10 Tf (version) Tj /F1 10 Tf (, ) Tj /F3 10 Tf (parents) Tj /F1 10 Tf (, ) Tj /F3 10 Tf (formatter_class) Tj /F1 10 Tf (, ) Tj /F3 10 Tf (prefix_chars) Tj /F1 10 Tf (, ) Tj /F3 10 Tf (fromfile_prefix_chars) Tj /F1 10 Tf (,) Tj T* 0 Tw 1.035976 Tw /F3 10 Tf (argument_default) Tj /F1 10 Tf (, ) Tj /F3 10 Tf (conflict_handler) Tj /F1 10 Tf (, ) Tj /F3 10 Tf (add_help) Tj /F1 10 Tf (\) simply by setting such attributes on the ) Tj /F3 10 Tf (main) Tj T* 0 Tw /F1 10 Tf (function. For instance) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 354.2849 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 468.6898 60 re B*
-Q
-q
-0 0 0 rg
-BT 1 0 0 1 0 41.71 Tm /F3 10 Tf 12 TL (def main\(...\):) Tj T* ( pass) Tj T* T* (main.add_help = False) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-1 0 0 1 62.69291 298.2849 cm
-q
-BT 1 0 0 1 0 40.82 Tm 1.256457 Tw 12 TL /F1 10 Tf 0 0 0 rg (disable the recognition of the help flag ) Tj /F3 10 Tf (-h, --help) Tj /F1 10 Tf (. This is not particularly elegant, but I assume the) Tj T* 0 Tw .274751 Tw (typical user of ) Tj 0 0 .501961 rg (clap ) Tj 0 0 0 rg (will be happy with the default message and would not want to go at this level of detail;) Tj T* 0 Tw 1.463876 Tw (still it is possible if she wants to. I redirect the interested readers to the documentation of ) Tj 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (to) Tj T* 0 Tw (understand the meaning of the various options.) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 268.2849 cm
-q
-BT 1 0 0 1 0 16.82 Tm .154269 Tw 12 TL /F1 10 Tf 0 0 0 rg (If you want to access the underlying ) Tj 0 0 .501961 rg (ArgumentParser ) Tj 0 0 0 rg (object, you can use the ) Tj /F3 10 Tf (clap.parser_from ) Tj /F1 10 Tf (utility) Tj T* 0 Tw (function:) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 151.0849 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 468.6898 108 re B*
-Q
-q
-BT 1 0 0 1 0 89.71 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( import clap) Tj T* (>) Tj (>) Tj (>) Tj ( def main\(arg\):) Tj T* (... pass) Tj T* (...) Tj T* (>) Tj (>) Tj (>) Tj ( print clap.parser_from\(main\)) Tj T* (ArgumentParser\(prog='', usage=None, description=None, version=None,) Tj T* (formatter_class=) Tj (<) Tj (class 'argparse.HelpFormatter') Tj (>) Tj (, conflict_handler='error',) Tj T* (add_help=True\)) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-1 0 0 1 62.69291 131.0849 cm
-q
-BT 1 0 0 1 0 4.82 Tm 12 TL /F1 10 Tf 0 0 0 rg (I use ) Tj /F3 10 Tf (clap.parser_from ) Tj /F1 10 Tf (in the unit tests of the module, but regular users should never need to use it.) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 101.0849 cm
-q
-BT 1 0 0 1 0 16.82 Tm .541318 Tw 12 TL /F1 10 Tf 0 0 .501961 rg (clap ) Tj 0 0 0 rg (uses an ) Tj /F3 10 Tf (Annotation ) Tj /F1 10 Tf (class to convert the raw annotations in the function signature into annotation) Tj T* 0 Tw (objects, i.e. objects with six attributes ) Tj /F3 10 Tf (help, kind, short, type, choices, metavar) Tj /F1 10 Tf (.) Tj T* ET
-Q
-Q
-
-endstream
-
-endobj
-% 'R76': class PDFStream
-76 0 obj
-% page stream
-<< /Length 3056 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
-q
-1 0 0 1 62.69291 717.0236 cm
-q
-0 0 0 rg
-BT 1 0 0 1 0 40.82 Tm /F1 10 Tf 12 TL 1.682126 Tw (Advanced users can implement their own annotation objects. Since the special case of no annotation) Tj T* 0 Tw 1.088735 Tw (must be taken care of, the annotation factory must return a suitable default annotation object where no) Tj T* 0 Tw .18811 Tw (arguments are passed in input. Here is an example of how you could implement annotations for positional) Tj T* 0 Tw (arguments:) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 711.0236 cm
-Q
-q
-1 0 0 1 62.69291 601.8236 cm
-0 0 0 rg
-BT /F5 10 Tf 12 TL ET
-BT 1 0 0 1 0 2 Tm T* ET
-q
-1 0 0 1 20 0 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 448.6898 108 re B*
-Q
-q
-0 0 0 rg
-BT 1 0 0 1 0 89.71 Tm /F3 10 Tf 12 TL (class Positional\(object\):) Tj T* ( def __init__\(self, help='', type=None, choices=None, metavar=None\):) Tj T* ( self.help = help) Tj T* ( self.kind = 'positional') Tj T* ( self.abbrev = None) Tj T* ( self.type = type) Tj T* ( self.choices = choices) Tj T* ( self.metavar = metavar) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-Q
-Q
-q
-1 0 0 1 62.69291 601.8236 cm
-Q
-q
-1 0 0 1 62.69291 583.8236 cm
-q
-0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (You can use such annotations objects as follows:) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 577.8236 cm
-Q
-q
-1 0 0 1 62.69291 420.6236 cm
-0 0 0 rg
-BT /F5 10 Tf 12 TL ET
-BT 1 0 0 1 0 2 Tm T* ET
-q
-1 0 0 1 20 0 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 448.6898 156 re B*
-Q
-q
-0 0 0 rg
-BT 1 0 0 1 0 137.71 Tm /F3 10 Tf 12 TL (import clap) Tj T* (from annotations import Positional) Tj T* T* (@clap.annotations\() Tj T* ( i=Positional\("This is an int", int\),) Tj T* ( n=Positional\("This is a float", float\),) Tj T* ( rest=Positional\("Other arguments"\)\)) Tj T* (def main\(i, n, *rest\):) Tj T* ( print\(i, n, rest\)) Tj T* T* (if __name__ == '__main__':) Tj T* ( import clap; clap.call\(main\)) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-Q
-Q
-q
-1 0 0 1 62.69291 420.6236 cm
-Q
-q
-1 0 0 1 62.69291 402.6236 cm
-q
-0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (Here is the usage message:) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 273.4236 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 468.6898 120 re B*
-Q
-q
-0 0 0 rg
-BT 1 0 0 1 0 101.71 Tm /F3 10 Tf 12 TL (usage: example11.py [-h] i n [rest [rest ...]]) Tj T* T* (positional arguments:) Tj T* ( i This is an int) Tj T* ( n This is a float) Tj T* ( rest Other arguments) Tj T* T* (optional arguments:) Tj T* ( -h, --help show this help message and exit) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-1 0 0 1 62.69291 253.4236 cm
-q
-0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (You can go on and define Option and Flag classes, if you like.) Tj T* ET
-Q
-Q
-
-endstream
-
-endobj
-% 'R77': class PDFPageLabels
-77 0 obj
-% Document Root
-<< /Nums [ 0
- 78 0 R
- 1
- 79 0 R
- 2
- 80 0 R
- 3
- 81 0 R
- 4
- 82 0 R
- 5
- 83 0 R
- 6
- 84 0 R
- 7
- 85 0 R ] >>
-endobj
-% 'R78': class PDFPageLabel
-78 0 obj
-% None
-<< /S /D
- /St 1 >>
-endobj
-% 'R79': class PDFPageLabel
-79 0 obj
-% None
-<< /S /D
- /St 2 >>
-endobj
-% 'R80': class PDFPageLabel
-80 0 obj
-% None
-<< /S /D
- /St 3 >>
-endobj
-% 'R81': class PDFPageLabel
-81 0 obj
-% None
-<< /S /D
- /St 4 >>
-endobj
-% 'R82': class PDFPageLabel
-82 0 obj
-% None
-<< /S /D
- /St 5 >>
-endobj
-% 'R83': class PDFPageLabel
-83 0 obj
-% None
-<< /S /D
- /St 6 >>
-endobj
-% 'R84': class PDFPageLabel
-84 0 obj
-% None
-<< /S /D
- /St 7 >>
-endobj
-% 'R85': class PDFPageLabel
-85 0 obj
-% None
-<< /S /D
- /St 8 >>
-endobj
-xref
-0 86
-0000000000 65535 f
-0000000113 00000 n
-0000000260 00000 n
-0000000425 00000 n
-0000000612 00000 n
-0000000872 00000 n
-0000001134 00000 n
-0000001382 00000 n
-0000001630 00000 n
-0000001894 00000 n
-0000002158 00000 n
-0000002423 00000 n
-0000002688 00000 n
-0000002938 00000 n
-0000003191 00000 n
-0000003366 00000 n
-0000003619 00000 n
-0000003801 00000 n
-0000003969 00000 n
-0000004369 00000 n
-0000004631 00000 n
-0000004895 00000 n
-0000005145 00000 n
-0000005411 00000 n
-0000005677 00000 n
-0000005942 00000 n
-0000006192 00000 n
-0000006443 00000 n
-0000006822 00000 n
-0000007088 00000 n
-0000007354 00000 n
-0000007619 00000 n
-0000007870 00000 n
-0000008213 00000 n
-0000008501 00000 n
-0000008785 00000 n
-0000009051 00000 n
-0000009339 00000 n
-0000009590 00000 n
-0000009942 00000 n
-0000010207 00000 n
-0000010473 00000 n
-0000010739 00000 n
-0000010990 00000 n
-0000011333 00000 n
-0000011583 00000 n
-0000011833 00000 n
-0000012083 00000 n
-0000012345 00000 n
-0000012580 00000 n
-0000012932 00000 n
-0000013197 00000 n
-0000013447 00000 n
-0000013734 00000 n
-0000014000 00000 n
-0000014250 00000 n
-0000014537 00000 n
-0000014788 00000 n
-0000015143 00000 n
-0000015424 00000 n
-0000015583 00000 n
-0000015849 00000 n
-0000015974 00000 n
-0000016165 00000 n
-0000016369 00000 n
-0000016562 00000 n
-0000016772 00000 n
-0000016962 00000 n
-0000017151 00000 n
-0000017322 00000 n
-0000023577 00000 n
-0000028311 00000 n
-0000032802 00000 n
-0000038318 00000 n
-0000043850 00000 n
-0000049525 00000 n
-0000054786 00000 n
-0000057947 00000 n
-0000058131 00000 n
-0000058208 00000 n
-0000058285 00000 n
-0000058362 00000 n
-0000058439 00000 n
-0000058516 00000 n
-0000058593 00000 n
-0000058670 00000 n
-trailer
-<< /ID
- % ReportLab generated PDF document -- digest (http://www.reportlab.com)
- [(\261\274,t\312\324D[\217\346f\222\0103;\021) (\261\274,t\312\324D[\217\346f\222\0103;\021)]
-
- /Info 60 0 R
- /Root 59 0 R
- /Size 86 >>
-startxref
-58717
-%%EOF
diff --git a/clap/article/article.txt b/clap/article/article.txt
deleted file mode 100644
index 79cb834..0000000
--- a/clap/article/article.txt
+++ /dev/null
@@ -1,442 +0,0 @@
-The Easiest Command Line Arguments Parser in the World
-================================================================
-
-There is no want of command line arguments parsers in Python
-world. The standard library alone contains three different modules for
-the parsing of command line options: getopt_ (from the stone age),
-optparse_ (from Python 2.3) and argparse_ (from Python 2.7). All of
-them are quite powerful and especially argparse_ is an industrial
-strength solution; unfortunately, all of them have a non-zero learning
-curve and a certain verbosity.
-
-Enters clap_. clap_ is designed to be `downwardly scalable`_, i.e. to
-be trivially simple to use for trivial use cases, and to have a
-next-to-zero learning curve. Technically clap_ is just a simple
-wrapper over argparse_, hiding most of the complexity while retaining
-most of the power. clap_ is surprisingly scalable upwards even for
-non-trivial use cases, but it is not intended to be an industrial
-strength command line parsing module. Its capabilities are limited by
-design. If you need more power, by all means use the parsing modules
-in the standard library. Still, I have been using Python for 8 years
-and never once I had to use the full power of the standard library
-modules.
-
-Actually I am pretty much convinced that features provided by ``clap``
-are more than enough for 99.9% of the typical use cases of a scripter
-working in a Unix-like environment. I am targetting here programmers,
-sys-admins, scientists and in general people writing throw-away scripts
-for themselves, choosing to use a command line interface because it is
-the quick and simple. Such users are not interested in features,
-they just want to be able to write a simple command line tool from a
-simple specification, not to build a command line parser by
-hand. Unfortunately, the current modules in the standard library
-forces them to go the hard way. They are designed to implement
-power user tools for programmers or system administrators, and
-they have a non-trivial learning curve.
-
-The importance of scaling down
-------------------------------------
-
-An ex-coworker of mine, David Welton, once wrote a nice article about
-the importance of `scaling down`_: most people are concerned with the
-possibility of scaling up, but we should also be concerned with the
-issue of scaling down: in other worlds, simple things should be kept
-simple. To be concrete, let me start with the simplest possible
-thing: a script that takes a single argument and does something to it.
-It cannot get more trivial than that (discarding the possibility of
-a script without command line arguments, where there is nothing to parse),
-nevertheless it is a use case *extremely common*:
-I need to write scripts like that nearly every day, I wrote hundreds
-of them in the last few years and I have never been happy. Here is
-a typical example of code I have been writing by hand for years:
-
- .. include:: example1.py
- :literal:
-
-As you see the whole ``if __name__ == '__main__'`` block (nine lines) is
-essentially boilerplate that should not exists. Actually I think the
-Python language should recognize the main function and perform trivial
-arguments parsing behind the scenes; unfortunaly this is unlikely to
-happen. I have been writing boilerplate like this in hundreds of
-scripts for years, and every time I *hate* it. The purpose of using a
-scripting language is convenience and trivial things should be
-trivial. Unfortunately the standard library modules do not help for
-this use case, which may be trivial, but it is still incredibly
-common. Using getopt_ and optparse_ does not help, since they are
-intended to manage options and not positional arguments; the argparse_
-module helps a bit and it is able to reduce the boilerplate from nine
-lines to six lines:
-
- .. include:: example2.py
- :literal:
-
-However saving three lines does not justify introducing the external
-dependency: most people will not switch Python 2.7, which at the time of
-this writing is just about to be released, for many years.
-Moreover, it just feels too complex to instantiate a class and to
-define a parser by hand for such a trivial task.
-
-The clap_ module is designed to manage well such use cases, and it is able
-to reduce the original nine lines of boiler plate to two lines. With the
-clap_ module all you need to write is
-
- .. include:: example3.py
- :literal:
-
-The clap_ module provides for free (actually the work is done by the
-underlying argparse_ module) a nice usage message::
-
- $ python example3.py -h
- usage: example3.py [-h] dsn
-
- positional arguments:
- dsn
-
- optional arguments:
- -h, --help show this help message and exit
-
-This is only the tip of the iceberg: clap_ is able to do much more than that.
-
-Positional default arguments
---------------------------------------------------
-
-I have encountered this use case at work hundreds of times:
-
- .. include:: example4.py
- :literal:
-
-With clap_ the entire ``__main__`` block reduces to the usual two lines::
-
- if __name__ == '__main__':
- import clap; clap.call(main)
-
-In other words, six lines of boilerplate have been removed, and I have
-the usage message for free::
-
- usage: example4_.py [-h] dsn [table] [today]
-
- positional arguments:
- dsn
- table
- today
-
- optional arguments:
- -h, --help show this help message and exit
-
-clap_ manages transparently even the case when you want to pass a
-variable number of arguments. Here is an example, a script running
-on a database a series of ``.sql`` scripts:
-
- .. include:: example6.py
- :literal:
-
-Using clap_, you can just replace the ``__main__`` block with the usual
-``import clap; clap.call(main)`` and you get the following usage message::
-
- usage: example7.py [-h] dsn [scripts [scripts ...]]
-
- positional arguments:
- dsn
- scripts
-
- optional arguments:
- -h, --help show this help message and exit
-
-The examples here should have made clear that *clap is able to figure out
-the command line arguments parser to use from the signature of the main
-function*. This is the whole idea behind clap_: if my intent is clear,
-let's the machine takes care of the details.
-
-Options and flags
----------------------------------------
-
-It is surprising how few command line scripts with options
-I have written over the years (probably less than a hundred),
-compared to the number of scripts with positional arguments
-(I certainly have written more than a thousand of them).
-Still, this use case is quite common and cannot be neglected.
-The standard library modules (all of them) are quite verbose
-when it comes to specifying the options and frankly I have
-never used them directly. Instead, I have always relied on
-an old recipe of mine, the optionparse_ recipe, which provides a
-convenient wrapper over optionparse_. Alternatively, in the simplest cases,
-I have just performed the parsing by hand, instead of manually building
-a suitable OptionParser.
-
-clap_ is inspired to the optionparse_ recipe, in the sense that
-it delivers the programmer from the burden of writing the
-parser, but is less of a hack: instead
-of extracting the parser from the docstring of the module, it
-extracts it from the signature of the ``main`` function.
-
-The idea comes from the `function annotations` concept, a new
-feature of Python 3. An example is worth a thousand words, so here
-it is:
-
- .. include:: example8.py
- :literal:
-
-As you see, the argument ``command`` has been annotated with the
-tuple ``("SQL query", 'option', 'c')``: the first string is the
-help string which will appear in the usage message, whereas the
-second and third strings tell clap_ that ``command`` is an option and that
-it can be abbreviated with the letter ``c``. Of course, it also
-possible to use the long option format, by prefixing the option
-with ``--command=``. The resulting usage message is the following::
-
- $ python3 example8.py -h
- usage: example8.py [-h] [-c COMMAND] dsn
-
- positional arguments:
- dsn
-
- optional arguments:
- -h, --help show this help message and exit
- -c COMMAND, --command COMMAND
- SQL query
-
-Here are two examples of usage::
-
- $ python3 example8.py -c"select * from table" dsn
- executing select * from table on dsn
-
- $ python3 example8.py --command="select * from table" dsn
- executing select * from table on dsn
-
-Notice that if the option is not passed, the variable ``command``
-will get the value ``None``.
-
-Even positional argument can be annotated::
-
- def main(command: ("SQL query", 'option', 'c'),
- dsn: ("Database dsn", 'positional', None)):
- ...
-
-Of course explicit is better than implicit, an no special cases are
-special enough, but sometimes practicality beats purity, so clap_ is
-smart enough to convert help messages into tuples internally; in other
-words, you can just write "Database dsn" instead of ``("Database dsn",
-'positional', None)``::
-
-
- def main(command: ("SQL query", 'option', 'c'), dsn: "Database dsn"):
- ...
-
-In both cases
-the usage message will show a nice help string on the right hand side
-of the ``dsn`` positional argument. varargs (starred-arguments) can also
-be annotated::
-
- def main(dsn: "Database dsn", *scripts: "SQL scripts"):
- ...
-
-is a valid signature for clap_, which will recognize the help strings
-for both ``dsn`` and ``scripts``::
-
- positional arguments:
- dsn Database dsn
- scripts SQL scripts
-
-clap_ also recognizes flags, i.e. boolean options which are
-``True`` if they are passed to the command line and ``False``
-if they are absent. Here is an example::
-
- $ python3 example9.py -v dsn
- connecting to dsn
-
-::
-
- $ python3 example9.py -h
- usage: example9.py [-h] [-v] dsn
-
- positional arguments:
- dsn connection string
-
- optional arguments:
- -h, --help show this help message and exit
- -v, --verbose prints more info
-
-For consistency with the way the usage message is printed, I suggest you to
-follow the Flag-Option-Positional (FOP) convention: in the ``main``
-function write first the flag arguments, then the option arguments and
-finally the positional arguments. This is just a convention and you are
-not forced to use it, but
-it makes sense to put the position arguments at the end, since they
-may be default arguments and varargs.
-
-clap for people not using Python 3
---------------------------------------------------
-
-I do not use Python 3. At work we are just starting to think about
-migrating to Python 2.6. I think it will take years before we even
-think to migrate to Python 3. I am pretty much sure most Pythonistas
-are in the same situation. Therefore clap_ provides a way to work
-with function annotations even in Python 2.X (including Python 2.3).
-There is no magic involved; you just need to add the annotations
-by hand. For instance
-
-::
-
- def main(dsn: "Database dsn", *scripts: "SQL scripts"):
-
-becomes::
-
- def main(dsn, *scripts):
- ...
- main.__annotations__ = dict(
- dsn="Database dsn",
- scripts="SQL scripts")
-
-One should be careful to much the keys of the annotations dictionary
-with the names of the arguments in the annotated function; for lazy
-people with Python 2.4 available the simplest way is to use the
-``clap.annotations`` decorator that performs the check for you.
-
-::
-
- @annotations(
- dsn="Database dsn",
- scripts="SQL scripts")
- def main(dsn, *scripts):
- ...
-
-In the rest of this article I will assume that you are using Python 2.X with
-``X >= 4`` and I will use the ``clap.annotations`` decorator.
-
-Advanced usage
---------------------------------------------------
-
-One of the goals of clap is to have a learning curve of *minutes*, compared
-to the learning curve of *hours* of argparse_. That does not mean
-that I have removed all the advanced features of argparse_. Actually
-a lot of argparse_ power persists in clap_: in particular, the
-``type``, ``choices`` and ``metavar`` concepts are there.
-Until now, I have only showed simple annotations, but in general
-an annotation is a 5-tuple of the form
-
- ``(help, kind, abbrev, type, choices, metavar)``
-
-where ``help`` is the help message, ``kind`` is one of {"flag",
-"option ", "positional"}, ``abbrev`` is a one-character string,
-``type`` is callable taking a string in input, choices is a sequence
-of values and ``metavar`` is a string.
-
-``type`` is used to automagically convert the arguments from string
-to any Python type; by default there is no convertion i.e. ``type=None``.
-
-``choices`` is used to restrict the number of the valid
-options; by default there is no restriction i.e. ``choices=None``.
-
-``metavar`` is used to change the argument name in the usage
-message (and only there); by default the metavar is equal to the name of the
-argument.
-
-Here is an example showing all of such features (shamelessly stolen
-from the argparse_ documentation):
-
- .. include:: example10.py
- :literal:
-
-Here is the usage for the script::
-
- usage: example10.py [-h] {add,mul} [n [n ...]]
-
- positional arguments:
- {add,mul} The name of an operator
- n A number
-
- optional arguments:
- -h, --help show this help message and exit
-
-Here are a couple of examples of use::
-
- $ python example10.py add 1 2 3 4
- 10.0
- $ python example10.py mul 1 2 3 4
- 24.0
- $ python example10.py ad 1 2 3 4 # a mispelling error
- usage: example10.py [-h] {add,mul} [n [n ...]]
- example10.py: error: argument operator: invalid choice: 'ad' (choose from 'add', 'mul')
-
-A few notes on the underlying implementation
-----------------------------------------------------
-
-clap_ relies on a argparse_ for all of the heavy lifting work. It is possible
-to pass options to the underlying ArgumentParser_ object (currently it
-accepts the default arguments ``description``, ``epilog``, ``prog``, ``usage``,
-``add_help``, ``argument_default``, ``parents``, ``prefix_chars``,
-``conflict_handler``, ``formatter_class``) simply by setting such attributes
-on the ``main`` function.
-For instance
-
-::
-
- def main(...):
- pass
-
- main.add_help = False
-
-disable the recognition of the help flag ``-h, --help``. This is not
-particularly elegant, but I assume the typical user of clap_ will be
-happy with the default message and would not want to go at this level
-of detail; still it is possible if she wants to. I redirect the interested
-readers to the documentation of argparse_ to understand the meaning of
-the various options.
-
-If you want to access the underlying ArgumentParser_ object, you can
-use the ``clap.parser_from`` utility function:
-
->>> import clap
->>> def main(arg):
-... pass
-...
->>> print clap.parser_from(main)
-ArgumentParser(prog='', usage=None, description=None, version=None,
-formatter_class=<class 'argparse.HelpFormatter'>, conflict_handler='error',
-add_help=True)
-
-I use ``clap.parser_from`` in the unit tests of the module, but regular
-users should never need to use it.
-
-clap_ uses an ``Annotation`` class to convert the tuples
-in the function signature into annotation objects, i.e. objects with
-six attributes ``help, kind, short, type, choices, metavar``.
-
-Advanced users can implement their own annotation objects.
-For instance, here is an example of how you could implement annotations for
-positional arguments:
-
- .. include:: annotations.py
- :literal:
-
-You can use such annotations objects as follows:
-
- .. include:: example11.py
- :literal:
-
-Here is the usage message::
-
- usage: example11.py [-h] i n [rest [rest ...]]
-
- positional arguments:
- i This is an int
- n This is a float
- rest Other arguments
-
- optional arguments:
- -h, --help show this help message and exit
-
-You can go on and define ``Option`` and ``Flag`` classes, if you like.
-Using custom annotation objects you could do advanced things like extracting the
-annotations from a configuration file or from a database, but I expect such
-use cases to be quite rare: the default mechanism should work
-pretty well for most users.
-
-.. _argparse: http://argparse.googlecode.com
-.. _optparse: http://docs.python.org/library/optparse.html
-.. _getopt: http://docs.python.org/library/getopt.html
-.. _optionparse: http://code.activestate.com/recipes/278844-parsing-the-command-line/
-.. _clap:
-.. _scaling down: http://www.welton.it/articles/scalable_systems
-.. _downwardly scalable: http://www.welton.it/articles/scalable_systems
-.. _ArgumentParser: http://argparse.googlecode.com/svn/tags/r11/doc/ArgumentParser.html
diff --git a/clap/article/clap.py b/clap/article/clap.py
deleted file mode 120000
index f85cf0d..0000000
--- a/clap/article/clap.py
+++ /dev/null
@@ -1 +0,0 @@
-../clap.py \ No newline at end of file
diff --git a/clap/article/example1.py b/clap/article/example1.py
deleted file mode 100644
index 59d4ef1..0000000
--- a/clap/article/example1.py
+++ /dev/null
@@ -1,13 +0,0 @@
-def main(dsn):
- "Do something with the database"
- print(dsn)
-
-if __name__ == '__main__':
- import sys
- n = len(sys.argv[1:])
- if n == 0:
- sys.exit('usage: python %s dsn' % sys.argv[0])
- elif n == 1:
- main(sys.argv[1])
- else:
- sys.exit('Unrecognized arguments: %s' % ' '.join(sys.argv[2:]))
diff --git a/clap/article/example10.py b/clap/article/example10.py
deleted file mode 100644
index 3797c3f..0000000
--- a/clap/article/example10.py
+++ /dev/null
@@ -1,14 +0,0 @@
-import clap
-
-@clap.annotations(
-operator=("The name of an operator", 'positional', None, str, ['add', 'mul']),
-numbers=("A number", 'positional', None, float, None, "n"))
-def main(operator, *numbers):
- op = getattr(float, '__%s__' % operator)
- result = dict(add=0.0, mul=1.0)[operator]
- for n in numbers:
- result = op(result, n)
- print(result)
-
-if __name__ == '__main__':
- clap.call(main)
diff --git a/clap/article/example11.py b/clap/article/example11.py
deleted file mode 100644
index 9c078b7..0000000
--- a/clap/article/example11.py
+++ /dev/null
@@ -1,12 +0,0 @@
-import clap
-from annotations import Positional
-
-@clap.annotations(
- i=Positional("This is an int", int),
- n=Positional("This is a float", float),
- rest=Positional("Other arguments"))
-def main(i, n, *rest):
- print(i, n, rest)
-
-if __name__ == '__main__':
- import clap; clap.call(main)
diff --git a/clap/article/example2.py b/clap/article/example2.py
deleted file mode 100644
index 69981ee..0000000
--- a/clap/article/example2.py
+++ /dev/null
@@ -1,10 +0,0 @@
-def main(dsn):
- "Do something on the database"
- print(dsn)
-
-if __name__ == '__main__':
- import argparse
- p = argparse.ArgumentParser()
- p.add_argument('dsn')
- arg = p.parse_args()
- main(arg.dsn)
diff --git a/clap/article/example3.py b/clap/article/example3.py
deleted file mode 100644
index 94b756f..0000000
--- a/clap/article/example3.py
+++ /dev/null
@@ -1,6 +0,0 @@
-def main(dsn):
- "Do something with the database"
- print(dsn)
-
-if __name__ == '__main__':
- import clap; clap.call(main)
diff --git a/clap/article/example4.py b/clap/article/example4.py
deleted file mode 100644
index 08a7dd2..0000000
--- a/clap/article/example4.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from datetime import datetime
-
-def main(dsn, table='product', today=datetime.today()):
- "Do something on the database"
- print(dsn, table, today)
-
-if __name__ == '__main__':
- import sys
- args = sys.argv[1:]
- if not args:
- sys.exit('usage: python %s dsn' % sys.argv[0])
- elif len(args) > 2:
- sys.exit('Unrecognized arguments: %s' % ' '.join(argv[2:]))
- main(*args)
diff --git a/clap/article/example4_.py b/clap/article/example4_.py
deleted file mode 100644
index 9ae2d46..0000000
--- a/clap/article/example4_.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from datetime import datetime
-
-def main(dsn, table='product', today=datetime.today()):
- "Do something on the database"
- print(dsn, table, today)
-
-if __name__ == '__main__':
- import clap; clap.call(main)
diff --git a/clap/article/example5.py b/clap/article/example5.py
deleted file mode 100644
index 59f88c7..0000000
--- a/clap/article/example5.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from datetime import datetime
-
-def main(dsn, today=datetime.today()):
- "Do something on the database"
- print(dsn, today)
-
-if __name__ == '__main__':
- import clap; clap.call(main)
diff --git a/clap/article/example6.py b/clap/article/example6.py
deleted file mode 100644
index 9c7b5fd..0000000
--- a/clap/article/example6.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from datetime import datetime
-
-def main(dsn, *scripts):
- "Run the given scripts on the database"
- for script in scripts:
- print('executing %s' % script)
-
-if __name__ == '__main__':
- import sys
- if len(sys.argv) < 2:
- sys.exit('usage: python %s dsn script.sql ...' % sys.argv[0])
- main(sys.argv[1:])
diff --git a/clap/article/example7.py b/clap/article/example7.py
deleted file mode 100644
index ab3f2f7..0000000
--- a/clap/article/example7.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from datetime import datetime
-
-def main(dsn, *scripts):
- "Run the given scripts on the database"
- for script in scripts:
- print('executing %s' % script)
-
-if __name__ == '__main__':
- import clap; clap.call(main)
diff --git a/clap/article/example8.py b/clap/article/example8.py
deleted file mode 100644
index 2f675f5..0000000
--- a/clap/article/example8.py
+++ /dev/null
@@ -1,7 +0,0 @@
-def main(command: ("SQL query", 'option', 'c'), dsn):
- if command:
- print('executing %s on %s' % (command, dsn))
- # ...
-
-if __name__ == '__main__':
- import clap; clap.call(main)
diff --git a/clap/article/example9.py b/clap/article/example9.py
deleted file mode 100644
index 6613345..0000000
--- a/clap/article/example9.py
+++ /dev/null
@@ -1,7 +0,0 @@
-def main(verbose: ('prints more info', 'flag', 'v'), dsn: 'connection string'):
- if verbose:
- print('connecting to %s' % dsn)
- # ...
-
-if __name__ == '__main__':
- import clap; clap.call(main)
diff --git a/clap/doc.html b/clap/doc.html
deleted file mode 100644
index 15a033d..0000000
--- a/clap/doc.html
+++ /dev/null
@@ -1,187 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!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" xml:lang="en" lang="en">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
-<title>clap: a simplified interface to optparse</title>
-<style type="text/css">
-
-.highlight { background: #f8f8f8; }
-.highlight .c { color: #408080; font-style: italic } /* Comment */
-.highlight .err { border: 1px solid #FF0000 } /* Error */
-.highlight .k { color: #008000; font-weight: bold } /* Keyword */
-.highlight .o { color: #666666 } /* Operator */
-.highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */
-.highlight .cp { color: #BC7A00 } /* Comment.Preproc */
-.highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */
-.highlight .cs { color: #408080; font-style: italic } /* Comment.Special */
-.highlight .gd { color: #A00000 } /* Generic.Deleted */
-.highlight .ge { font-style: italic } /* Generic.Emph */
-.highlight .gr { color: #FF0000 } /* Generic.Error */
-.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
-.highlight .gi { color: #00A000 } /* Generic.Inserted */
-.highlight .go { color: #808080 } /* Generic.Output */
-.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
-.highlight .gs { font-weight: bold } /* Generic.Strong */
-.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
-.highlight .gt { color: #0040D0 } /* Generic.Traceback */
-.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
-.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
-.highlight .kp { color: #008000 } /* Keyword.Pseudo */
-.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
-.highlight .kt { color: #008000; font-weight: bold } /* Keyword.Type */
-.highlight .m { color: #666666 } /* Literal.Number */
-.highlight .s { color: #BA2121 } /* Literal.String */
-.highlight .na { color: #7D9029 } /* Name.Attribute */
-.highlight .nb { color: #008000 } /* Name.Builtin */
-.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */
-.highlight .no { color: #880000 } /* Name.Constant */
-.highlight .nd { color: #AA22FF } /* Name.Decorator */
-.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
-.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
-.highlight .nf { color: #0000FF } /* Name.Function */
-.highlight .nl { color: #A0A000 } /* Name.Label */
-.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
-.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
-.highlight .nv { color: #19177C } /* Name.Variable */
-.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
-.highlight .w { color: #bbbbbb } /* Text.Whitespace */
-.highlight .mf { color: #666666 } /* Literal.Number.Float */
-.highlight .mh { color: #666666 } /* Literal.Number.Hex */
-.highlight .mi { color: #666666 } /* Literal.Number.Integer */
-.highlight .mo { color: #666666 } /* Literal.Number.Oct */
-.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */
-.highlight .sc { color: #BA2121 } /* Literal.String.Char */
-.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
-.highlight .s2 { color: #BA2121 } /* Literal.String.Double */
-.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
-.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */
-.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
-.highlight .sx { color: #008000 } /* Literal.String.Other */
-.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
-.highlight .s1 { color: #BA2121 } /* Literal.String.Single */
-.highlight .ss { color: #19177C } /* Literal.String.Symbol */
-.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */
-.highlight .vc { color: #19177C } /* Name.Variable.Class */
-.highlight .vg { color: #19177C } /* Name.Variable.Global */
-.highlight .vi { color: #19177C } /* Name.Variable.Instance */
-.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
-
-</style>
-</head>
-<body>
-<div class="document" id="clap-a-simplified-interface-to-optparse">
-<h1 class="title">clap: a simplified interface to optparse</h1>
-
-<p>The Python standard library contains three different modules for the
-parsing of command line options: <tt class="docutils literal">getopt</tt> (from the stone age),
-<tt class="docutils literal">optparse</tt> (from Python 2.3) and <tt class="docutils literal">argparse</tt> (from Python 2.7).
-There are therefore plenty of industrial strength ways of parsing
-the command line in Python; nevertheless, in my opinion, we a <em>simple</em>
-way is still missing.</p>
-<p>I see two classes of users for command line scripts: on one side there
-are programmers, sysadmins, scientists and in general people writing throw-away
-scripts for themselves, choosing to use a command line interface
-because it is the quick and simple; on the other side there are programmers
-writing power user tools for other programmers or system administrators.
-I strongly believe that 99.9% of the users of command line interfaces
-fit in the first category. Such users are
-not interested in features, they just want to be able to write a simple
-command line tool from a simple specification, not to build a command line
-parser by hand. Unfortunately, the current modules in the standard
-library forces them to go the hard way.</p>
-<p><tt class="docutils literal">clap</tt> solves this problem. By design it is not intended to
-be an industrial strength command line parsing module. Its capabilities
-are limited <em>on purpose</em>. If you need more power, by all means use the
-parsing modules in the standard library. Still, I have been using Python for 8
-years and never once I had to use the full power of <tt class="docutils literal">optparse</tt>: the
-features provided by <tt class="docutils literal">clap</tt> have been more than enough for
-me and I guess that the same could be said for most people.</p>
-<p>The fundamental idea behind <tt class="docutils literal">clap</tt> is to extract the parser
-from the usage docstring. In this way the user does not need to write
-the parser by hand by duplicating the instructions which she has already
-encoded implicitly in the usage docstring.</p>
-<p>Here is a concrete example of a script using <tt class="docutils literal">clap</tt>:</p>
-<pre class="literal-block">
-&quot;&quot;&quot;\
-usage: %prog [options]
--c, --color=black: set default color
--d, --delete=: delete the given file
--a, --delete-all: delete all files
-&quot;&quot;&quot;
-
-def print_(color, txt):
- code = {'black': 30, 'red': 31}[color]
- print '\x1b[%dm%s\x1b[0m' % (code, txt)
-
-if __name__=='__main__':
- from clap import OptionParser
- option, args = OptionParser(__doc__).parse_args()
- color = option.color
- if option.delete_all:
- print_(color, &quot;Delete all files&quot;)
- elif option.delete:
- print_(color, &quot;Delete the file %s&quot; % option.delete)
-
-</pre>
-<p>Here are a few examples of usage:</p>
-<pre class="literal-block">
-$ python example.py
-&lt;no output&gt;
-
-$ python example.py -h
-Usage: example.py [options]
-
-Options:
- -h, --help show this help message and exit
- -c COLOR, --color=COLOR
- set default color
- -d DELETE, --delete=DELETE
- delete the given file
- -a, --delete_all delete all files
-
-$ python example.py -d
-Usage: example.py [options]
-
-example.py: error: -d option requires an argument
-
-$ python example.py --delete x.txt
-Delete the file x.txt
-
-$ python example.py --delete-all
-Delete all files
-
-$ python example.py -a --color=red
-Delete all files # this is printed in red on most terminals
-
-
-</pre>
-<p>Here is some explanation. First of all, <tt class="docutils literal">clap</tt> recognizes
-four classes of command line arguments:</p>
-<ul class="simple">
-<li>positional arguments (none in this example)</li>
-<li>options with non-trivial defaults (<tt class="docutils literal">color=black</tt> in this example)</li>
-<li>options with null defaults (<tt class="docutils literal">delete=</tt> in this example)</li>
-<li>flags (<tt class="docutils literal"><span class="pre">delete-all</span></tt> in this example)</li>
-</ul>
-<p>You can have a generic number of positional arguments, including no
-arguments. An option with default can be set on the command line
-(for instance you can pass <tt class="docutils literal"><span class="pre">--color=red</span></tt>) or not; if not, the default
-value is used. An option with null default is a special case of
-option with a default, where the default value is the empty string.
-A flag is similar to an option with null default: if the
-flag is not passed its value is False, otherwise it is True.
-The difference with respect to a null default option is that
-the flag value is a boolean, not a string, and that the syntax
-is different (there is no <tt class="docutils literal">=</tt>).</p>
-<p>The <tt class="docutils literal">OptionParser.parse_args</tt> method
-parses the usage docstring by looking at the
-characters &quot;,&quot;, &quot;:&quot;, &quot;=&quot;, &quot;\n&quot;, so be careful when using them. If
-the docstring is not correctly formatted you will get a SyntaxError.</p>
-<p>Options with dashes inside the name, such as
-<tt class="docutils literal"><span class="pre">--delete-all</span></tt>, will be translated with underscore (<tt class="docutils literal">delete_all</tt>), since
-<tt class="docutils literal"><span class="pre">delete-all</span></tt> is not a valid Python identifier.</p>
-</div>
-</body>
-</html>
diff --git a/clap/doc.txt b/clap/doc.txt
deleted file mode 100644
index c84d8da..0000000
--- a/clap/doc.txt
+++ /dev/null
@@ -1,82 +0,0 @@
-clap: a simplified interface to optparse
--------------------------------------------------
-
-The Python standard library contains three different modules for the
-parsing of command line options: ``getopt`` (from the stone age),
-``optparse`` (from Python 2.3) and ``argparse`` (from Python 2.7).
-There are therefore plenty of industrial strength ways of parsing
-the command line in Python; nevertheless, in my opinion, we a *simple*
-way is still missing.
-
-I see two classes of users for command line scripts: on one side there
-are programmers, sysadmins, scientists and in general people writing throw-away
-scripts for themselves, choosing to use a command line interface
-because it is the quick and simple; on the other side there are programmers
-writing power user tools for other programmers or system administrators.
-I strongly believe that 99.9% of the users of command line interfaces
-fit in the first category. Such users are
-not interested in features, they just want to be able to write a simple
-command line tool from a simple specification, not to build a command line
-parser by hand. Unfortunately, the current modules in the standard
-library forces them to go the hard way.
-
-``clap`` solves this problem. By design it is not intended to
-be an industrial strength command line parsing module. Its capabilities
-are limited *on purpose*. If you need more power, by all means use the
-parsing modules in the standard library. Still, I have been using Python for 8
-years and never once I had to use the full power of ``optparse``: the
-features provided by ``clap`` have been more than enough for
-me and I guess that the same could be said for most people.
-
-The fundamental idea behind ``clap`` is to extract the parser
-from the usage docstring. In this way the user does not need to write
-the parser by hand by duplicating the instructions which she has already
-encoded implicitly in the usage docstring.
-
-Here is a concrete example of a script using ``clap``:
-
-.. include:: example.py
- :literal:
-
-Here are a few examples of usage:
-
-.. include:: example.txt
- :literal:
-
-Here are some explanations. First of all, ``clap`` recognizes
-four classes of command line arguments:
-
-- positional arguments (none in this example)
-- options with non-trivial defaults (``color=black`` in this example)
-- options with null defaults (``delete=`` in this example)
-- flags (``delete-all`` in this example)
-
-You can have a generic number of positional arguments, including no
-arguments. An option with default can be set on the command line
-(for instance you can pass ``--color=red``) or not; if not, the default
-value is used. An option with null default is a special case of
-option with a default, where the default value is the empty string.
-A flag is similar to an option with null default: if the
-flag is not passed its value is False, otherwise it is True.
-The difference with respect to a null default option is that
-the flag value is a boolean, not a string, and that the syntax
-is different (there is no ``=``).
-
-The ``OptionParser.parse_args`` method
-parses the usage docstring by looking at the
-characters ",", ":", "=", "\\n" (be careful when using them, if
-the docstring is not correctly formatted you will get a ``SyntaxError``).
-
-Options with dashes inside the name, such as
-``--delete-all``, are translated into with underscore (``delete_all``), since
-``delete-all`` is not a valid Python identifier.
-
-Limitations
-------------------------------------
-
-The default values cannot contain a ':' (or it should be escaped).
-
-
-.. Today I want to announce to the general public the birth of my latest
-.. project, which aims to be the easiest command line arguments
-.. parser in the Python world: clap_.
diff --git a/clap/example.py b/clap/example.py
deleted file mode 100644
index 69cc981..0000000
--- a/clap/example.py
+++ /dev/null
@@ -1,20 +0,0 @@
-"""\
-usage: %prog [options]
--c, --color=black: set default color
--d, --delete=: delete the given file
--a, --delete-all: delete all files
-"""
-from clap import OptionParser
-
-def print_(color, txt):
- code = {'black': 30, 'red': 31}[color]
- print '\x1b[%dm%s\x1b[0m' % (code, txt)
-
-if __name__=='__main__':
- opt = OptionParser(__doc__).parse_args()
- if not opt:
- OptionParser.exit()
- elif opt.delete_all:
- print_(opt.color, "Delete all files")
- elif opt.delete:
- print_(opt.color, "Delete the file %s" % opt.delete)
diff --git a/clap/example.txt b/clap/example.txt
deleted file mode 100644
index 4cf83ff..0000000
--- a/clap/example.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-$ python example.py
-usage: example.py [options]
--c, --color=black: set default color
--d, --delete=: delete the given file
--a, --delete-all: delete all files
-
-$ python example.py -h
-Usage: example.py [options]
-
-Options:
- -h, --help show this help message and exit
- -c COLOR, --color=COLOR
- set default color
- -d DELETE, --delete=DELETE
- delete the given file
- -a, --delete_all delete all files
-
-$ python example.py -d
-Usage: example.py [options]
-
-example.py: error: -d option requires an argument
-
-$ python example.py --delete x.txt
-Delete the file x.txt
-
-$ python example.py --delete-all
-Delete all files
-
-$ python example.py -a --color=red
-Delete all files # this is printed in red on most terminals
-
diff --git a/clap/README.txt b/plac/README.txt
index 06c9ce3..50ac30c 100644
--- a/clap/README.txt
+++ b/plac/README.txt
@@ -1,11 +1,11 @@
-clap, the easiest command line arguments parser in the world
+plac, the easiest command line arguments parser in the world
============================================================
:Author: Michele Simionato
:E-mail: michele.simionato@gmail.com
:Requires: Python 2.3+
-:Download page: http://pypi.python.org/pypi/clap
-:Installation: ``easy_install clap``
+:Download page: http://pypi.python.org/pypi/plac
+:Installation: ``easy_install plac``
:License: BSD license
Installation
@@ -13,7 +13,7 @@ Installation
If you are lazy, just perform
-$ easy_install clap
+$ easy_install plac
which will install just the module on your system. Notice that
Python 3 requires the easy_install version of the distribute_ project.
@@ -25,7 +25,7 @@ $ python setup.py install
in the main directory, possibly as superuser.
-.. _tarball: http://pypi.python.org/pypi/clap
+.. _tarball: http://pypi.python.org/pypi/plac
.. _distribute: http://packages.python.org/distribute/
Testing
@@ -33,20 +33,20 @@ Testing
Run
-$ python test_clap.py
+$ python test_plac.py
or
-$ nosetests test_clap
+$ nosetests test_plac
or
-$ py.test test_clap
+$ py.test test_plac
Documentation
--------------
You can choose between the `HTML version`_ and the `PDF version`_ .
-.. _HTML version: http://micheles.googlecode.com/hg/clap/documentation.html
-.. _PDF version: http://micheles.googlecode.com/hg/clap/documentation.pdf
+.. _HTML version: http://micheles.googlecode.com/hg/plac/doc/plac.html
+.. _PDF version: http://micheles.googlecode.com/hg/plac/doc/plac.pdf
diff --git a/clap/clap.py b/plac/plac.py
index 625092b..fdde35f 100644
--- a/clap/clap.py
+++ b/plac/plac.py
@@ -24,9 +24,11 @@
## DAMAGE.
"""
-clap, the easiest Command Line Arguments Parser in the world.
-See clap/doc.html for the documentation.
+plac, the easiest Command Line Arguments Parser in the world.
+See plac/doc.html for the documentation.
"""
+# this module should be kept Python 2.3 compatible
+
__version__ = '0.2.0'
import re, sys, inspect, argparse
@@ -82,7 +84,6 @@ class Annotation(object):
self.choices = choices
self.metavar = metavar
- @classmethod
def from_(cls, obj):
"Helper to convert an object into an annotation, if needed"
if is_annotation(obj):
@@ -90,14 +91,23 @@ class Annotation(object):
elif hasattr(obj, '__iter__') and not isinstance(obj, str):
return cls(*obj)
return cls(obj)
-
+ from_ = classmethod(from_)
+
NONE = object() # sentinel use to signal the absence of a default
valid_attrs = getfullargspec(argparse.ArgumentParser.__init__).args[1:]
def parser_from(func):
- # extract the ArgumentParser arguments from the attributes of func
- attrs = dict([(n, v) for n, v in vars(func).items() if n in valid_attrs])
+ """
+ Extract the arguments from the attributes of the passed function and
+ return an ArgumentParser instance.
+ """
+ short_prefix = getattr(func, 'short_prefix', '-')
+ long_prefix = getattr(func, 'long_prefix', '--')
+ attrs = {'description': func.__doc__}
+ for n, v in vars(func).items():
+ if n in valid_attrs:
+ attrs[n] = v
p = argparse.ArgumentParser(**attrs)
f = p.argspec = getfullargspec(func)
defaults = f.defaults or ()
@@ -106,20 +116,22 @@ def parser_from(func):
alldefaults = (NONE,) * (n_args - n_defaults) + defaults
for name, default in zip(f.args, alldefaults):
a = Annotation.from_(f.annotations.get(name, ()))
+ if default is NONE:
+ dflt, metavar = None, a.metavar
+ else:
+ dflt, metavar = default, a.metavar or str(default)
if a.kind in ('option', 'flag'):
- short = '-' + a.abbrev
- long = '--' + name
- elif default is NONE: # mandatory positional argument
+ short = short_prefix + a.abbrev
+ long = long_prefix + name
+ elif default is NONE: # required argument
p.add_argument(name, help=a.help, type=a.type, choices=a.choices,
- metavar=a.metavar)
- else: # regular default argument
- p.add_argument(name, nargs='?', help=a.help, default=default,
- type=a.type, choices=a.choices, metavar=a.metavar)
+ metavar=metavar)
+ else: # default argument
+ p.add_argument(name, nargs='?', help=a.help, default=dflt,
+ type=a.type, choices=a.choices, metavar=metavar)
if a.kind == 'option':
- if default is not NONE:
- raise TypeError('Option %r does not want a default' % name)
- p.add_argument(short, long, help=a.help, type=a.type,
- choices=a.choices, metavar=a.metavar)
+ p.add_argument(short, long, help=a.help, default=dflt,
+ type=a.type, choices=a.choices, metavar=metavar)
elif a.kind == 'flag':
if default is not NONE:
raise TypeError('Flag %r does not want a default' % name)
diff --git a/plac/setup.py b/plac/setup.py
new file mode 100644
index 0000000..ca34c5b
--- /dev/null
+++ b/plac/setup.py
@@ -0,0 +1,29 @@
+try:
+ from setuptools import setup
+except ImportError:
+ from distutils.core import setup
+import os.path
+import plac
+
+if __name__ == '__main__':
+ setup(name=plac.__name__,
+ version=plac.__version__,
+ description='The easiest command line arguments parser in the world',
+ long_description=open('README.txt').read(),
+ author='Michele Simionato',
+ author_email='michele.simionato@gmail.com',
+ url='http://pypi.python.org/pypi/plac',
+ license="BSD License",
+ py_modules = ['plac'],
+ install_requires=['argparse>=1.1'],
+ keywords="command line arguments parser",
+ platforms=["All"],
+ classifiers=['Development Status :: 3 - Alpha',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: BSD License',
+ 'Natural Language :: English',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python',
+ 'Topic :: Software Development :: Libraries',
+ 'Topic :: Utilities'],
+ zip_safe=False)
diff --git a/clap/test_clap.py b/plac/test_plac.py
index 04a313d..c961759 100644
--- a/clap/test_clap.py
+++ b/plac/test_plac.py
@@ -3,34 +3,36 @@ The tests are runnable with nose, with py.test, or even as standalone script
"""
import sys
-import clap3
+import plac
-def expect_exit(func, *args, **kw):
+def expect(errclass, func, *args, **kw):
try:
func(*args, **kw)
- except SystemExit:
+ except errclass:
pass
else:
- raise RuntimeError('SystemExit expected, got none!')
+ raise RuntimeError('%s expected, got none!', errclass.__name__)
-def f1(delete: "d: delete a file", args=()):
- pass
+def parser_from(f, **kw):
+ f.__annotations__ = kw
+ return plac.parser_from(f)
+
+p1 = parser_from(lambda delete, *args: None,
+ delete=('delete a file', 'option', 'd'))
def test_p1():
- p1 = clap3.parser_from(f1)
arg = p1.parse_args(['-d', 'foo', 'arg1', 'arg2'])
assert arg.delete == 'foo'
assert arg.args == ['arg1', 'arg2']
arg = p1.parse_args([])
assert arg.delete is None, arg.delete
- assert arg.args is (), arg.args
+ assert arg.args == [], arg.args
-def f2(arg1, delete: "d: delete a file", args=()):
- pass
+p2 = parser_from(lambda arg1, delete, *args: None,
+ delete=('delete a file', 'option', 'd'))
def test_p2():
- p2 = clap3.parser_from(f2)
arg = p2.parse_args(['-d', 'foo', 'arg1', 'arg2'])
assert arg.delete == 'foo', arg.delete
assert arg.arg1 == 'arg1', arg.arg1
@@ -38,30 +40,29 @@ def test_p2():
arg = p2.parse_args(['arg1'])
assert arg.delete is None, arg.delete
- assert arg.args is (), arg.args
+ assert arg.args == [], arg.args
assert arg, arg
- expect_exit(p2.parse_args, [])
+ expect(SystemExit, p2.parse_args, [])
+
-def f3(arg1, delete: "d: delete a file"):
- pass
+p3 = parser_from(lambda arg1, delete: None,
+ delete=('delete a file', 'option', 'd'))
def test_p3():
- p3 = clap3.parser_from(f3)
arg = p3.parse_args(['arg1'])
assert arg.delete is None, arg.delete
assert arg.arg1 == 'arg1', arg.args
- expect_exit(p3.parse_args, ['arg1', 'arg2'])
- expect_exit(p3.parse_args, [])
+ expect(SystemExit, p3.parse_args, ['arg1', 'arg2'])
+ expect(SystemExit, p3.parse_args, [])
-def f4(delete: "d: delete a file",
- delete_all: "a, delete all files",
- color: "c: set default color"="black"):
- pass
+p4 = parser_from(lambda delete, delete_all, color="black": None,
+ delete=('delete a file', 'option', 'd'),
+ delete_all=('delete all files', 'flag', 'a'),
+ color=('color', 'option', 'c'))
def test_p4():
- p4 = clap3.parser_from(f4)
arg = p4.parse_args(['-a'])
assert arg.delete_all is True, arg.delete_all
@@ -73,11 +74,15 @@ def test_p4():
arg = p4.parse_args(['--color=red'])
assert arg.color == 'red'
+def test_flag_with_default():
+ expect(TypeError, parser_from, lambda yes_or_no='no': None,
+ yes_or_no=('A yes/no flag', 'flag', 'f'))
+
if __name__ == '__main__':
n = 0
- for name, test in list(globals().items()):
+ for name, test in sorted(globals().items()):
if name.startswith('test_'):
- print('Running', name)
+ print('Running ' + name)
test()
n +=1
print('Executed %d tests OK' % n)