summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plac/MANIFEST.in2
-rw-r--r--plac/doc/example1.py1
-rw-r--r--plac/doc/example2.py1
-rw-r--r--plac/doc/example3.py1
-rw-r--r--plac/doc/example4_.py9
-rw-r--r--plac/doc/example5.py4
-rw-r--r--plac/doc/example6.py1
-rw-r--r--plac/doc/example7.py2
-rw-r--r--plac/doc/example8_.py2
-rw-r--r--plac/doc/plac.html338
-rw-r--r--plac/doc/plac.pdf3562
-rw-r--r--plac/doc/plac.txt309
-rw-r--r--plac/plac.py2
-rw-r--r--plac/test_plac.py1
14 files changed, 2202 insertions, 2033 deletions
diff --git a/plac/MANIFEST.in b/plac/MANIFEST.in
index c480a35..1075e92 100644
--- a/plac/MANIFEST.in
+++ b/plac/MANIFEST.in
@@ -1 +1 @@
-include doc/*.py doc/*.txt doc/*.html doc/*.pdf
+include test_plac.py *.txt doc/*.py doc/*.txt doc/*.html doc/*.pdf
diff --git a/plac/doc/example1.py b/plac/doc/example1.py
index 8d5fe7a..a5071bb 100644
--- a/plac/doc/example1.py
+++ b/plac/doc/example1.py
@@ -2,6 +2,7 @@
def main(dsn):
"Do something with the database"
print(dsn)
+ # ...
if __name__ == '__main__':
import sys
diff --git a/plac/doc/example2.py b/plac/doc/example2.py
index 74a4a01..56aa23c 100644
--- a/plac/doc/example2.py
+++ b/plac/doc/example2.py
@@ -2,6 +2,7 @@
def main(dsn):
"Do something on the database"
print(dsn)
+ # ...
if __name__ == '__main__':
import argparse
diff --git a/plac/doc/example3.py b/plac/doc/example3.py
index adfbed6..979b1a4 100644
--- a/plac/doc/example3.py
+++ b/plac/doc/example3.py
@@ -2,6 +2,7 @@
def main(dsn):
"Do something with the database"
print(dsn)
+ # ...
if __name__ == '__main__':
import plac; plac.call(main)
diff --git a/plac/doc/example4_.py b/plac/doc/example4_.py
deleted file mode 100644
index c2c92da..0000000
--- a/plac/doc/example4_.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# example4_.py
-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 plac; plac.call(main)
diff --git a/plac/doc/example5.py b/plac/doc/example5.py
index 1da6153..30c1d87 100644
--- a/plac/doc/example5.py
+++ b/plac/doc/example5.py
@@ -1,9 +1,9 @@
# example5.py
from datetime import datetime
-def main(dsn, today=datetime.today()):
+def main(dsn, table='product', today=datetime.today()):
"Do something on the database"
- print(dsn, today)
+ print(dsn, table, today)
if __name__ == '__main__':
import plac; plac.call(main)
diff --git a/plac/doc/example6.py b/plac/doc/example6.py
index a68075f..5586c03 100644
--- a/plac/doc/example6.py
+++ b/plac/doc/example6.py
@@ -5,6 +5,7 @@ def main(dsn, *scripts):
"Run the given scripts on the database"
for script in scripts:
print('executing %s' % script)
+ # ...
if __name__ == '__main__':
import sys
diff --git a/plac/doc/example7.py b/plac/doc/example7.py
index 541c4ac..475799d 100644
--- a/plac/doc/example7.py
+++ b/plac/doc/example7.py
@@ -1,11 +1,11 @@
# example7.py
-
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 plac; plac.call(main)
diff --git a/plac/doc/example8_.py b/plac/doc/example8_.py
index 33ae359..20f6df0 100644
--- a/plac/doc/example8_.py
+++ b/plac/doc/example8_.py
@@ -3,4 +3,4 @@ def main(dsn, command: ("SQL query", 'option', 'c')='select * from table'):
print('executing %r on %s' % (command, dsn))
if __name__ == '__main__':
- import clap; clap.call(main)
+ import plac; plac.call(main)
diff --git a/plac/doc/plac.html b/plac/doc/plac.html
index 9d90470..b415a4f 100644
--- a/plac/doc/plac.html
+++ b/plac/doc/plac.html
@@ -4,7 +4,7 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
-<title>Parsing the Command Line the Easy Way: Introducing plac, the EasiestArgument Parser in the Python World</title>
+<title>Parsing the Command Line the Easy Way: Introducing plac, the Easiest Argument Parser in the Python World</title>
<meta name="author" content="Michele Simionato" />
<style type="text/css">
@@ -412,8 +412,8 @@ h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
</style>
</head>
<body>
-<div class="document" id="parsing-the-command-line-the-easy-way-introducing-plac-the-easiestargument-parser-in-the-python-world">
-<h1 class="title">Parsing the Command Line the Easy Way: Introducing plac, the EasiestArgument Parser in the Python World</h1>
+<div class="document" id="parsing-the-command-line-the-easy-way-introducing-plac-the-easiest-argument-parser-in-the-python-world">
+<h1 class="title">Parsing the Command Line the Easy Way: Introducing plac, the Easiest Argument Parser in the Python World</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
@@ -426,6 +426,8 @@ h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
</tr>
<tr class="field"><th class="docinfo-name">Download page:</th><td class="field-body"><a class="reference external" href="http://pypi.python.org/pypi/plac">http://pypi.python.org/pypi/plac</a></td>
</tr>
+<tr class="field"><th class="docinfo-name">Project page:</th><td class="field-body"><a class="reference external" href="http://micheles.googlecode.com/hg/plac/doc/plac.html">http://micheles.googlecode.com/hg/plac/doc/plac.html</a></td>
+</tr>
<tr class="field"><th class="docinfo-name">Installation:</th><td class="field-body"><tt class="docutils literal">easy_install plac</tt></td>
</tr>
<tr class="field"><th class="docinfo-name">License:</th><td class="field-body">BSD license</td>
@@ -436,17 +438,18 @@ h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
<p class="topic-title first">Contents</p>
<ul class="simple">
<li><a class="reference internal" href="#the-importance-of-scaling-down" id="id1">The importance of scaling down</a></li>
-<li><a class="reference internal" href="#scripts-with-required-positional-arguments" id="id2">Scripts with required positional arguments</a></li>
-<li><a class="reference internal" href="#scritps-with-default-arguments" id="id3">Scritps with default arguments</a></li>
-<li><a class="reference internal" href="#options-and-flags" id="id4">Options and flags</a></li>
-<li><a class="reference internal" href="#plac-for-python-2-x-users" id="id5">plac for Python 2.X users</a></li>
-<li><a class="reference internal" href="#more-features" id="id6">More features</a></li>
-<li><a class="reference internal" href="#a-somewhat-realistic-example" id="id7">A somewhat realistic example</a></li>
-<li><a class="reference internal" href="#a-few-notes-about-the-underlying-implementation" id="id8">A few notes about the underlying implementation</a></li>
-<li><a class="reference internal" href="#custom-annotation-objects" id="id9">Custom annotation objects</a></li>
-<li><a class="reference internal" href="#plac-vs-argparse" id="id10">plac vs argparse</a></li>
-<li><a class="reference internal" href="#the-future" id="id11">The future</a></li>
-<li><a class="reference internal" href="#trivia-the-story-behind-the-name" id="id12">Trivia: the story behind the name</a></li>
+<li><a class="reference internal" href="#scripts-with-required-arguments" id="id2">Scripts with required arguments</a></li>
+<li><a class="reference internal" href="#scripts-with-default-arguments" id="id3">Scripts with default arguments</a></li>
+<li><a class="reference internal" href="#scripts-with-options" id="id4">Scripts with options</a></li>
+<li><a class="reference internal" href="#scripts-with-flags" id="id5">Scripts with flags</a></li>
+<li><a class="reference internal" href="#plac-for-python-2-x-users" id="id6">plac for Python 2.X users</a></li>
+<li><a class="reference internal" href="#more-features" id="id7">More features</a></li>
+<li><a class="reference internal" href="#a-more-realistic-example" id="id8">A more realistic example</a></li>
+<li><a class="reference internal" href="#advanced-usage" id="id9">Advanced usage</a></li>
+<li><a class="reference internal" href="#custom-annotation-objects" id="id10">Custom annotation objects</a></li>
+<li><a class="reference internal" href="#plac-vs-argparse" id="id11">plac vs argparse</a></li>
+<li><a class="reference internal" href="#the-future" id="id12">The future</a></li>
+<li><a class="reference internal" href="#trivia-the-story-behind-the-name" id="id13">Trivia: the story behind the name</a></li>
</ul>
</div>
<div class="section" id="the-importance-of-scaling-down">
@@ -457,52 +460,55 @@ world. The standard library alone contains three different modules:
<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; unfortunately, all of them feature a non-zero learning
-curve and a certain verbosity.</p>
-<p>An ex-coworker 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. This is an old meme in the computing world:
-programs should address the common cases simply, simple things should
-be kept simple, while at the same keeping difficult things
-possible. <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> adhere as much as possible to this philosophy and it
-is designed to handle well the simple cases, while retaining the
-ability to handle complex cases by relying on the underlying power of
-<a class="reference external" href="http://argparse.googlecode.com">argparse</a>.</p>
-<p>Technically <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> is just a simple wrapper over <a class="reference external" href="http://argparse.googlecode.com">argparse</a>, hiding most
-of its complexity while retaining most of its power. The complexity is
-removed by using a declarative interface instead of an imperative one.
-Still, <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> is surprisingly scalable upwards, even without
-using the underlying <a class="reference external" href="http://argparse.googlecode.com">argparse</a>. I have been using Python for
-8 years and in my experience it is extremely unlikely that you will
-ever need to go beyond the features provided by the declarative interface
-of <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a>: they should be more than enough for 99.9% of the typical use cases.</p>
-<p><a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> is targetting 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 are interested in a small
-learning curve: 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 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>
+curve and a certain verbosity. They do not scale down well enough, at
+least in my opinion.</p>
+<p>It should not be necessary to stress the importance <a class="reference external" href="http://www.welton.it/articles/scalable_systems">scaling down</a>;
+nevertheless most people are obsessed with features and concerned with
+the possibility of scaling up, whereas I think that we should be even
+more concerned with the issue of scaling down. This is an old meme in
+the computing world: programs should address the common cases simply,
+simple things should be kept simple, while at the same keeping
+difficult things possible. <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> adhere as much as possible to this
+philosophy and it is designed to handle well the simple cases, while
+retaining the ability to handle complex cases by relying on the
+underlying power of <a class="reference external" href="http://argparse.googlecode.com">argparse</a>.</p>
+<p>Technically <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> is just a simple wrapper over <a class="reference external" href="http://argparse.googlecode.com">argparse</a> which hides
+most of its complexity by using a declarative interface: the argument
+parser is inferred rather than written down by imperatively. Still, <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> is
+surprisingly scalable upwards, even without using the underlying
+<a class="reference external" href="http://argparse.googlecode.com">argparse</a>. I have been using Python for 8 years and in my experience
+it is extremely unlikely that you will ever need to go beyond the
+features provided by the declarative interface of <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a>: they should
+be more than enough for 99.9% of the use cases.</p>
+<p><a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> is targetting especially unsophisticated users,
+programmers, sys-admins, scientists and in general people writing
+throw-away scripts for themselves, choosing the command line
+interface because it is the quick and simple. Such users are not
+interested in features, they are interested in a small learning curve:
+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 modules in the standard library forces them
+to go the hard way. They are designed to implement power user tools
+and they have a non-trivial learning curve. On the contrary, <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a>
+is designed to be simple to use and extremely concise, as the examples
+below will show.</p>
</div>
-<div class="section" id="scripts-with-required-positional-arguments">
-<h1><a class="toc-backref" href="#id2">Scripts with required positional arguments</a></h1>
+<div class="section" id="scripts-with-required-arguments">
+<h1><a class="toc-backref" href="#id2">Scripts with required arguments</a></h1>
<p>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
+single argument and does something to it. It cannot get simpler
+than that, unless you consider a script without command line
+arguments, where there is nothing to parse. Still, it is a use
case <em>extremely common</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 of code I have been
writing by hand for years:</p>
-<blockquote>
<pre class="literal-block">
# example1.py
def main(dsn):
&quot;Do something with the database&quot;
print(dsn)
+ # ...
if __name__ == '__main__':
import sys
@@ -515,26 +521,24 @@ if __name__ == '__main__':
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 (nine lines) is
-essentially boilerplate that should not exists. Actually I think the
-Python language should recognize the main function and pass to it the
-command line arguments behind the scenes; unfortunaly this is unlikely to
+<p>As you see the whole <tt class="docutils literal">if __name__ == '__main__'</tt> block (nine lines)
+is essentially boilerplate that should not exists. Actually I think
+the language should recognize the main function and pass to it the
+command line arguments automatically; unfortunaly this is unlikely to
happen. I have been writing boilerplate like this in hundreds of
scripts for years, and every time I <em>hate</em> it. The purpose of using a
scripting language is convenience and trivial things should be
-trivial. Unfortunately the standard library does 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 nine
-lines to six lines:</p>
-<blockquote>
+trivial. Unfortunately the standard library does not help for this
+incredibly common use case. 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 nine lines to six lines:</p>
<pre class="literal-block">
# example2.py
def main(dsn):
&quot;Do something on the database&quot;
print(dsn)
+ # ...
if __name__ == '__main__':
import argparse
@@ -544,27 +548,25 @@ if __name__ == '__main__':
main(arg.dsn)
</pre>
-</blockquote>
<p>However saving three lines does not justify introducing the external
-dependency: most people will not switch Python 2.7, which at the time of
+dependency: most people will not switch to 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.</p>
<p>The <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> 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
<a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> module all you need to write is</p>
-<blockquote>
<pre class="literal-block">
# example3.py
def main(dsn):
&quot;Do something with the database&quot;
print(dsn)
+ # ...
if __name__ == '__main__':
import plac; plac.call(main)
</pre>
-</blockquote>
<p>The <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> module provides for free (actually the work is done by the
underlying <a class="reference external" href="http://argparse.googlecode.com">argparse</a> module) a nice usage message:</p>
<pre class="literal-block">
@@ -579,10 +581,11 @@ optional arguments:
</pre>
<p>This is only the tip of the iceberg: <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> is able to do much more than that.</p>
</div>
-<div class="section" id="scritps-with-default-arguments">
-<h1><a class="toc-backref" href="#id3">Scritps with default arguments</a></h1>
-<p>I have encountered this use case at work hundreds of times:</p>
-<blockquote>
+<div class="section" id="scripts-with-default-arguments">
+<h1><a class="toc-backref" href="#id3">Scripts with default arguments</a></h1>
+<p>The need to have suitable defaults for command line arguments is quite
+common. For instance I have encountered this use case at work hundreds
+of times:</p>
<pre class="literal-block">
# example4.py
from datetime import datetime
@@ -601,16 +604,21 @@ if __name__ == '__main__':
main(*args)
</pre>
-</blockquote>
-<p>With <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> the entire <tt class="docutils literal">__main__</tt> block reduces to the usual two lines:</p>
+<p>Here I want to perform a query on a database table, by extracting the
+today's data: it makes sense for <tt class="docutils literal">today</tt> to be a default argument.
+If there is a most used table (in this example a table called <tt class="docutils literal">'product'</tt>)
+it also makes sense to make it a default argument. Performing the parsing
+of the command lines arguments by hand takes 8 ugly lines of boilerplate
+(using <a class="reference external" href="http://argparse.googlecode.com">argparse</a> would require about the same number of lines).
+With <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> the entire <tt class="docutils literal">__main__</tt> block reduces to the usual two lines:</p>
<pre class="literal-block">
if __name__ == '__main__':
import plac; plac.call(main)
</pre>
-<p>In other words, six lines of boilerplate have been removed, and I have
+<p>In other words, six lines of boilerplate have been removed, and we get
the usage message for free:</p>
<pre class="literal-block">
-usage: example4_.py [-h] dsn [table] [today]
+usage: example5.py [-h] dsn [table] [today]
positional arguments:
dsn
@@ -623,7 +631,6 @@ optional arguments:
<p><a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> 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:</p>
-<blockquote>
<pre class="literal-block">
# example6.py
from datetime import datetime
@@ -632,6 +639,7 @@ def main(dsn, *scripts):
&quot;Run the given scripts on the database&quot;
for script in scripts:
print('executing %s' % script)
+ # ...
if __name__ == '__main__':
import sys
@@ -640,10 +648,9 @@ if __name__ == '__main__':
main(sys.argv[1:])
</pre>
-</blockquote>
<p>Using <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a>, you can just replace the <tt class="docutils literal">__main__</tt> block with the
usual two lines (I have defined an Emacs keybinding for them)
-and you get the following usage message:</p>
+and then you get the following nice usage message:</p>
<pre class="literal-block">
usage: example7.py [-h] dsn [scripts [scripts ...]]
@@ -656,22 +663,21 @@ optional arguments:
</pre>
<p>The examples here should have made clear that <em>plac is able to figure out
the command line arguments parser to use from the signature of the main
-function</em>. This is the whole idea behind <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a>: if my intent is clear,
+function</em>. This is the whole idea behind <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a>: if the intent is clear,
let's the machine take care of the details.</p>
</div>
-<div class="section" id="options-and-flags">
-<h1><a class="toc-backref" href="#id4">Options and flags</a></h1>
+<div class="section" id="scripts-with-options">
+<h1><a class="toc-backref" href="#id4">Scripts with options</a></h1>
<p>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 have written (certainly
-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>. Alternatively, in the simplest
-cases, I have just performed the parsing by hand, instead of manually
-building a suitable <a class="reference external" href="http://docs.python.org/library/optparse.html?highlight=optionparser#optparse.OptionParser">OptionParser</a>.</p>
+number of scripts with positional arguments I wrote (certainly more
+than a thousand of them). Still, this use case 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>. Alternatively, in the simplest cases, I have just
+performed the parsing by hand.</p>
<p><a class="reference external" href="http://pypi.python.org/pypi/plac">plac</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, but is
less of a hack: instead of extracting the parser from the docstring of
@@ -680,7 +686,6 @@ function.</p>
<p>The idea comes from 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">
# example8.py
def main(command: (&quot;SQL query&quot;, 'option', 'c'), dsn):
@@ -692,16 +697,14 @@ if __name__ == '__main__':
import plac; plac.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;, 'option', 'c')</tt>: the first string is the
-help string which will appear in the usage message, whereas the
-second and third strings tell <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</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, the long option
-format (<tt class="docutils literal"><span class="pre">--command=</span></tt>) comes from the argument name.
-The resulting usage message is the following:</p>
+<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;, 'option', 'c')</tt>: the first string is the help string
+which will appear in the usage message, the second string tell <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a>
+that <tt class="docutils literal">command</tt> is an option and the third string that it can be
+abbreviated with the letter <tt class="docutils literal">c</tt>. Of course, the long option format
+(<tt class="docutils literal"><span class="pre">--command=</span></tt>) comes from the argument name. 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:
@@ -723,21 +726,19 @@ executing select * from table on dsn
<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>. It is possible to specify a non-trivial
default for an option. Here is an example:</p>
-<blockquote>
<pre class="literal-block">
# example8_.py
def main(dsn, command: (&quot;SQL query&quot;, 'option', 'c')='select * from table'):
print('executing %r on %s' % (command, dsn))
if __name__ == '__main__':
- import clap; clap.call(main)
+ import plac; plac.call(main)
</pre>
-</blockquote>
<p>Now if you do not pass the <tt class="docutils literal">command option</tt>, the
default query will be executed:</p>
<pre class="literal-block">
-$ python article/example8_.py dsn
+$ python example8_.py dsn
executing 'select * from table' on dsn
</pre>
<p>Positional argument can be annotated too:</p>
@@ -752,24 +753,37 @@ smart enough to convert help messages into tuples; in other words, you
can just write <tt class="docutils literal">&quot;Database dsn&quot;</tt> instead of <tt class="docutils literal">(&quot;Database dsn&quot;,
'positional', None)</tt>. In both cases the usage message 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>
+argument.</p>
+<p>I should also notice that varargs (starred-arguments) can be annotated too;
+here is an example:</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://pypi.python.org/pypi/plac">plac</a>, which will recognize the help strings
+<p>This is a valid signature for <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a>, which will recognize the help strings
for both <tt class="docutils literal">dsn</tt> and <tt class="docutils literal">scripts</tt>:</p>
<pre class="literal-block">
positional arguments:
dsn Database dsn
scripts SQL scripts
</pre>
+</div>
+<div class="section" id="scripts-with-flags">
+<h1><a class="toc-backref" href="#id5">Scripts with flags</a></h1>
<p><a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> also recognizes flags, i.e. boolean options which are
<tt class="docutils literal">True</tt> if they are passed to the command line and <tt class="docutils literal">False</tt>
if they are absent. Here is an example:</p>
<pre class="literal-block">
-$ python3 example9.py -v dsn
-connecting to dsn
+# example9.py
+
+def main(verbose: ('prints more info', 'flag', 'v'), dsn: 'connection string'):
+ if verbose:
+ print('connecting to %s' % dsn)
+ # ...
+
+if __name__ == '__main__':
+ import plac; plac.call(main)
+
</pre>
<pre class="literal-block">
$ python3 example9.py -h
@@ -782,6 +796,10 @@ optional arguments:
-h, --help show this help message and exit
-v, --verbose prints more info
</pre>
+<pre class="literal-block">
+$ python3 example9.py -v dsn
+connecting to dsn
+</pre>
<p>Notice that it is an error trying to specify a default for flags: the
default value for a flag is always <tt class="docutils literal">False</tt>. If you feel the need to
implement non-boolean flags, you should use an option with two
@@ -792,34 +810,35 @@ the <tt class="docutils literal">main</tt> function write first the flag argumen
arguments, then the required arguments and finally the default
arguments. This is just a convention and you are not forced to use it,
except for the default arguments (including the varargs) which must
-stay at the end since it is required by the Python syntax.</p>
+stay at the end as it is required by the Python syntax.</p>
</div>
<div class="section" id="plac-for-python-2-x-users">
-<h1><a class="toc-backref" href="#id5">plac for Python 2.X users</a></h1>
+<h1><a class="toc-backref" href="#id6">plac for Python 2.X users</a></h1>
<p>I do not use Python 3. At work we are just starting to think about
-migrating to Python 2.6. It will take years before we even
+migrating to Python 2.6. It will take years before we
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://pypi.python.org/pypi/plac">plac</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>
+by hand. For instance the annotate function declaration</p>
<pre class="literal-block">
def main(dsn: &quot;Database dsn&quot;, *scripts: &quot;SQL scripts&quot;):
+ ...
</pre>
-<p>becomes:</p>
+<p>is equivalent to the following code:</p>
<pre class="literal-block">
def main(dsn, *scripts):
...
main.__annotations__ = dict(
-dsn=&quot;Database dsn&quot;,
-scripts=&quot;SQL scripts&quot;)
+ dsn=&quot;Database dsn&quot;,
+ scripts=&quot;SQL scripts&quot;)
</pre>
-<p>One should be careful to much the keys of the annotations dictionary
+<p>One should be careful to match the keys of the annotation 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">plac.annotations</tt> decorator that performs the check for you.</p>
+<tt class="docutils literal">plac.annotations</tt> decorator that performs the check for you:</p>
<pre class="literal-block">
-&#64;annotations(
+&#64;plac.annotations(
dsn=&quot;Database dsn&quot;,
scripts=&quot;SQL scripts&quot;)
def main(dsn, *scripts):
@@ -827,33 +846,34 @@ def main(dsn, *scripts):
</pre>
<p>In the rest of this article I will assume that you are using Python 2.X with
<tt class="docutils literal">X &gt;= 4</tt> and I will use the <tt class="docutils literal">plac.annotations</tt> decorator. Notice however
-that the tests for <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> are supposed to run even with Python 2.3.</p>
+that the tests for <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> runs even on Python 2.3.</p>
</div>
<div class="section" id="more-features">
-<h1><a class="toc-backref" href="#id6">More features</a></h1>
-<p>One of the goals of plac 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 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://pypi.python.org/pypi/plac">plac</a>.
-Until now, I have only showed simple annotations, but in general
-an annotation is a 5-tuple of the form</p>
+<h1><a class="toc-backref" href="#id7">More features</a></h1>
+<p>Even if one of the goals of plac 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>, it does not mean that I have removed all the 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://pypi.python.org/pypi/plac">plac</a>. Until
+now, I have only showed simple annotations, but in general an
+annotation is a 5-tuple of the form</p>
<blockquote>
<tt class="docutils literal">(help, kind, abbrev, type, choices, metavar)</tt></blockquote>
-<p>where <tt class="docutils literal">help</tt> is the help message, <tt class="docutils literal">kind</tt> is one of {&quot;flag&quot;,
-&quot;option &quot;, &quot;positional&quot;}, <tt class="docutils literal">abbrev</tt> is a one-character string,
-<tt class="docutils literal">type</tt> is callable taking a string in input, choices is a sequence
-of values and <tt class="docutils literal">metavar</tt> is a string.</p>
-<p><tt class="docutils literal">type</tt> is used to automagically convert the arguments from string
-to any Python type; by default there is no convertion i.e. <tt class="docutils literal">type=None</tt>.</p>
+<p>where <tt class="docutils literal">help</tt> is the help message, <tt class="docutils literal">kind</tt> is a string in the set {
+<tt class="docutils literal">&quot;flag&quot;</tt>, <tt class="docutils literal">&quot;option&quot;</tt>, <tt class="docutils literal">&quot;positional&quot;</tt>}, <tt class="docutils literal">abbrev</tt> is a
+one-character string, <tt class="docutils literal">type</tt> is a callable taking a string in input,
+<tt class="docutils literal">choices</tt> is a discrete sequence of values and <tt class="docutils literal">metavar</tt> is a string.</p>
+<p><tt class="docutils literal">type</tt> is used to automagically convert the command line arguments
+from the string type to any Python type; by default there is no
+convertion and <tt class="docutils literal">type=None</tt>.</p>
<p><tt class="docutils literal">choices</tt> is used to restrict the number of the valid
options; by default there is no restriction i.e. <tt class="docutils literal">choices=None</tt>.</p>
<p><tt class="docutils literal">metavar</tt> 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, unless the argument has a default and in such a case is
+(and only there); by default the metavar is <tt class="docutils literal">None</tt>: this means that
+the name in the usage message is the same as the argument name,
+unless the argument has a default and in such a case is
equal to the stringified form of the default.</p>
-<p>Here is an example showing many of the features (shamelessly stolen
-from the <a class="reference external" href="http://argparse.googlecode.com">argparse</a> documentation):</p>
-<blockquote>
+<p>Here is an example showing many of the features (taken from the
+<a class="reference external" href="http://argparse.googlecode.com">argparse</a> documentation):</p>
<pre class="literal-block">
# example10.py
import plac
@@ -873,8 +893,7 @@ if __name__ == '__main__':
plac.call(main)
</pre>
-</blockquote>
-<p>Here is the usage for the script:</p>
+<p>Here is the usage:</p>
<pre class="literal-block">
usage: example10.py [-h] {add,mul} [n [n ...]]
@@ -899,13 +918,12 @@ usage: example10.py [-h] {add,mul} [n [n ...]]
example10.py: error: argument operator: invalid choice: 'ad' (choose from 'add', 'mul')
</pre>
</div>
-<div class="section" id="a-somewhat-realistic-example">
-<h1><a class="toc-backref" href="#id7">A somewhat realistic example</a></h1>
+<div class="section" id="a-more-realistic-example">
+<h1><a class="toc-backref" href="#id8">A more realistic example</a></h1>
<p>Here is a more realistic script using most of the features of <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> to
run SQL queries on a database by relying on <a class="reference external" href="http://www.sqlalchemy.org/">SQLAlchemy</a>. Notice the usage
of the <tt class="docutils literal">type</tt> feature to automagically convert a SQLAlchemy connection
string into a <a class="reference external" href="http://www.sqlalchemy.org/docs/reference/ext/sqlsoup.html">SqlSoup</a> object:</p>
-<blockquote>
<pre class="literal-block">
# dbcli.py
import plac
@@ -935,10 +953,9 @@ if __name__ == '__main__':
plac.call(main)
</pre>
-</blockquote>
<p>Here is the usage message:</p>
<pre class="literal-block">
-$ python article/dbcli.py -h
+$ python dbcli.py -h
usage: dbcli.py [-h] [-H] [-c SQL] [-d |] db [scripts [scripts ...]]
A script to run queries and SQL scripts on a database
@@ -954,8 +971,8 @@ optional arguments:
-d |, --delimiter | Column separator
</pre>
</div>
-<div class="section" id="a-few-notes-about-the-underlying-implementation">
-<h1><a class="toc-backref" href="#id8">A few notes about the underlying implementation</a></h1>
+<div class="section" id="advanced-usage">
+<h1><a class="toc-backref" href="#id9">Advanced usage</a></h1>
<p><a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> relies on a <a class="reference external" href="http://argparse.googlecode.com">argparse</a> for all of the heavy lifting work and it is
possible to leverage on <a class="reference external" href="http://argparse.googlecode.com">argparse</a> features directly or indirectly.</p>
<p>For instance, you can make invisible an argument in the usage message
@@ -990,7 +1007,7 @@ main.short_prefix = '/'
</pre>
<p>The recognition of the <tt class="docutils literal">short_prefix</tt> attribute is a <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a>
extension; there is also a companion <tt class="docutils literal">long_prefix</tt> attribute with
-default value of <tt class="docutils literal"><span class="pre">--</span></tt>. <tt class="docutils literal">prefix_chars</tt> is an <a class="reference external" href="http://argparse.googlecode.com">argparse</a> feature.
+default value of <tt class="docutils literal"><span class="pre">&quot;--&quot;</span></tt>. <tt class="docutils literal">prefix_chars</tt> is an <a class="reference external" href="http://argparse.googlecode.com">argparse</a> feature.
Interested readers should read the documentation of <a class="reference external" href="http://argparse.googlecode.com">argparse</a> to
understand the meaning of the other options. If there is a set of
options that you use very often, you may consider writing a decorator
@@ -1012,14 +1029,13 @@ add_help=True)
users should never need to use it.</p>
</div>
<div class="section" id="custom-annotation-objects">
-<h1><a class="toc-backref" href="#id9">Custom annotation objects</a></h1>
+<h1><a class="toc-backref" href="#id10">Custom annotation objects</a></h1>
<p>Internally <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> uses an <tt class="docutils literal">Annotation</tt> class to convert the tuples
in the function signature into annotation objects, i.e. objects with
six attributes <tt class="docutils literal">help, kind, short, type, choices, metavar</tt>.</p>
<p>Advanced users can implement their own annotation objects.
For instance, here is an example of how you could implement annotations for
positional arguments:</p>
-<blockquote>
<pre class="literal-block">
# annotations.py
class Positional(object):
@@ -1032,9 +1048,7 @@ class Positional(object):
self.metavar = metavar
</pre>
-</blockquote>
<p>You can use such annotations objects as follows:</p>
-<blockquote>
<pre class="literal-block">
# example11.py
import plac
@@ -1051,7 +1065,6 @@ if __name__ == '__main__':
import plac; plac.call(main)
</pre>
-</blockquote>
<p>Here is the usage message you get:</p>
<pre class="literal-block">
usage: example11.py [-h] i n [rest [rest ...]]
@@ -1071,11 +1084,11 @@ use cases to be quite rare: the default mechanism should work
pretty well for most users.</p>
</div>
<div class="section" id="plac-vs-argparse">
-<h1><a class="toc-backref" href="#id10">plac vs argparse</a></h1>
+<h1><a class="toc-backref" href="#id11">plac vs argparse</a></h1>
<p><a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> is opinionated and by design it does not try to make available
-all of the features of <a class="reference external" href="http://argparse.googlecode.com">argparse</a>. In particular you should be aware
-of the following limitations/differences (the following assumes knowledge
-of <a class="reference external" href="http://argparse.googlecode.com">argparse</a>):</p>
+all of the features of <a class="reference external" href="http://argparse.googlecode.com">argparse</a> in an easy way. In particular you
+should be aware of the following limitations/differences (the
+following assumes knowledge of <a class="reference external" href="http://argparse.googlecode.com">argparse</a>):</p>
<ul class="simple">
<li><a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> automatically defines both a long and short form for each options,
just like <a class="reference external" href="http://docs.python.org/library/optparse.html">optparse</a>. <a class="reference external" href="http://argparse.googlecode.com">argparse</a> allows you to define only a long form,
@@ -1104,7 +1117,7 @@ can be trivially implemented with a ternary operator
<li><a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> does not support <tt class="docutils literal">nargs</tt> options directly (it uses them internally,
though, to implement flag recognition). The reason it that all the use
cases of interest to me are covered by <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> and did not feel the need
-to increase the learning curve by adding direct support to <tt class="docutils literal">nargs</tt>.</li>
+to increase the learning curve by adding direct support for <tt class="docutils literal">nargs</tt>.</li>
<li><a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> does not support subparsers directly. For the moment, this
looks like a feature too advanced for the goals of <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a>.</li>
<li><a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> does not support actions directly. This also
@@ -1120,7 +1133,7 @@ etc. In other words, while some features are not supported directly,
<em>all</em> features are supported indirectly.</p>
</div>
<div class="section" id="the-future">
-<h1><a class="toc-backref" href="#id11">The future</a></h1>
+<h1><a class="toc-backref" href="#id12">The future</a></h1>
<p>Currently plac is below 100 lines of code, not counting blanks, comments
and docstrings. I do not plan to extend it much in the future. The idea is
to keep the module short: it is and it should remain a little wrapper over
@@ -1131,7 +1144,7 @@ I wrote it in three days, including the tests, the documentation and the
time to learn <a class="reference external" href="http://argparse.googlecode.com">argparse</a>.</p>
</div>
<div class="section" id="trivia-the-story-behind-the-name">
-<h1><a class="toc-backref" href="#id12">Trivia: the story behind the name</a></h1>
+<h1><a class="toc-backref" href="#id13">Trivia: the story behind the name</a></h1>
<p>The <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> project started very humble: I just wanted to make
easy_installable my old <a class="reference external" href="http://code.activestate.com/recipes/278844-parsing-the-command-line/">optionparse</a> recipe, and to publish it on PyPI.
The original name of <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> was optionparser and the idea behind it was
@@ -1148,14 +1161,15 @@ of functions annotations in Python 3.</li>
<p>Putting together these two observations with the original idea of inferring the
parser I decided to build an <a class="reference external" href="http://argparse.googlecode.com/svn/tags/r11/doc/ArgumentParser.html">ArgumentParser</a> object from function
annotations. The <tt class="docutils literal">optionparser</tt> name was ruled out, since I was
-using <a class="reference external" href="http://argparse.googlecode.com">argparse</a>; a name like <tt class="docutils literal">argparse_plus</tt> was also ruled out,
+now using <a class="reference external" href="http://argparse.googlecode.com">argparse</a>; a name like <tt class="docutils literal">argparse_plus</tt> was also ruled out,
since the typical usage was completely different from the <a class="reference external" href="http://argparse.googlecode.com">argparse</a> usage.</p>
-<p>I made a research on PyPI and the name clap (Command Line Arguments Parser)
-was not taken, so I renamed everything to clap. After two days
-a <a class="reference external" href="http://pypi.python.org/pypi/Clap/0.7">Clap</a> module appeared on PyPI! &lt;expletives deleted&gt;</p>
+<p>I made a research on PyPI and the name plac (Command Line Arguments Parser)
+was not taken, so I renamed everything to plac. After two days
+a <a class="reference external" href="http://pypi.python.org/pypi/Clap/0.7">Clap</a> module appeared on PyPI &lt;expletives deleted&gt;!</p>
<p>Having little imagination, I decided to rename everything again to plac,
-an anagram of clap: since it is a non-existing English name, I hope nobody
+an anagram of plac: since it is a non-existing English name, I hope nobody
will steal it from me!</p>
+<p>That's all, I hope you will enjoy working with plac!</p>
</div>
</div>
</body>
diff --git a/plac/doc/plac.pdf b/plac/doc/plac.pdf
index 6119e4c..7bbaa83 100644
--- a/plac/doc/plac.pdf
+++ b/plac/doc/plac.pdf
@@ -6,8 +6,8 @@
<< /F1 2 0 R
/F2 3 0 R
/F3 4 0 R
- /F4 7 0 R
- /F5 46 0 R >>
+ /F4 8 0 R
+ /F5 50 0 R >>
endobj
% 'F1': class PDFType1Font
2 0 obj
@@ -66,8 +66,23 @@ endobj
/Subtype /Link
/Type /Annot >>
endobj
-% 'F4': class PDFType1Font
+% 'Annot.NUMBER3': class PDFDictionary
7 0 obj
+<< /A << /S /URI
+ /Type /Action
+ /URI (http://micheles.googlecode.com/hg/plac/doc/plac.html) >>
+ /Border [ 0
+ 0
+ 0 ]
+ /Rect [ 153.7323
+ 602.5936
+ 526.5827
+ 614.5936 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'F4': class PDFType1Font
+8 0 obj
% Font Courier
<< /BaseFont /Courier
/Encoding /WinAnsiEncoding
@@ -75,39 +90,21 @@ endobj
/Subtype /Type1
/Type /Font >>
endobj
-% 'Annot.NUMBER3': class LinkAnnotation
-8 0 obj
-<< /Border [ 0
- 0
- 0 ]
- /Contents ()
- /Dest [ 44 0 R
- /XYZ
- 62.69291
- 314.0236
- 0 ]
- /Rect [ 62.69291
- 530.5936
- 215.5029
- 542.5936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
% 'Annot.NUMBER4': class LinkAnnotation
9 0 obj
<< /Border [ 0
0
0 ]
/Contents ()
- /Dest [ 44 0 R
+ /Dest [ 42 0 R
/XYZ
62.69291
- 314.0236
+ 281.0236
0 ]
- /Rect [ 527.0227
- 530.5936
- 532.5827
- 542.5936 ]
+ /Rect [ 62.69291
+ 515.5936
+ 215.5029
+ 527.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -117,15 +114,15 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 50 0 R
+ /Dest [ 42 0 R
/XYZ
62.69291
- 651.0236
+ 281.0236
0 ]
- /Rect [ 62.69291
- 512.5936
- 266.0729
- 524.5936 ]
+ /Rect [ 527.0227
+ 515.5936
+ 532.5827
+ 527.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -135,15 +132,15 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 50 0 R
+ /Dest [ 54 0 R
/XYZ
62.69291
- 651.0236
+ 579.0236
0 ]
- /Rect [ 527.0227
- 512.5936
- 532.5827
- 524.5936 ]
+ /Rect [ 62.69291
+ 497.5936
+ 216.0629
+ 509.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -153,15 +150,15 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 57 0 R
+ /Dest [ 54 0 R
/XYZ
62.69291
- 440.6236
+ 579.0236
0 ]
- /Rect [ 62.69291
- 494.5936
- 208.8329
- 506.5936 ]
+ /Rect [ 527.0227
+ 497.5936
+ 532.5827
+ 509.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -171,15 +168,15 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 57 0 R
+ /Dest [ 60 0 R
/XYZ
62.69291
- 440.6236
+ 295.4236
0 ]
- /Rect [ 527.0227
- 494.5936
- 532.5827
- 506.5936 ]
+ /Rect [ 62.69291
+ 479.5936
+ 208.8329
+ 491.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -189,15 +186,15 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 66 0 R
+ /Dest [ 60 0 R
/XYZ
62.69291
- 233.4236
+ 295.4236
0 ]
- /Rect [ 62.69291
- 476.5936
- 147.1529
- 488.5936 ]
+ /Rect [ 527.0227
+ 479.5936
+ 532.5827
+ 491.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -207,15 +204,15 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 66 0 R
+ /Dest [ 72 0 R
/XYZ
62.69291
- 233.4236
+ 671.8236
0 ]
- /Rect [ 527.0227
- 476.5936
- 532.5827
- 488.5936 ]
+ /Rect [ 62.69291
+ 461.5936
+ 158.2629
+ 473.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -225,15 +222,15 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 73 0 R
+ /Dest [ 72 0 R
/XYZ
62.69291
- 197.0236
+ 671.8236
0 ]
- /Rect [ 62.69291
- 458.5936
- 182.7329
- 470.5936 ]
+ /Rect [ 527.0227
+ 461.5936
+ 532.5827
+ 473.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -243,15 +240,15 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 73 0 R
+ /Dest [ 76 0 R
/XYZ
62.69291
- 197.0236
+ 239.8236
0 ]
- /Rect [ 527.0227
- 458.5936
- 532.5827
- 470.5936 ]
+ /Rect [ 62.69291
+ 443.5936
+ 145.4929
+ 455.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -261,15 +258,15 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 80 0 R
+ /Dest [ 76 0 R
/XYZ
62.69291
- 457.4236
+ 239.8236
0 ]
- /Rect [ 62.69291
- 440.5936
- 128.2629
- 452.5936 ]
+ /Rect [ 527.0227
+ 443.5936
+ 532.5827
+ 455.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -279,15 +276,15 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 80 0 R
+ /Dest [ 78 0 R
/XYZ
62.69291
- 457.4236
+ 419.4236
0 ]
- /Rect [ 527.0227
- 440.5936
- 532.5827
- 452.5936 ]
+ /Rect [ 62.69291
+ 425.5936
+ 182.7329
+ 437.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -297,15 +294,15 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 84 0 R
+ /Dest [ 78 0 R
/XYZ
62.69291
- 347.2849
+ 419.4236
0 ]
- /Rect [ 62.69291
- 422.5936
- 204.9729
- 434.5936 ]
+ /Rect [ 527.0227
+ 425.5936
+ 532.5827
+ 437.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -315,15 +312,15 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 84 0 R
+ /Dest [ 85 0 R
/XYZ
62.69291
- 347.2849
+ 671.8236
0 ]
- /Rect [ 527.0227
- 422.5936
- 532.5827
- 434.5936 ]
+ /Rect [ 62.69291
+ 407.5936
+ 128.2629
+ 419.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -333,15 +330,15 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 90 0 R
+ /Dest [ 85 0 R
/XYZ
62.69291
- 388.6236
+ 671.8236
0 ]
- /Rect [ 62.69291
- 404.5936
- 297.1729
- 416.5936 ]
+ /Rect [ 527.0227
+ 407.5936
+ 532.5827
+ 419.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -351,15 +348,15 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 90 0 R
+ /Dest [ 89 0 R
/XYZ
62.69291
- 388.6236
+ 566.4849
0 ]
- /Rect [ 527.0227
- 404.5936
- 532.5827
- 416.5936 ]
+ /Rect [ 62.69291
+ 389.5936
+ 180.5229
+ 401.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -369,15 +366,15 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 97 0 R
+ /Dest [ 89 0 R
/XYZ
62.69291
- 480.6236
+ 566.4849
0 ]
- /Rect [ 62.69291
- 386.5936
- 191.5929
- 398.5936 ]
+ /Rect [ 527.0227
+ 389.5936
+ 532.5827
+ 401.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -387,15 +384,15 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 97 0 R
+ /Dest [ 100 0 R
/XYZ
62.69291
- 480.6236
+ 607.8236
0 ]
- /Rect [ 521.4627
- 386.5936
- 532.5827
- 398.5936 ]
+ /Rect [ 62.69291
+ 371.5936
+ 142.1629
+ 383.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -405,15 +402,15 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 117 0 R
+ /Dest [ 100 0 R
/XYZ
62.69291
- 524.6236
+ 607.8236
0 ]
- /Rect [ 62.69291
- 368.5936
- 141.6229
- 380.5936 ]
+ /Rect [ 521.4627
+ 371.5936
+ 532.5827
+ 383.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -423,15 +420,15 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 117 0 R
+ /Dest [ 102 0 R
/XYZ
62.69291
- 524.6236
+ 671.8236
0 ]
- /Rect [ 521.4627
- 368.5936
- 532.5827
- 380.5936 ]
+ /Rect [ 62.69291
+ 353.5936
+ 191.5929
+ 365.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -441,15 +438,15 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 136 0 R
+ /Dest [ 102 0 R
/XYZ
62.69291
- 705.0236
+ 671.8236
0 ]
- /Rect [ 62.69291
- 350.5936
- 111.5829
- 362.5936 ]
+ /Rect [ 521.4627
+ 353.5936
+ 532.5827
+ 365.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -459,15 +456,15 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 136 0 R
+ /Dest [ 130 0 R
/XYZ
62.69291
- 705.0236
+ 717.0236
0 ]
- /Rect [ 521.4627
- 350.5936
- 532.5827
- 362.5936 ]
+ /Rect [ 62.69291
+ 335.5936
+ 141.6229
+ 347.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -477,15 +474,15 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 136 0 R
+ /Dest [ 130 0 R
/XYZ
62.69291
- 594.0236
+ 717.0236
0 ]
- /Rect [ 62.69291
- 332.5936
- 219.9529
- 344.5936 ]
+ /Rect [ 521.4627
+ 335.5936
+ 532.5827
+ 347.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -495,60 +492,69 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 136 0 R
+ /Dest [ 130 0 R
/XYZ
62.69291
- 594.0236
+ 228.0236
0 ]
- /Rect [ 521.4627
- 332.5936
- 532.5827
- 344.5936 ]
+ /Rect [ 62.69291
+ 317.5936
+ 111.5829
+ 329.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER27': class PDFDictionary
+% 'Annot.NUMBER27': class LinkAnnotation
32 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://docs.python.org/library/getopt.html) >>
- /Border [ 0
+<< /Border [ 0
0
0 ]
- /Rect [ 214.8914
- 266.5936
- 246.5585
- 278.5936 ]
+ /Contents ()
+ /Dest [ 130 0 R
+ /XYZ
+ 62.69291
+ 228.0236
+ 0 ]
+ /Rect [ 521.4627
+ 317.5936
+ 532.5827
+ 329.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER28': class PDFDictionary
+% 'Annot.NUMBER28': class LinkAnnotation
33 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://docs.python.org/library/optparse.html) >>
- /Border [ 0
+<< /Border [ 0
0
0 ]
- /Rect [ 346.507
- 266.5936
- 389.2842
- 278.5936 ]
+ /Contents ()
+ /Dest [ 141 0 R
+ /XYZ
+ 62.69291
+ 765.0236
+ 0 ]
+ /Rect [ 62.69291
+ 299.5936
+ 219.9529
+ 311.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER29': class PDFDictionary
+% 'Annot.NUMBER29': class LinkAnnotation
34 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://argparse.googlecode.com) >>
- /Border [ 0
+<< /Border [ 0
0
0 ]
- /Rect [ 493.1227
- 266.5936
- 531.4956
- 278.5936 ]
+ /Contents ()
+ /Dest [ 141 0 R
+ /XYZ
+ 62.69291
+ 765.0236
+ 0 ]
+ /Rect [ 521.4627
+ 299.5936
+ 532.5827
+ 311.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -556,14 +562,14 @@ endobj
35 0 obj
<< /A << /S /URI
/Type /Action
- /URI (http://argparse.googlecode.com) >>
+ /URI (http://docs.python.org/library/getopt.html) >>
/Border [ 0
0
0 ]
- /Rect [ 346.384
- 254.5936
- 388.8477
- 266.5936 ]
+ /Rect [ 214.8914
+ 233.5936
+ 246.5585
+ 245.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -571,14 +577,14 @@ endobj
36 0 obj
<< /A << /S /URI
/Type /Action
- /URI (http://www.welton.it/articles/scalable_systems) >>
+ /URI (http://docs.python.org/library/optparse.html) >>
/Border [ 0
0
0 ]
- /Rect [ 471.0489
- 224.5936
- 529.8027
- 236.5936 ]
+ /Rect [ 346.507
+ 233.5936
+ 389.2842
+ 245.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -586,14 +592,14 @@ endobj
37 0 obj
<< /A << /S /URI
/Type /Action
- /URI (http://pypi.python.org/pypi/plac) >>
+ /URI (http://argparse.googlecode.com) >>
/Border [ 0
0
0 ]
- /Rect [ 514.2427
- 188.5936
- 532.4971
- 200.5936 ]
+ /Rect [ 493.1227
+ 233.5936
+ 531.4956
+ 245.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -605,10 +611,10 @@ endobj
/Border [ 0
0
0 ]
- /Rect [ 427.8629
- 164.5936
- 467.3229
- 176.5936 ]
+ /Rect [ 346.384
+ 221.5936
+ 388.8477
+ 233.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -616,14 +622,14 @@ endobj
39 0 obj
<< /A << /S /URI
/Type /Action
- /URI (http://pypi.python.org/pypi/plac) >>
+ /URI (http://www.welton.it/articles/scalable_systems) >>
/Border [ 0
0
0 ]
- /Rect [ 115.8141
- 146.5936
- 137.2654
- 158.5936 ]
+ /Rect [ 292.1608
+ 179.5936
+ 350.0128
+ 191.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -631,14 +637,14 @@ endobj
40 0 obj
<< /A << /S /URI
/Type /Action
- /URI (http://argparse.googlecode.com) >>
+ /URI (http://pypi.python.org/pypi/plac) >>
/Border [ 0
0
0 ]
- /Rect [ 268.7328
- 146.5936
- 308.1928
- 158.5936 ]
+ /Rect [ 208.2364
+ 131.5936
+ 229.8923
+ 143.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -646,53 +652,23 @@ endobj
41 0 obj
<< /A << /S /URI
/Type /Action
- /URI (http://pypi.python.org/pypi/plac) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 62.69291
- 122.5936
- 85.77504
- 134.5936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER37': class PDFDictionary
-42 0 obj
-<< /A << /S /URI
- /Type /Action
/URI (http://argparse.googlecode.com) >>
/Border [ 0
0
0 ]
- /Rect [ 400.7742
- 122.5936
- 440.2342
- 134.5936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER38': class PDFDictionary
-43 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://pypi.python.org/pypi/plac) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 280.3287
- 98.59362
- 298.6687
- 110.5936 ]
+ /Rect [ 152.7329
+ 107.5936
+ 192.1929
+ 119.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
% 'Page1': class PDFPage
-44 0 obj
+42 0 obj
% Page dictionary
<< /Annots [ 5 0 R
6 0 R
- 8 0 R
+ 7 0 R
9 0 R
10 0 R
11 0 R
@@ -725,15 +701,13 @@ endobj
38 0 R
39 0 R
40 0 R
- 41 0 R
- 42 0 R
- 43 0 R ]
- /Contents 153 0 R
+ 41 0 R ]
+ /Contents 159 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 152 0 R
+ /Parent 158 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -744,6 +718,36 @@ endobj
/Trans << >>
/Type /Page >>
endobj
+% 'Annot.NUMBER37': class PDFDictionary
+43 0 obj
+<< /A << /S /URI
+ /Type /Action
+ /URI (http://pypi.python.org/pypi/plac) >>
+ /Border [ 0
+ 0
+ 0 ]
+ /Rect [ 116.9711
+ 756.5936
+ 139.5794
+ 768.5936 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER38': class PDFDictionary
+44 0 obj
+<< /A << /S /URI
+ /Type /Action
+ /URI (http://argparse.googlecode.com) >>
+ /Border [ 0
+ 0
+ 0 ]
+ /Rect [ 277.9887
+ 756.5936
+ 321.7169
+ 768.5936 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
% 'Annot.NUMBER39': class PDFDictionary
45 0 obj
<< /A << /S /URI
@@ -752,15 +756,75 @@ endobj
/Border [ 0
0
0 ]
+ /Rect [ 504.0394
+ 744.5936
+ 525.3627
+ 756.5936 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER40': class PDFDictionary
+46 0 obj
+<< /A << /S /URI
+ /Type /Action
+ /URI (http://argparse.googlecode.com) >>
+ /Border [ 0
+ 0
+ 0 ]
+ /Rect [ 351.0408
+ 732.5936
+ 390.5008
+ 744.5936 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER41': class PDFDictionary
+47 0 obj
+<< /A << /S /URI
+ /Type /Action
+ /URI (http://pypi.python.org/pypi/plac) >>
+ /Border [ 0
+ 0
+ 0 ]
+ /Rect [ 247.8817
+ 708.5936
+ 266.2217
+ 720.5936 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER42': class PDFDictionary
+48 0 obj
+<< /A << /S /URI
+ /Type /Action
+ /URI (http://pypi.python.org/pypi/plac) >>
+ /Border [ 0
+ 0
+ 0 ]
/Rect [ 62.69291
- 738.5936
- 83.92136
- 750.5936 ]
+ 678.5936
+ 85.3538
+ 690.5936 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER43': class PDFDictionary
+49 0 obj
+<< /A << /S /URI
+ /Type /Action
+ /URI (http://pypi.python.org/pypi/plac) >>
+ /Border [ 0
+ 0
+ 0 ]
+ /Rect [ 124.2211
+ 606.5936
+ 146.9252
+ 618.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
% 'F5': class PDFType1Font
-46 0 obj
+50 0 obj
% Font Helvetica-Oblique
<< /BaseFont /Helvetica-Oblique
/Encoding /WinAnsiEncoding
@@ -768,64 +832,70 @@ endobj
/Subtype /Type1
/Type /Font >>
endobj
-% 'Annot.NUMBER40': class PDFDictionary
-47 0 obj
+% 'Annot.NUMBER44': class PDFDictionary
+51 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://docs.python.org/library/getopt.html) >>
/Border [ 0
0
0 ]
- /Rect [ 484.2853
- 302.3936
- 515.9027
- 314.3936 ]
+ /Rect [ 325.341
+ 214.3936
+ 356.6198
+ 226.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER41': class PDFDictionary
-48 0 obj
+% 'Annot.NUMBER45': class PDFDictionary
+52 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://docs.python.org/library/optparse.html) >>
/Border [ 0
0
0 ]
- /Rect [ 62.69291
- 290.3936
- 105.9509
- 302.3936 ]
+ /Rect [ 376.7786
+ 214.3936
+ 419.1674
+ 226.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER42': class PDFDictionary
-49 0 obj
+% 'Annot.NUMBER46': class PDFDictionary
+53 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
/Border [ 0
0
0 ]
- /Rect [ 62.69291
- 278.3936
- 104.9329
- 290.3936 ]
+ /Rect [ 365.694
+ 202.3936
+ 408.8281
+ 214.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
% 'Page2': class PDFPage
-50 0 obj
+54 0 obj
% Page dictionary
-<< /Annots [ 45 0 R
+<< /Annots [ 43 0 R
+ 44 0 R
+ 45 0 R
+ 46 0 R
47 0 R
48 0 R
- 49 0 R ]
- /Contents 154 0 R
+ 49 0 R
+ 51 0 R
+ 52 0 R
+ 53 0 R ]
+ /Contents 160 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 152 0 R
+ /Parent 158 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -836,8 +906,8 @@ endobj
/Trans << >>
/Type /Page >>
endobj
-% 'Annot.NUMBER43': class PDFDictionary
-51 0 obj
+% 'Annot.NUMBER47': class PDFDictionary
+55 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -845,14 +915,14 @@ endobj
0
0 ]
/Rect [ 83.82606
- 738.5936
+ 609.3936
106.0692
- 750.5936 ]
+ 621.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER44': class PDFDictionary
-52 0 obj
+% 'Annot.NUMBER48': class PDFDictionary
+56 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -860,14 +930,14 @@ endobj
0
0 ]
/Rect [ 243.8829
- 726.5936
+ 597.3936
265.0029
- 738.5936 ]
+ 609.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER45': class PDFDictionary
-53 0 obj
+% 'Annot.NUMBER49': class PDFDictionary
+57 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -875,14 +945,14 @@ endobj
0
0 ]
/Rect [ 83.6329
- 605.3936
+ 460.1936
105.6829
- 617.3936 ]
+ 472.1936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER46': class PDFDictionary
-54 0 obj
+% 'Annot.NUMBER50': class PDFDictionary
+58 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
@@ -890,14 +960,14 @@ endobj
0
0 ]
/Rect [ 421.9727
- 605.3936
+ 460.1936
465.1427
- 617.3936 ]
+ 472.1936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER47': class PDFDictionary
-55 0 obj
+% 'Annot.NUMBER51': class PDFDictionary
+59 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -905,42 +975,26 @@ endobj
0
0 ]
/Rect [ 211.6529
- 456.1936
+ 310.9936
232.7729
- 468.1936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER48': class PDFDictionary
-56 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://pypi.python.org/pypi/plac) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 85.47291
- 187.9936
- 106.5929
- 199.9936 ]
+ 322.9936 ]
/Subtype /Link
/Type /Annot >>
endobj
% 'Page3': class PDFPage
-57 0 obj
+60 0 obj
% Page dictionary
-<< /Annots [ 51 0 R
- 52 0 R
- 53 0 R
- 54 0 R
- 55 0 R
- 56 0 R ]
- /Contents 155 0 R
+<< /Annots [ 55 0 R
+ 56 0 R
+ 57 0 R
+ 58 0 R
+ 59 0 R ]
+ /Contents 161 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 152 0 R
+ /Parent 158 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -951,98 +1005,136 @@ endobj
/Trans << >>
/Type /Page >>
endobj
-% 'Annot.NUMBER49': class PDFDictionary
-58 0 obj
+% 'Annot.NUMBER52': class PDFDictionary
+61 0 obj
+<< /A << /S /URI
+ /Type /Action
+ /URI (http://argparse.googlecode.com) >>
+ /Border [ 0
+ 0
+ 0 ]
+ /Rect [ 321.4303
+ 651.3936
+ 363.754
+ 663.3936 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER53': class PDFDictionary
+62 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
/Border [ 0
0
0 ]
- /Rect [ 62.69291
- 627.3936
- 84.20915
- 639.3936 ]
+ /Rect [ 126.0429
+ 639.3936
+ 147.1629
+ 651.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER50': class PDFDictionary
-59 0 obj
+% 'Annot.NUMBER54': class PDFDictionary
+63 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
/Border [ 0
0
0 ]
- /Rect [ 91.59679
- 422.1936
- 109.9368
- 434.1936 ]
+ /Rect [ 62.69291
+ 424.9936
+ 84.20915
+ 436.9936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER51': class PDFDictionary
-60 0 obj
+% 'Annot.NUMBER55': class PDFDictionary
+64 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
/Border [ 0
0
0 ]
- /Rect [ 446.6187
- 260.9936
- 464.9587
- 272.9936 ]
+ /Rect [ 91.59679
+ 203.7936
+ 109.9368
+ 215.7936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER52': class PDFDictionary
-61 0 obj
+% 'Page4': class PDFPage
+65 0 obj
+% Page dictionary
+<< /Annots [ 61 0 R
+ 62 0 R
+ 63 0 R
+ 64 0 R ]
+ /Contents 162 0 R
+ /MediaBox [ 0
+ 0
+ 595.2756
+ 841.8898 ]
+ /Parent 158 0 R
+ /Resources << /Font 1 0 R
+ /ProcSet [ /PDF
+ /Text
+ /ImageB
+ /ImageC
+ /ImageI ] >>
+ /Rotate 0
+ /Trans << >>
+ /Type /Page >>
+endobj
+% 'Annot.NUMBER56': class PDFDictionary
+66 0 obj
<< /A << /S /URI
/Type /Action
- /URI (http://code.activestate.com/recipes/278844-parsing-the-command-line/) >>
+ /URI (http://pypi.python.org/pypi/plac) >>
/Border [ 0
0
0 ]
- /Rect [ 446.8103
- 149.9936
- 502.5727
- 161.9936 ]
+ /Rect [ 446.1627
+ 699.3936
+ 464.5027
+ 711.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER53': class PDFDictionary
-62 0 obj
+% 'Annot.NUMBER57': class PDFDictionary
+67 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
- 137.9936
- 312.43
- 149.9936 ]
+ /Rect [ 357.8702
+ 588.3936
+ 416.0058
+ 600.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER54': class PDFDictionary
-63 0 obj
+% 'Annot.NUMBER58': class PDFDictionary
+68 0 obj
<< /A << /S /URI
/Type /Action
- /URI (http://docs.python.org/library/optparse.html?highlight=optionparser#optparse.OptionParser) >>
+ /URI (http://code.activestate.com/recipes/278844-parsing-the-command-line/) >>
/Border [ 0
0
0 ]
- /Rect [ 376.1829
- 125.9936
- 435.0929
- 137.9936 ]
+ /Rect [ 182.0729
+ 576.3936
+ 234.3229
+ 588.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER55': class PDFDictionary
-64 0 obj
+% 'Annot.NUMBER59': class PDFDictionary
+69 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1050,14 +1142,14 @@ endobj
0
0 ]
/Rect [ 62.69291
- 107.9936
+ 546.3936
84.28901
- 119.9936 ]
+ 558.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER56': class PDFDictionary
-65 0 obj
+% 'Annot.NUMBER60': class PDFDictionary
+70 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://code.activestate.com/recipes/278844-parsing-the-command-line/) >>
@@ -1065,64 +1157,42 @@ endobj
0
0 ]
/Rect [ 161.7834
- 107.9936
+ 546.3936
217.2895
- 119.9936 ]
+ 558.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Page4': class PDFPage
-66 0 obj
-% Page dictionary
-<< /Annots [ 58 0 R
- 59 0 R
- 60 0 R
- 61 0 R
- 62 0 R
- 63 0 R
- 64 0 R
- 65 0 R ]
- /Contents 156 0 R
- /MediaBox [ 0
- 0
- 595.2756
- 841.8898 ]
- /Parent 152 0 R
- /Resources << /Font 1 0 R
- /ProcSet [ /PDF
- /Text
- /ImageB
- /ImageC
- /ImageI ] >>
- /Rotate 0
- /Trans << >>
- /Type /Page >>
-endobj
-% 'Annot.NUMBER57': class PDFDictionary
-67 0 obj
+% 'Annot.NUMBER61': class PDFDictionary
+71 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
/Border [ 0
0
0 ]
- /Rect [ 133.1479
- 569.3936
- 154.4129
- 581.3936 ]
+ /Rect [ 514.2427
+ 343.1936
+ 532.2243
+ 355.1936 ]
/Subtype /Link
/Type /Annot >>
endobj
% 'Page5': class PDFPage
-68 0 obj
+72 0 obj
% Page dictionary
-<< /Annots [ 67 0 R ]
- /Contents 157 0 R
+<< /Annots [ 66 0 R
+ 67 0 R
+ 68 0 R
+ 69 0 R
+ 70 0 R
+ 71 0 R ]
+ /Contents 163 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 152 0 R
+ /Parent 158 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1133,8 +1203,8 @@ endobj
/Trans << >>
/Type /Page >>
endobj
-% 'Annot.NUMBER58': class PDFDictionary
-69 0 obj
+% 'Annot.NUMBER62': class PDFDictionary
+73 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1142,29 +1212,29 @@ endobj
0
0 ]
/Rect [ 183.7423
- 687.3936
+ 431.7936
204.9746
- 699.3936 ]
+ 443.7936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER59': class PDFDictionary
-70 0 obj
+% 'Annot.NUMBER63': class PDFDictionary
+74 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
/Border [ 0
0
0 ]
- /Rect [ 162.7329
- 586.1936
- 181.0729
- 598.1936 ]
+ /Rect [ 184.4029
+ 312.5936
+ 202.7429
+ 324.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER60': class PDFDictionary
-71 0 obj
+% 'Annot.NUMBER64': class PDFDictionary
+75 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1172,40 +1242,59 @@ endobj
0
0 ]
/Rect [ 62.69291
- 508.9936
+ 204.3936
84.57878
- 520.9936 ]
+ 216.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER61': class PDFDictionary
-72 0 obj
+% 'Page6': class PDFPage
+76 0 obj
+% Page dictionary
+<< /Annots [ 73 0 R
+ 74 0 R
+ 75 0 R ]
+ /Contents 164 0 R
+ /MediaBox [ 0
+ 0
+ 595.2756
+ 841.8898 ]
+ /Parent 158 0 R
+ /Resources << /Font 1 0 R
+ /ProcSet [ /PDF
+ /Text
+ /ImageB
+ /ImageC
+ /ImageI ] >>
+ /Rotate 0
+ /Trans << >>
+ /Type /Page >>
+endobj
+% 'Annot.NUMBER65': class PDFDictionary
+77 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
/Border [ 0
0
0 ]
- /Rect [ 153.3575
- 137.5936
- 175.3449
- 149.5936 ]
+ /Rect [ 110.2829
+ 359.9936
+ 132.8629
+ 371.9936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Page6': class PDFPage
-73 0 obj
+% 'Page7': class PDFPage
+78 0 obj
% Page dictionary
-<< /Annots [ 69 0 R
- 70 0 R
- 71 0 R
- 72 0 R ]
- /Contents 158 0 R
+<< /Annots [ 77 0 R ]
+ /Contents 165 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 152 0 R
+ /Parent 158 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1216,111 +1305,111 @@ endobj
/Trans << >>
/Type /Page >>
endobj
-% 'Annot.NUMBER62': class PDFDictionary
-74 0 obj
+% 'Annot.NUMBER66': class PDFDictionary
+79 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
/Border [ 0
0
0 ]
- /Rect [ 371.2728
- 484.9936
- 393.9678
- 496.9936 ]
+ /Rect [ 358.6729
+ 687.3936
+ 379.7929
+ 699.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER63': class PDFDictionary
-75 0 obj
+% 'Annot.NUMBER67': class PDFDictionary
+80 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
/Border [ 0
0
0 ]
- /Rect [ 62.69291
- 409.9936
- 102.1529
- 421.9936 ]
+ /Rect [ 104.3155
+ 624.3936
+ 143.7755
+ 636.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER64': class PDFDictionary
-76 0 obj
+% 'Annot.NUMBER68': class PDFDictionary
+81 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
/Border [ 0
0
0 ]
- /Rect [ 375.4489
- 409.9936
- 414.9089
- 421.9936 ]
+ /Rect [ 414.3275
+ 624.3936
+ 453.7875
+ 636.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER65': class PDFDictionary
-77 0 obj
+% 'Annot.NUMBER69': class PDFDictionary
+82 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
/Border [ 0
0
0 ]
- /Rect [ 493.1227
- 409.9936
- 532.1699
- 421.9936 ]
+ /Rect [ 62.69291
+ 612.3936
+ 106.6498
+ 624.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER66': class PDFDictionary
-78 0 obj
+% 'Annot.NUMBER70': class PDFDictionary
+83 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
/Border [ 0
0
0 ]
- /Rect [ 140.8079
- 397.9936
- 159.1479
- 409.9936 ]
+ /Rect [ 189.6004
+ 612.3936
+ 207.9404
+ 624.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER67': class PDFDictionary
-79 0 obj
+% 'Annot.NUMBER71': class PDFDictionary
+84 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
/Border [ 0
0
0 ]
- /Rect [ 415.0529
- 205.9936
- 457.2929
- 217.9936 ]
+ /Rect [ 355.0429
+ 420.3936
+ 397.2829
+ 432.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Page7': class PDFPage
-80 0 obj
+% 'Page8': class PDFPage
+85 0 obj
% Page dictionary
-<< /Annots [ 74 0 R
- 75 0 R
- 76 0 R
- 77 0 R
- 78 0 R
- 79 0 R ]
- /Contents 159 0 R
+<< /Annots [ 79 0 R
+ 80 0 R
+ 81 0 R
+ 82 0 R
+ 83 0 R
+ 84 0 R ]
+ /Contents 166 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 152 0 R
+ /Parent 158 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1331,8 +1420,8 @@ endobj
/Trans << >>
/Type /Page >>
endobj
-% 'Annot.NUMBER68': class PDFDictionary
-81 0 obj
+% 'Annot.NUMBER72': class PDFDictionary
+86 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1340,14 +1429,14 @@ endobj
0
0 ]
/Rect [ 338.1568
- 311.8549
+ 531.0549
360.5113
- 323.8549 ]
+ 543.0549 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER69': class PDFDictionary
-82 0 obj
+% 'Annot.NUMBER73': class PDFDictionary
+87 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://www.sqlalchemy.org/) >>
@@ -1355,14 +1444,14 @@ endobj
0
0 ]
/Rect [ 110.6843
- 299.8549
+ 519.0549
169.0343
- 311.8549 ]
+ 531.0549 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER70': class PDFDictionary
-83 0 obj
+% 'Annot.NUMBER74': class PDFDictionary
+88 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://www.sqlalchemy.org/docs/reference/ext/sqlsoup.html) >>
@@ -1370,24 +1459,24 @@ endobj
0
0 ]
/Rect [ 168.3029
- 287.8549
+ 507.0549
208.8829
- 299.8549 ]
+ 519.0549 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Page8': class PDFPage
-84 0 obj
+% 'Page9': class PDFPage
+89 0 obj
% Page dictionary
-<< /Annots [ 81 0 R
- 82 0 R
- 83 0 R ]
- /Contents 160 0 R
+<< /Annots [ 86 0 R
+ 87 0 R
+ 88 0 R ]
+ /Contents 167 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 152 0 R
+ /Parent 158 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1398,8 +1487,8 @@ endobj
/Trans << >>
/Type /Page >>
endobj
-% 'Annot.NUMBER71': class PDFDictionary
-85 0 obj
+% 'Annot.NUMBER75': class PDFDictionary
+90 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1407,14 +1496,14 @@ endobj
0
0 ]
/Rect [ 62.69291
- 353.1936
+ 572.3936
83.9079
- 365.1936 ]
+ 584.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER72': class PDFDictionary
-86 0 obj
+% 'Annot.NUMBER76': class PDFDictionary
+91 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
@@ -1422,14 +1511,14 @@ endobj
0
0 ]
/Rect [ 133.1029
- 353.1936
+ 572.3936
175.4379
- 365.1936 ]
+ 584.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER73': class PDFDictionary
-87 0 obj
+% 'Annot.NUMBER77': class PDFDictionary
+92 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
@@ -1437,14 +1526,14 @@ endobj
0
0 ]
/Rect [ 454.1177
- 353.1936
+ 572.3936
496.4527
- 365.1936 ]
+ 584.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER74': class PDFDictionary
-88 0 obj
+% 'Annot.NUMBER78': class PDFDictionary
+93 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com/svn/tags/r11/doc/other-utilities.html?highlight=filetype#FileType) >>
@@ -1452,14 +1541,14 @@ endobj
0
0 ]
/Rect [ 455.2227
- 311.1936
+ 530.3936
534.3667
- 323.1936 ]
+ 542.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER75': class PDFDictionary
-89 0 obj
+% 'Annot.NUMBER79': class PDFDictionary
+94 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1467,38 +1556,14 @@ endobj
0
0 ]
/Rect [ 127.99
- 143.9936
+ 363.1936
149.3857
- 155.9936 ]
+ 375.1936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Page9': class PDFPage
-90 0 obj
-% Page dictionary
-<< /Annots [ 85 0 R
- 86 0 R
- 87 0 R
- 88 0 R
- 89 0 R ]
- /Contents 161 0 R
- /MediaBox [ 0
- 0
- 595.2756
- 841.8898 ]
- /Parent 152 0 R
- /Resources << /Font 1 0 R
- /ProcSet [ /PDF
- /Text
- /ImageB
- /ImageC
- /ImageI ] >>
- /Rotate 0
- /Trans << >>
- /Type /Page >>
-endobj
-% 'Annot.NUMBER76': class PDFDictionary
-91 0 obj
+% 'Annot.NUMBER80': class PDFDictionary
+95 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1506,29 +1571,29 @@ endobj
0
0 ]
/Rect [ 326.9971
- 711.3936
+ 249.9936
351.8113
- 723.3936 ]
+ 261.9936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER77': class PDFDictionary
-92 0 obj
+% 'Annot.NUMBER81': class PDFDictionary
+96 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
/Border [ 0
0
0 ]
- /Rect [ 407.706
- 699.3936
- 452.2944
- 711.3936 ]
+ /Rect [ 409.706
+ 237.9936
+ 453.2944
+ 249.9936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER78': class PDFDictionary
-93 0 obj
+% 'Annot.NUMBER82': class PDFDictionary
+97 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
@@ -1536,14 +1601,14 @@ endobj
0
0 ]
/Rect [ 259.0928
- 687.3936
+ 225.9936
302.7528
- 699.3936 ]
+ 237.9936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER79': class PDFDictionary
-94 0 obj
+% 'Annot.NUMBER83': class PDFDictionary
+98 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1551,14 +1616,14 @@ endobj
0
0 ]
/Rect [ 258.3129
- 663.3936
+ 201.9936
279.4329
- 675.3936 ]
+ 213.9936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER80': class PDFDictionary
-95 0 obj
+% 'Annot.NUMBER84': class PDFDictionary
+99 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com/svn/tags/r11/doc/ArgumentParser.html) >>
@@ -1566,14 +1631,43 @@ endobj
0
0 ]
/Rect [ 327.2261
- 645.3936
+ 183.9936
410.5152
- 657.3936 ]
+ 195.9936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER81': class PDFDictionary
-96 0 obj
+% 'Page10': class PDFPage
+100 0 obj
+% Page dictionary
+<< /Annots [ 90 0 R
+ 91 0 R
+ 92 0 R
+ 93 0 R
+ 94 0 R
+ 95 0 R
+ 96 0 R
+ 97 0 R
+ 98 0 R
+ 99 0 R ]
+ /Contents 168 0 R
+ /MediaBox [ 0
+ 0
+ 595.2756
+ 841.8898 ]
+ /Parent 158 0 R
+ /Resources << /Font 1 0 R
+ /ProcSet [ /PDF
+ /Text
+ /ImageB
+ /ImageC
+ /ImageI ] >>
+ /Rotate 0
+ /Trans << >>
+ /Type /Page >>
+endobj
+% 'Annot.NUMBER85': class PDFDictionary
+101 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1581,27 +1675,22 @@ endobj
0
0 ]
/Rect [ 106.6216
- 445.1936
+ 636.3936
128.3202
- 457.1936 ]
+ 648.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Page10': class PDFPage
-97 0 obj
+% 'Page11': class PDFPage
+102 0 obj
% Page dictionary
-<< /Annots [ 91 0 R
- 92 0 R
- 93 0 R
- 94 0 R
- 95 0 R
- 96 0 R ]
- /Contents 162 0 R
+<< /Annots [ 101 0 R ]
+ /Contents 169 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 152 0 R
+ /Parent 158 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1612,8 +1701,8 @@ endobj
/Trans << >>
/Type /Page >>
endobj
-% 'Annot.NUMBER82': class PDFDictionary
-98 0 obj
+% 'Annot.NUMBER86': class PDFDictionary
+103 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1621,44 +1710,44 @@ endobj
0
0 ]
/Rect [ 62.69291
- 489.1936
- 85.4908
- 501.1936 ]
+ 681.5936
+ 84.8789
+ 693.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER83': class PDFDictionary
-99 0 obj
+% 'Annot.NUMBER87': class PDFDictionary
+104 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
/Border [ 0
0
0 ]
- /Rect [ 477.5448
- 489.1936
- 517.0048
- 501.1936 ]
+ /Rect [ 466.5307
+ 681.5936
+ 509.8367
+ 693.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER84': class PDFDictionary
-100 0 obj
+% 'Annot.NUMBER88': class PDFDictionary
+105 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
/Border [ 0
0
0 ]
- /Rect [ 73.81291
- 465.1936
- 113.2729
- 477.1936 ]
+ /Rect [ 124.3929
+ 657.5936
+ 163.8529
+ 669.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER85': class PDFDictionary
-101 0 obj
+% 'Annot.NUMBER89': class PDFDictionary
+106 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1666,14 +1755,14 @@ endobj
0
0 ]
/Rect [ 85.69291
- 444.1936
+ 636.5936
107.7029
- 456.1936 ]
+ 648.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER86': class PDFDictionary
-102 0 obj
+% 'Annot.NUMBER90': class PDFDictionary
+107 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://docs.python.org/library/optparse.html) >>
@@ -1681,14 +1770,14 @@ endobj
0
0 ]
/Rect [ 447.7627
- 444.1936
+ 636.5936
486.6727
- 456.1936 ]
+ 648.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER87': class PDFDictionary
-103 0 obj
+% 'Annot.NUMBER91': class PDFDictionary
+108 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
@@ -1696,14 +1785,14 @@ endobj
0
0 ]
/Rect [ 493.1227
- 444.1936
+ 636.5936
531.6927
- 456.1936 ]
+ 648.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER88': class PDFDictionary
-104 0 obj
+% 'Annot.NUMBER92': class PDFDictionary
+109 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://docs.python.org/library/optparse.html) >>
@@ -1711,14 +1800,14 @@ endobj
0
0 ]
/Rect [ 232.9652
- 420.1936
+ 612.5936
271.8752
- 432.1936 ]
+ 624.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER89': class PDFDictionary
-105 0 obj
+% 'Annot.NUMBER93': class PDFDictionary
+110 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
@@ -1726,14 +1815,14 @@ endobj
0
0 ]
/Rect [ 85.69291
- 330.1936
+ 522.5936
127.9329
- 342.1936 ]
+ 534.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER90': class PDFDictionary
-106 0 obj
+% 'Annot.NUMBER94': class PDFDictionary
+111 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1741,14 +1830,14 @@ endobj
0
0 ]
/Rect [ 85.69291
- 312.1936
+ 504.5936
107.9337
- 324.1936 ]
+ 516.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER91': class PDFDictionary
-107 0 obj
+% 'Annot.NUMBER95': class PDFDictionary
+112 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
@@ -1756,14 +1845,14 @@ endobj
0
0 ]
/Rect [ 308.5389
- 312.1936
+ 504.5936
351.8997
- 324.1936 ]
+ 516.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER92': class PDFDictionary
-108 0 obj
+% 'Annot.NUMBER96': class PDFDictionary
+113 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1771,14 +1860,14 @@ endobj
0
0 ]
/Rect [ 85.69291
- 270.1936
+ 462.5936
108.3529
- 282.1936 ]
+ 474.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER93': class PDFDictionary
-109 0 obj
+% 'Annot.NUMBER97': class PDFDictionary
+114 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
@@ -1786,14 +1875,14 @@ endobj
0
0 ]
/Rect [ 277.2428
- 270.1936
+ 462.5936
321.0228
- 282.1936 ]
+ 474.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER94': class PDFDictionary
-110 0 obj
+% 'Annot.NUMBER98': class PDFDictionary
+115 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1801,14 +1890,14 @@ endobj
0
0 ]
/Rect [ 404.5839
- 258.1936
+ 450.5936
426.0657
- 270.1936 ]
+ 462.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER95': class PDFDictionary
-111 0 obj
+% 'Annot.NUMBER99': class PDFDictionary
+116 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1816,14 +1905,14 @@ endobj
0
0 ]
/Rect [ 85.69291
- 204.1936
+ 396.5936
108.61
- 216.1936 ]
+ 408.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER96': class PDFDictionary
-112 0 obj
+% 'Annot.NUMBER100': class PDFDictionary
+117 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1831,14 +1920,14 @@ endobj
0
0 ]
/Rect [ 459.2622
- 192.1936
+ 384.5936
481.289
- 204.1936 ]
+ 396.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER97': class PDFDictionary
-113 0 obj
+% 'Annot.NUMBER101': class PDFDictionary
+118 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1846,14 +1935,14 @@ endobj
0
0 ]
/Rect [ 85.69291
- 162.1936
+ 354.5936
107.0573
- 174.1936 ]
+ 366.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER98': class PDFDictionary
-114 0 obj
+% 'Annot.NUMBER102': class PDFDictionary
+119 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1861,14 +1950,14 @@ endobj
0
0 ]
/Rect [ 140.1729
- 150.1936
+ 342.5936
158.5129
- 162.1936 ]
+ 354.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER99': class PDFDictionary
-115 0 obj
+% 'Annot.NUMBER103': class PDFDictionary
+120 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1876,14 +1965,14 @@ endobj
0
0 ]
/Rect [ 85.69291
- 132.1936
+ 324.5936
107.9247
- 144.1936 ]
+ 336.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER100': class PDFDictionary
-116 0 obj
+% 'Annot.NUMBER104': class PDFDictionary
+121 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1891,52 +1980,14 @@ endobj
0
0 ]
/Rect [ 85.69291
- 120.1936
+ 312.5936
104.0329
- 132.1936 ]
+ 324.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Page11': class PDFPage
-117 0 obj
-% Page dictionary
-<< /Annots [ 98 0 R
- 99 0 R
- 100 0 R
- 101 0 R
- 102 0 R
- 103 0 R
- 104 0 R
- 105 0 R
- 106 0 R
- 107 0 R
- 108 0 R
- 109 0 R
- 110 0 R
- 111 0 R
- 112 0 R
- 113 0 R
- 114 0 R
- 115 0 R
- 116 0 R ]
- /Contents 163 0 R
- /MediaBox [ 0
- 0
- 595.2756
- 841.8898 ]
- /Parent 152 0 R
- /Resources << /Font 1 0 R
- /ProcSet [ /PDF
- /Text
- /ImageB
- /ImageC
- /ImageI ] >>
- /Rotate 0
- /Trans << >>
- /Type /Page >>
-endobj
-% 'Annot.NUMBER101': class PDFDictionary
-118 0 obj
+% 'Annot.NUMBER105': class PDFDictionary
+122 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
@@ -1944,14 +1995,14 @@ endobj
0
0 ]
/Rect [ 340.7317
- 756.5936
+ 279.5936
385.1185
- 768.5936 ]
+ 291.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER102': class PDFDictionary
-119 0 obj
+% 'Annot.NUMBER106': class PDFDictionary
+123 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1959,14 +2010,14 @@ endobj
0
0 ]
/Rect [ 451.1022
- 756.5936
+ 279.5936
474.369
- 768.5936 ]
+ 291.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER103': class PDFDictionary
-120 0 obj
+% 'Annot.NUMBER107': class PDFDictionary
+124 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com/svn/tags/r11/doc/ArgumentParser.html) >>
@@ -1974,14 +2025,14 @@ endobj
0
0 ]
/Rect [ 321.0443
- 744.5936
+ 267.5936
399.3474
- 756.5936 ]
+ 279.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER104': class PDFDictionary
-121 0 obj
+% 'Annot.NUMBER108': class PDFDictionary
+125 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
@@ -1989,14 +2040,14 @@ endobj
0
0 ]
/Rect [ 62.69291
- 732.5936
+ 255.5936
107.3744
- 744.5936 ]
+ 267.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER105': class PDFDictionary
-122 0 obj
+% 'Annot.NUMBER109': class PDFDictionary
+126 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
@@ -2004,14 +2055,14 @@ endobj
0
0 ]
/Rect [ 86.82623
- 645.5936
+ 168.5936
126.2862
- 657.5936 ]
+ 180.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER106': class PDFDictionary
-123 0 obj
+% 'Annot.NUMBER110': class PDFDictionary
+127 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
@@ -2019,14 +2070,14 @@ endobj
0
0 ]
/Rect [ 415.1627
- 645.5936
+ 168.5936
459.306
- 657.5936 ]
+ 180.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER107': class PDFDictionary
-124 0 obj
+% 'Annot.NUMBER111': class PDFDictionary
+128 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -2034,14 +2085,14 @@ endobj
0
0 ]
/Rect [ 468.9894
- 645.5936
+ 168.5936
492.0127
- 657.5936 ]
+ 180.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER108': class PDFDictionary
-125 0 obj
+% 'Annot.NUMBER112': class PDFDictionary
+129 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
@@ -2049,14 +2100,60 @@ endobj
0
0 ]
/Rect [ 62.69291
- 609.5936
+ 132.5936
102.1529
- 621.5936 ]
+ 144.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER109': class PDFDictionary
-126 0 obj
+% 'Page12': class PDFPage
+130 0 obj
+% Page dictionary
+<< /Annots [ 103 0 R
+ 104 0 R
+ 105 0 R
+ 106 0 R
+ 107 0 R
+ 108 0 R
+ 109 0 R
+ 110 0 R
+ 111 0 R
+ 112 0 R
+ 113 0 R
+ 114 0 R
+ 115 0 R
+ 116 0 R
+ 117 0 R
+ 118 0 R
+ 119 0 R
+ 120 0 R
+ 121 0 R
+ 122 0 R
+ 123 0 R
+ 124 0 R
+ 125 0 R
+ 126 0 R
+ 127 0 R
+ 128 0 R
+ 129 0 R ]
+ /Contents 170 0 R
+ /MediaBox [ 0
+ 0
+ 595.2756
+ 841.8898 ]
+ /Parent 158 0 R
+ /Resources << /Font 1 0 R
+ /ProcSet [ /PDF
+ /Text
+ /ImageB
+ /ImageC
+ /ImageI ] >>
+ /Rotate 0
+ /Trans << >>
+ /Type /Page >>
+endobj
+% 'Annot.NUMBER113': class PDFDictionary
+131 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -2064,14 +2161,14 @@ endobj
0
0 ]
/Rect [ 83.64556
- 558.5936
+ 729.5936
105.7082
- 570.5936 ]
+ 741.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER110': class PDFDictionary
-127 0 obj
+% 'Annot.NUMBER114': class PDFDictionary
+132 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://code.activestate.com/recipes/278844-parsing-the-command-line/) >>
@@ -2079,14 +2176,14 @@ endobj
0
0 ]
/Rect [ 446.6
- 558.5936
+ 729.5936
502.5727
- 570.5936 ]
+ 741.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER111': class PDFDictionary
-128 0 obj
+% 'Annot.NUMBER115': class PDFDictionary
+133 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -2094,14 +2191,14 @@ endobj
0
0 ]
/Rect [ 275.6828
- 546.5936
+ 717.5936
297.3688
- 558.5936 ]
+ 729.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER112': class PDFDictionary
-129 0 obj
+% 'Annot.NUMBER116': class PDFDictionary
+134 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://docs.python.org/library/optparse.html?highlight=optionparser#optparse.OptionParser) >>
@@ -2109,14 +2206,14 @@ endobj
0
0 ]
/Rect [ 77.19665
- 534.5936
+ 705.5936
139.4904
- 546.5936 ]
+ 717.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER113': class PDFDictionary
-130 0 obj
+% 'Annot.NUMBER117': class PDFDictionary
+135 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
@@ -2124,14 +2221,14 @@ endobj
0
0 ]
/Rect [ 96.54131
- 522.5936
+ 693.5936
139.0255
- 534.5936 ]
+ 705.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER114': class PDFDictionary
-131 0 obj
+% 'Annot.NUMBER118': class PDFDictionary
+136 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
@@ -2139,14 +2236,14 @@ endobj
0
0 ]
/Rect [ 203.5016
- 489.5936
+ 660.5936
245.8453
- 501.5936 ]
+ 672.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER115': class PDFDictionary
-132 0 obj
+% 'Annot.NUMBER119': class PDFDictionary
+137 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com/svn/tags/r11/doc/ArgumentParser.html) >>
@@ -2154,44 +2251,44 @@ endobj
0
0 ]
/Rect [ 62.69291
- 414.5936
+ 585.5936
138.7898
- 426.5936 ]
+ 597.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER116': class PDFDictionary
-133 0 obj
+% 'Annot.NUMBER120': class PDFDictionary
+138 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
/Border [ 0
0
0 ]
- /Rect [ 89.49556
- 402.5936
- 128.9556
- 414.5936 ]
+ /Rect [ 114.6649
+ 573.5936
+ 154.1249
+ 585.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER117': class PDFDictionary
-134 0 obj
+% 'Annot.NUMBER121': class PDFDictionary
+139 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
/Border [ 0
0
0 ]
- /Rect [ 141.0629
- 390.5936
- 183.3029
- 402.5936 ]
+ /Rect [ 191.6329
+ 561.5936
+ 233.8729
+ 573.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER118': class PDFDictionary
-135 0 obj
+% 'Annot.NUMBER122': class PDFDictionary
+140 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/Clap/0.7) >>
@@ -2199,39 +2296,31 @@ endobj
0
0 ]
/Rect [ 263.3429
- 360.5936
+ 531.5936
286.6829
- 372.5936 ]
+ 543.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Page12': class PDFPage
-136 0 obj
+% 'Page13': class PDFPage
+141 0 obj
% Page dictionary
-<< /Annots [ 118 0 R
- 119 0 R
- 120 0 R
- 121 0 R
- 122 0 R
- 123 0 R
- 124 0 R
- 125 0 R
- 126 0 R
- 127 0 R
- 128 0 R
- 129 0 R
- 130 0 R
- 131 0 R
+<< /Annots [ 131 0 R
132 0 R
133 0 R
134 0 R
- 135 0 R ]
- /Contents 164 0 R
+ 135 0 R
+ 136 0 R
+ 137 0 R
+ 138 0 R
+ 139 0 R
+ 140 0 R ]
+ /Contents 171 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 152 0 R
+ /Parent 158 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -2242,201 +2331,214 @@ endobj
/Trans << >>
/Type /Page >>
endobj
-% 'R137': class PDFCatalog
-137 0 obj
+% 'R142': class PDFCatalog
+142 0 obj
% Document Root
-<< /Outlines 139 0 R
- /PageLabels 165 0 R
+<< /Outlines 144 0 R
+ /PageLabels 172 0 R
/PageMode /UseNone
- /Pages 152 0 R
+ /Pages 158 0 R
/Type /Catalog >>
endobj
-% 'R138': class PDFInfo
-138 0 obj
+% 'R143': class PDFInfo
+143 0 obj
<< /Author (Michele Simionato)
- /CreationDate (D:20100602045230-01'00')
+ /CreationDate (D:20100602062545-01'00')
/Keywords ()
/Producer (ReportLab http://www.reportlab.com)
/Subject (\(unspecified\))
- /Title (Parsing the Command Line the Easy Way: Introducing plac, the EasiestArgument Parser in the Python World) >>
+ /Title (Parsing the Command Line the Easy Way: Introducing plac, the Easiest Argument Parser in the Python World) >>
endobj
-% 'R139': class PDFOutlines
-139 0 obj
-<< /Count 12
- /First 140 0 R
- /Last 151 0 R
+% 'R144': class PDFOutlines
+144 0 obj
+<< /Count 13
+ /First 145 0 R
+ /Last 157 0 R
/Type /Outlines >>
endobj
% 'Outline.0': class OutlineEntryObject
-140 0 obj
-<< /Dest [ 44 0 R
+145 0 obj
+<< /Dest [ 42 0 R
/XYZ
62.69291
- 314.0236
+ 281.0236
0 ]
- /Next 141 0 R
- /Parent 139 0 R
+ /Next 146 0 R
+ /Parent 144 0 R
/Title (The importance of scaling down) >>
endobj
% 'Outline.1': class OutlineEntryObject
-141 0 obj
-<< /Dest [ 50 0 R
+146 0 obj
+<< /Dest [ 54 0 R
/XYZ
62.69291
- 651.0236
+ 579.0236
0 ]
- /Next 142 0 R
- /Parent 139 0 R
- /Prev 140 0 R
- /Title (Scripts with required positional arguments) >>
+ /Next 147 0 R
+ /Parent 144 0 R
+ /Prev 145 0 R
+ /Title (Scripts with required arguments) >>
endobj
% 'Outline.2': class OutlineEntryObject
-142 0 obj
-<< /Dest [ 57 0 R
+147 0 obj
+<< /Dest [ 60 0 R
/XYZ
62.69291
- 440.6236
+ 295.4236
0 ]
- /Next 143 0 R
- /Parent 139 0 R
- /Prev 141 0 R
- /Title (Scritps with default arguments) >>
+ /Next 148 0 R
+ /Parent 144 0 R
+ /Prev 146 0 R
+ /Title (Scripts with default arguments) >>
endobj
% 'Outline.3': class OutlineEntryObject
-143 0 obj
-<< /Dest [ 66 0 R
+148 0 obj
+<< /Dest [ 72 0 R
/XYZ
62.69291
- 233.4236
+ 671.8236
0 ]
- /Next 144 0 R
- /Parent 139 0 R
- /Prev 142 0 R
- /Title (Options and flags) >>
+ /Next 149 0 R
+ /Parent 144 0 R
+ /Prev 147 0 R
+ /Title (Scripts with options) >>
endobj
% 'Outline.4': class OutlineEntryObject
-144 0 obj
-<< /Dest [ 73 0 R
+149 0 obj
+<< /Dest [ 76 0 R
/XYZ
62.69291
- 197.0236
+ 239.8236
0 ]
- /Next 145 0 R
- /Parent 139 0 R
- /Prev 143 0 R
- /Title (plac for Python 2.X users) >>
+ /Next 150 0 R
+ /Parent 144 0 R
+ /Prev 148 0 R
+ /Title (Scripts with flags) >>
endobj
% 'Outline.5': class OutlineEntryObject
-145 0 obj
-<< /Dest [ 80 0 R
+150 0 obj
+<< /Dest [ 78 0 R
/XYZ
62.69291
- 457.4236
+ 419.4236
0 ]
- /Next 146 0 R
- /Parent 139 0 R
- /Prev 144 0 R
- /Title (More features) >>
+ /Next 151 0 R
+ /Parent 144 0 R
+ /Prev 149 0 R
+ /Title (plac for Python 2.X users) >>
endobj
% 'Outline.6': class OutlineEntryObject
-146 0 obj
-<< /Dest [ 84 0 R
+151 0 obj
+<< /Dest [ 85 0 R
/XYZ
62.69291
- 347.2849
+ 671.8236
0 ]
- /Next 147 0 R
- /Parent 139 0 R
- /Prev 145 0 R
- /Title (A somewhat realistic example) >>
+ /Next 152 0 R
+ /Parent 144 0 R
+ /Prev 150 0 R
+ /Title (More features) >>
endobj
% 'Outline.7': class OutlineEntryObject
-147 0 obj
-<< /Dest [ 90 0 R
+152 0 obj
+<< /Dest [ 89 0 R
/XYZ
62.69291
- 388.6236
+ 566.4849
0 ]
- /Next 148 0 R
- /Parent 139 0 R
- /Prev 146 0 R
- /Title (A few notes about the underlying implementation) >>
+ /Next 153 0 R
+ /Parent 144 0 R
+ /Prev 151 0 R
+ /Title (A more realistic example) >>
endobj
% 'Outline.8': class OutlineEntryObject
-148 0 obj
-<< /Dest [ 97 0 R
+153 0 obj
+<< /Dest [ 100 0 R
/XYZ
62.69291
- 480.6236
+ 607.8236
0 ]
- /Next 149 0 R
- /Parent 139 0 R
- /Prev 147 0 R
- /Title (Custom annotation objects) >>
+ /Next 154 0 R
+ /Parent 144 0 R
+ /Prev 152 0 R
+ /Title (Advanced usage) >>
endobj
% 'Outline.9': class OutlineEntryObject
-149 0 obj
-<< /Dest [ 117 0 R
+154 0 obj
+<< /Dest [ 102 0 R
/XYZ
62.69291
- 524.6236
+ 671.8236
0 ]
- /Next 150 0 R
- /Parent 139 0 R
- /Prev 148 0 R
- /Title (plac vs argparse) >>
+ /Next 155 0 R
+ /Parent 144 0 R
+ /Prev 153 0 R
+ /Title (Custom annotation objects) >>
endobj
% 'Outline.10': class OutlineEntryObject
-150 0 obj
-<< /Dest [ 136 0 R
+155 0 obj
+<< /Dest [ 130 0 R
/XYZ
62.69291
- 705.0236
+ 717.0236
0 ]
- /Next 151 0 R
- /Parent 139 0 R
- /Prev 149 0 R
- /Title (The future) >>
+ /Next 156 0 R
+ /Parent 144 0 R
+ /Prev 154 0 R
+ /Title (plac vs argparse) >>
endobj
% 'Outline.11': class OutlineEntryObject
-151 0 obj
-<< /Dest [ 136 0 R
+156 0 obj
+<< /Dest [ 130 0 R
/XYZ
62.69291
- 594.0236
+ 228.0236
0 ]
- /Parent 139 0 R
- /Prev 150 0 R
+ /Next 157 0 R
+ /Parent 144 0 R
+ /Prev 155 0 R
+ /Title (The future) >>
+endobj
+% 'Outline.12': class OutlineEntryObject
+157 0 obj
+<< /Dest [ 141 0 R
+ /XYZ
+ 62.69291
+ 765.0236
+ 0 ]
+ /Parent 144 0 R
+ /Prev 156 0 R
/Title (Trivia: the story behind the name) >>
endobj
-% 'R152': class PDFPages
-152 0 obj
+% 'R158': class PDFPages
+158 0 obj
% page tree
-<< /Count 12
- /Kids [ 44 0 R
- 50 0 R
- 57 0 R
- 66 0 R
- 68 0 R
- 73 0 R
- 80 0 R
- 84 0 R
- 90 0 R
- 97 0 R
- 117 0 R
- 136 0 R ]
+<< /Count 13
+ /Kids [ 42 0 R
+ 54 0 R
+ 60 0 R
+ 65 0 R
+ 72 0 R
+ 76 0 R
+ 78 0 R
+ 85 0 R
+ 89 0 R
+ 100 0 R
+ 102 0 R
+ 130 0 R
+ 141 0 R ]
/Type /Pages >>
endobj
-% 'R153': class PDFStream
-153 0 obj
+% 'R159': class PDFStream
+159 0 obj
% page stream
-<< /Length 8466 >>
+<< /Length 8272 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
1 0 0 1 62.69291 693.0236 cm
q
-BT 1 0 0 1 0 57.64 Tm 34.89488 0 Td 24 TL /F2 20 Tf 0 0 0 rg (Parsing the Command Line the Easy Way:) Tj T* -28.9 0 Td (Introducing plac, the EasiestArgument Parser in) Tj T* 146.17 0 Td (the Python World) Tj T* -152.1649 0 Td ET
+BT 1 0 0 1 0 57.64 Tm 34.89488 0 Td 24 TL /F2 20 Tf 0 0 0 rg (Parsing the Command Line the Easy Way:) Tj T* -31.68 0 Td (Introducing plac, the Easiest Argument Parser in) Tj T* 148.95 0 Td (the Python World) Tj T* -152.1649 0 Td ET
Q
Q
q
@@ -2533,6 +2635,28 @@ q
1 0 0 1 6 3 cm
q
0 0 0 rg
+BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 9.68937 0 Td (Project page:) Tj T* -9.68937 0 Td ET
+Q
+Q
+q
+1 0 0 1 91.03937 3 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (http://micheles.googlecode.com/hg/plac/doc/plac.html) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 581.0236 cm
+0 0 0 rg
+BT /F3 10 Tf 12 TL ET
+q
+1 0 0 1 6 3 cm
+q
+0 0 0 rg
BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 16.91937 0 Td (Installation:) Tj T* -16.91937 0 Td ET
Q
Q
@@ -2547,7 +2671,7 @@ q
Q
Q
q
-1 0 0 1 62.69291 581.0236 cm
+1 0 0 1 62.69291 566.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -2568,23 +2692,23 @@ q
Q
Q
q
-1 0 0 1 62.69291 548.0236 cm
+1 0 0 1 62.69291 533.0236 cm
q
BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Contents) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 326.0236 cm
+1 0 0 1 62.69291 293.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
-1 0 0 1 0 201 cm
+1 0 0 1 0 219 cm
q
BT 1 0 0 1 0 4.82 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (The importance of scaling down) Tj T* ET
Q
Q
q
-1 0 0 1 397.8898 201 cm
+1 0 0 1 397.8898 219 cm
q
0 0 .501961 rg
0 0 .501961 RG
@@ -2592,9 +2716,23 @@ BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 66.44 0 Td (1) Tj T* -66.44 0 Td ET
Q
Q
q
+1 0 0 1 0 201 cm
+q
+BT 1 0 0 1 0 4.82 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Scripts with required arguments) Tj T* ET
+Q
+Q
+q
+1 0 0 1 397.8898 201 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 66.44 0 Td (2) Tj T* -66.44 0 Td ET
+Q
+Q
+q
1 0 0 1 0 183 cm
q
-BT 1 0 0 1 0 4.82 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Scripts with required positional arguments) Tj T* ET
+BT 1 0 0 1 0 4.82 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Scripts with default arguments) Tj T* ET
Q
Q
q
@@ -2602,13 +2740,13 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 66.44 0 Td (2) Tj T* -66.44 0 Td ET
+BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 66.44 0 Td (3) Tj T* -66.44 0 Td ET
Q
Q
q
1 0 0 1 0 165 cm
q
-BT 1 0 0 1 0 4.82 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Scritps with default arguments) Tj T* ET
+BT 1 0 0 1 0 4.82 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Scripts with options) Tj T* ET
Q
Q
q
@@ -2616,13 +2754,13 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 66.44 0 Td (3) Tj T* -66.44 0 Td ET
+BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 66.44 0 Td (5) Tj T* -66.44 0 Td ET
Q
Q
q
1 0 0 1 0 147 cm
q
-BT 1 0 0 1 0 4.82 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Options and flags) Tj T* ET
+BT 1 0 0 1 0 4.82 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Scripts with flags) Tj T* ET
Q
Q
q
@@ -2630,7 +2768,7 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 66.44 0 Td (4) Tj T* -66.44 0 Td ET
+BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 66.44 0 Td (6) Tj T* -66.44 0 Td ET
Q
Q
q
@@ -2644,7 +2782,7 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 66.44 0 Td (6) Tj T* -66.44 0 Td ET
+BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 66.44 0 Td (7) Tj T* -66.44 0 Td ET
Q
Q
q
@@ -2658,13 +2796,13 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 66.44 0 Td (7) Tj T* -66.44 0 Td ET
+BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 66.44 0 Td (8) Tj T* -66.44 0 Td ET
Q
Q
q
1 0 0 1 0 93 cm
q
-BT 1 0 0 1 0 4.82 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (A somewhat realistic example) Tj T* ET
+BT 1 0 0 1 0 4.82 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (A more realistic example) Tj T* ET
Q
Q
q
@@ -2672,13 +2810,13 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 66.44 0 Td (8) Tj T* -66.44 0 Td ET
+BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 66.44 0 Td (9) Tj T* -66.44 0 Td ET
Q
Q
q
1 0 0 1 0 75 cm
q
-BT 1 0 0 1 0 4.82 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (A few notes about the underlying implementation) Tj T* ET
+BT 1 0 0 1 0 4.82 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Advanced usage) Tj T* ET
Q
Q
q
@@ -2686,7 +2824,7 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 66.44 0 Td (9) Tj T* -66.44 0 Td ET
+BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 60.88 0 Td (10) Tj T* -60.88 0 Td ET
Q
Q
q
@@ -2700,7 +2838,7 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 60.88 0 Td (10) Tj T* -60.88 0 Td ET
+BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 60.88 0 Td (11) Tj T* -60.88 0 Td ET
Q
Q
q
@@ -2714,7 +2852,7 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 60.88 0 Td (11) Tj T* -60.88 0 Td ET
+BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 60.88 0 Td (12) Tj T* -60.88 0 Td ET
Q
Q
q
@@ -2742,34 +2880,28 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 60.88 0 Td (12) Tj T* -60.88 0 Td ET
+BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 60.88 0 Td (13) Tj T* -60.88 0 Td ET
Q
Q
q
Q
Q
q
-1 0 0 1 62.69291 293.0236 cm
+1 0 0 1 62.69291 260.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 239.0236 cm
-q
-BT 1 0 0 1 0 40.82 Tm 1.50936 Tw 12 TL /F1 10 Tf 0 0 0 rg (There is no want of command line arguments parsers in the Python world. The standard library alone) Tj T* 0 Tw 1.087126 Tw (contains three different modules: ) Tj 0 0 .501961 rg (getopt ) Tj 0 0 0 rg (\(from the stone age\), ) Tj 0 0 .501961 rg (optparse ) Tj 0 0 0 rg (\(from Python 2.3\) and ) Tj 0 0 .501961 rg (argparse) Tj T* 0 Tw .223735 Tw 0 0 0 rg (\(from Python 2.7\). All of them are quite powerful and especially ) Tj 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (is an industrial strength solution;) Tj T* 0 Tw (unfortunately, all of them feature a non-zero learning curve and a certain verbosity.) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 161.0236 cm
+1 0 0 1 62.69291 194.0236 cm
q
-BT 1 0 0 1 0 64.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 .048221 Tw (issue of scaling down. This is an old meme in the computing world: programs should address the common) Tj T* 0 Tw .08561 Tw (cases simply, simple things should be kept simple, while at the same keeping difficult things possible. ) Tj 0 0 .501961 rg (plac) Tj T* 0 Tw .846654 Tw 0 0 0 rg (adhere as much as possible to this philosophy and it is designed to handle well the simple cases, while) Tj T* 0 Tw (retaining the ability to handle complex cases by relying on the underlying power of ) Tj 0 0 .501961 rg (argparse) Tj 0 0 0 rg (.) Tj T* ET
+BT 1 0 0 1 0 52.82 Tm 1.50936 Tw 12 TL /F1 10 Tf 0 0 0 rg (There is no want of command line arguments parsers in the Python world. The standard library alone) Tj T* 0 Tw 1.087126 Tw (contains three different modules: ) Tj 0 0 .501961 rg (getopt ) Tj 0 0 0 rg (\(from the stone age\), ) Tj 0 0 .501961 rg (optparse ) Tj 0 0 0 rg (\(from Python 2.3\) and ) Tj 0 0 .501961 rg (argparse) Tj T* 0 Tw .223735 Tw 0 0 0 rg (\(from Python 2.7\). All of them are quite powerful and especially ) Tj 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (is an industrial strength solution;) Tj T* 0 Tw 1.40311 Tw (unfortunately, all of them feature a non-zero learning curve and a certain verbosity. They do not scale) Tj T* 0 Tw (down well enough, at least in my opinion.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 95.02362 cm
+1 0 0 1 62.69291 104.0236 cm
q
-BT 1 0 0 1 0 52.82 Tm .331235 Tw 12 TL /F1 10 Tf 0 0 0 rg (Technically ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (is just a simple wrapper over ) Tj 0 0 .501961 rg (argparse) Tj 0 0 0 rg (, hiding most of its complexity while retaining most ) Tj T* 0 Tw .047633 Tw (of its power. The complexity is removed by using a declarative interface instead of an imperative one. Still, ) Tj T* 0 Tw 1.962126 Tw 0 0 .501961 rg (plac ) Tj 0 0 0 rg (is surprisingly scalable upwards, even without using the underlying ) Tj 0 0 .501961 rg (argparse) Tj 0 0 0 rg (. I have been using ) Tj T* 0 Tw .567488 Tw (Python for 8 years and in my experience it is extremely unlikely that you will ever need to go beyond the ) Tj T* 0 Tw .599398 Tw (features provided by the declarative interface of ) Tj 0 0 .501961 rg (plac) Tj 0 0 0 rg (: they should be more than enough for 99.9% of the) Tj T* 0 Tw ET
+BT 1 0 0 1 0 76.82 Tm .051984 Tw 12 TL /F1 10 Tf 0 0 0 rg (It should not be necessary to stress the importance ) Tj 0 0 .501961 rg (scaling down) Tj 0 0 0 rg (; nevertheless most people are obsessed) Tj T* 0 Tw 1.385868 Tw (with features and concerned with the possibility of scaling up, whereas I think that we should be even) Tj T* 0 Tw .996457 Tw (more concerned with the issue of scaling down. This is an old meme in the computing world: programs) Tj T* 0 Tw 2.499984 Tw (should address the common cases simply, simple things should be kept simple, while at the same) Tj T* 0 Tw .535868 Tw (keeping difficult things possible. ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (adhere as much as possible to this philosophy and it is designed to) Tj T* 0 Tw 2.44686 Tw (handle well the simple cases, while retaining the ability to handle complex cases by relying on the) Tj T* 0 Tw (underlying power of ) Tj 0 0 .501961 rg (argparse) Tj 0 0 0 rg (.) Tj T* ET
Q
Q
q
@@ -2783,47 +2915,38 @@ Q
endstream
endobj
-% 'R154': class PDFStream
-154 0 obj
+% 'R160': class PDFStream
+160 0 obj
% page stream
-<< /Length 5294 >>
+<< /Length 5349 >>
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
+1 0 0 1 62.69291 693.0236 cm
q
-0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (typical use cases.) Tj T* ET
+BT 1 0 0 1 0 64.82 Tm 1.488221 Tw 12 TL /F1 10 Tf 0 0 0 rg (Technically ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (is just a simple wrapper over ) Tj 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (which hides most of its complexity by using a) Tj T* 0 Tw .203318 Tw (declarative interface: the argument parser is inferred rather than written down by imperatively. Still, ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (is) Tj T* 0 Tw .125984 Tw (surprisingly scalable upwards, even without using the underlying ) Tj 0 0 .501961 rg (argparse) Tj 0 0 0 rg (. I have been using Python for 8) Tj T* 0 Tw 1.618876 Tw (years and in my experience it is extremely unlikely that you will ever need to go beyond the features) Tj T* 0 Tw 1.776457 Tw (provided by the declarative interface of ) Tj 0 0 .501961 rg (plac) Tj 0 0 0 rg (: they should be more than enough for 99.9% of the use) Tj T* 0 Tw (cases.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 663.0236 cm
+1 0 0 1 62.69291 591.0236 cm
q
-BT 1 0 0 1 0 76.82 Tm .108443 Tw 12 TL /F1 10 Tf 0 0 .501961 rg (plac ) Tj 0 0 0 rg (is targetting programmers, sys-admins, scientists and in general people writing throw-away scripts for) Tj T* 0 Tw .242927 Tw (themselves, choosing to use a command line interface because it is the quick and simple. Such users are) Tj T* 0 Tw .205488 Tw (not interested in features, they are interested in a small learning curve: they just want to be able to write a) Tj T* 0 Tw 2.27436 Tw (simple command line tool from a simple specification, not to build a command line parser by hand.) Tj T* 0 Tw .699398 Tw (Unfortunately, the modules in the standard library forces them to go the hard way. They are designed to) Tj T* 0 Tw 2.80152 Tw (implement power user tools for programmers or system administrators, and they have a non-trivial) Tj T* 0 Tw (learning curve.) Tj T* ET
+BT 1 0 0 1 0 88.82 Tm 1.540888 Tw 12 TL /F1 10 Tf 0 0 .501961 rg (plac ) Tj 0 0 0 rg (is targetting especially unsophisticated users, programmers, sys-admins, scientists and in general) Tj T* 0 Tw .81284 Tw (people writing throw-away scripts for themselves, choosing the command line interface because it is the) Tj T* 0 Tw .471751 Tw (quick and simple. Such users are not interested in features, they are interested in a small learning curve:) Tj T* 0 Tw .984988 Tw (they just want to be able to write a simple command line tool from a simple specification, not to build a) Tj T* 0 Tw 1.091235 Tw (command line parser by hand. Unfortunately, the modules in the standard library forces them to go the) Tj T* 0 Tw .014104 Tw (hard way. They are designed to implement power user tools and they have a non-trivial learning curve. On) Tj T* 0 Tw 1.584104 Tw (the contrary, ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (is designed to be simple to use and extremely concise, as the examples below will) Tj T* 0 Tw (show.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 630.0236 cm
+1 0 0 1 62.69291 558.0236 cm
q
-BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Scripts with required positional arguments) Tj T* ET
+BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Scripts with required arguments) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 564.0236 cm
+1 0 0 1 62.69291 492.0236 cm
q
-BT 1 0 0 1 0 52.82 Tm .352209 Tw 12 TL /F1 10 Tf 0 0 0 rg (Let me start with the simplest possible thing: a script that takes a single argument and does something to) Tj T* 0 Tw 3.17686 Tw (it. It cannot get more trivial than that \(discarding the possibility of a script without command line) Tj T* 0 Tw .79881 Tw (arguments, where there is nothing to parse\), nevertheless it is a use case ) Tj /F5 10 Tf (extremely common) Tj /F1 10 Tf (: I need to) Tj T* 0 Tw .956988 Tw (write scripts like that nearly every day, I wrote hundreds of them in the last few years and I have never) Tj T* 0 Tw (been happy. Here is a typical example of code I have been writing by hand for years:) Tj T* ET
-Q
+BT 1 0 0 1 0 52.82 Tm .352209 Tw 12 TL /F1 10 Tf 0 0 0 rg (Let me start with the simplest possible thing: a script that takes a single argument and does something to) Tj T* 0 Tw 1.022485 Tw (it. It cannot get simpler than that, unless you consider a script without command line arguments, where) Tj T* 0 Tw .735488 Tw (there is nothing to parse. Still, it is a use case ) Tj /F5 10 Tf (extremely common) Tj /F1 10 Tf (: I need to write scripts like that nearly) Tj T* 0 Tw .486655 Tw (every day, I wrote hundreds of them in the last few years and I have never been happy. Here is a typical) Tj T* 0 Tw (example of code I have been writing by hand for years:) Tj T* ET
Q
-q
-1 0 0 1 62.69291 558.0236 cm
Q
q
-1 0 0 1 62.69291 376.8236 cm
-0 0 0 rg
-BT /F3 10 Tf 12 TL ET
-BT 1 0 0 1 0 2 Tm T* ET
-q
-1 0 0 1 20 0 cm
+1 0 0 1 62.69291 290.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -2833,38 +2956,24 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 448.6898 180 re B*
+n -6 -6 468.6898 192 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 161.71 Tm /F4 10 Tf 12 TL (# example1.py) Tj T* (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
+BT 1 0 0 1 0 173.71 Tm /F4 10 Tf 12 TL (# example1.py) Tj T* (def main\(dsn\):) Tj T* ( "Do something with the database") Tj T* ( print\(dsn\)) Tj T* ( # ...) 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
+1 0 0 1 62.69291 186.8236 cm
q
-1 0 0 1 62.69291 376.8236 cm
+BT 1 0 0 1 0 88.82 Tm .880651 Tw 12 TL /F1 10 Tf 0 0 0 rg (As you see the whole ) Tj /F4 10 Tf (if __name__ == '__main__' ) Tj /F1 10 Tf (block \(nine lines\) is essentially boilerplate that) Tj T* 0 Tw 1.67881 Tw (should not exists. Actually I think the language should recognize the main function and pass to it the) Tj T* 0 Tw 3.096905 Tw (command line arguments automatically; 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 /F5 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 .69881 Tw (does not help for this incredibly common use case. Using ) Tj 0 0 .501961 rg (getopt ) Tj 0 0 0 rg (and ) Tj 0 0 .501961 rg (optparse ) Tj 0 0 0 rg (does not help, since they) Tj T* 0 Tw .894104 Tw (are intended to manage options and not positional arguments; the ) Tj 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (module helps a bit and it is) Tj T* 0 Tw (able to reduce the boilerplate from nine lines to six lines:) Tj T* ET
Q
-q
-1 0 0 1 62.69291 274.8236 cm
-q
-BT 1 0 0 1 0 88.82 Tm .880651 Tw 12 TL /F1 10 Tf 0 0 0 rg (As you see the whole ) Tj /F4 10 Tf (if __name__ == '__main__' ) Tj /F1 10 Tf (block \(nine lines\) is essentially boilerplate that) Tj T* 0 Tw .66528 Tw (should not exists. Actually I think the Python language should recognize the main function and pass to it) Tj T* 0 Tw .04811 Tw (the command line arguments 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 /F5 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 1.037356 Tw (does not help for this use case, which may be trivial, but it is still incredibly common. Using ) Tj 0 0 .501961 rg (getopt ) Tj 0 0 0 rg (and) Tj T* 0 Tw 1.567984 Tw 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 268.8236 cm
Q
q
-1 0 0 1 62.69291 123.6236 cm
-0 0 0 rg
-BT /F3 10 Tf 12 TL ET
-BT 1 0 0 1 0 2 Tm T* ET
-q
-1 0 0 1 20 0 cm
+1 0 0 1 62.69291 93.62362 cm
q
q
1 0 0 1 0 0 cm
@@ -2874,28 +2983,15 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 448.6898 144 re B*
+n -6 -6 468.6898 84 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 125.71 Tm /F4 10 Tf 12 TL (# example2.py) Tj T* (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
+BT 1 0 0 1 0 65.71 Tm /F4 10 Tf 12 TL (# example2.py) Tj T* (def main\(dsn\):) Tj T* ( "Do something on the database") Tj T* ( print\(dsn\)) Tj T* ( # ...) Tj T* T* ET
Q
Q
Q
Q
-q
-Q
-Q
-q
-1 0 0 1 62.69291 123.6236 cm
-Q
-q
-1 0 0 1 62.69291 93.62362 cm
-q
-0 0 0 rg
-BT 1 0 0 1 0 16.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 ET
-Q
Q
q
1 0 0 1 56.69291 56.69291 cm
@@ -2908,35 +3004,48 @@ Q
endstream
endobj
-% 'R155': class PDFStream
-155 0 obj
+% 'R161': class PDFStream
+161 0 obj
% page stream
-<< /Length 4353 >>
+<< /Length 3933 >>
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
+1 0 0 1 62.69291 679.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 84 re B*
+Q
q
0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (it just feels too complex to instantiate a class and to define a parser by hand for such a trivial task.) Tj T* ET
+BT 1 0 0 1 0 65.71 Tm /F4 10 Tf 12 TL (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
-1 0 0 1 62.69291 723.0236 cm
+1 0 0 1 62.69291 623.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 (plac ) 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 (plac ) Tj 0 0 0 rg (module all you need to write is) Tj T* ET
+0 0 0 rg
+BT 1 0 0 1 0 40.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 2.206303 Tw (switch to Python 2.7, which at the time of this writing is just about to be released, for many years.) Tj T* 0 Tw .678488 Tw (Moreover, it just feels too complex to instantiate a class and to define a parser by hand for such a trivial) Tj T* 0 Tw (task.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 717.0236 cm
-Q
+1 0 0 1 62.69291 593.8236 cm
q
-1 0 0 1 62.69291 619.8236 cm
-0 0 0 rg
-BT /F3 10 Tf 12 TL ET
-BT 1 0 0 1 0 2 Tm T* ET
+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 (plac ) 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 (plac ) Tj 0 0 0 rg (module all you need to write is) Tj T* ET
+Q
+Q
q
-1 0 0 1 20 0 cm
+1 0 0 1 62.69291 476.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -2946,30 +3055,24 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 448.6898 96 re B*
+n -6 -6 468.6898 108 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 77.71 Tm /F4 10 Tf 12 TL (# example3.py) Tj T* (def main\(dsn\):) Tj T* ( "Do something with the database") Tj T* ( print\(dsn\)) Tj T* ( ) Tj T* (if __name__ == '__main__':) Tj T* ( import plac; plac.call\(main\)) Tj T* ET
+BT 1 0 0 1 0 89.71 Tm /F4 10 Tf 12 TL (# example3.py) Tj T* (def main\(dsn\):) Tj T* ( "Do something with the database") Tj T* ( print\(dsn\)) Tj T* ( # ...) Tj T* ( ) Tj T* (if __name__ == '__main__':) Tj T* ( import plac; plac.call\(main\)) Tj T* ET
Q
Q
Q
Q
Q
q
-Q
-Q
-q
-1 0 0 1 62.69291 619.8236 cm
-Q
-q
-1 0 0 1 62.69291 589.8236 cm
+1 0 0 1 62.69291 444.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 (plac ) 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 472.6236 cm
+1 0 0 1 62.69291 327.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -2990,34 +3093,26 @@ Q
Q
Q
q
-1 0 0 1 62.69291 452.6236 cm
+1 0 0 1 62.69291 307.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 (plac ) 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 419.6236 cm
+1 0 0 1 62.69291 274.4236 cm
q
-BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Scritps with default arguments) Tj T* ET
+BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Scripts with default arguments) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 401.6236 cm
+1 0 0 1 62.69291 244.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
+BT 1 0 0 1 0 16.82 Tm /F1 10 Tf 12 TL 1.33436 Tw (The need to have suitable defaults for command line arguments is quite common. For instance I have) Tj T* 0 Tw (encountered this use case at work hundreds of times:) Tj T* ET
Q
-q
-1 0 0 1 62.69291 395.6236 cm
Q
q
-1 0 0 1 62.69291 202.4236 cm
-0 0 0 rg
-BT /F3 10 Tf 12 TL ET
-BT 1 0 0 1 0 2 Tm T* ET
-q
-1 0 0 1 20 0 cm
+1 0 0 1 62.69291 91.22362 cm
q
q
1 0 0 1 0 0 cm
@@ -3027,29 +3122,60 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 448.6898 192 re B*
+n -6 -6 468.6898 144 re B*
Q
q
-BT 1 0 0 1 0 173.71 Tm 12 TL /F4 10 Tf 0 0 0 rg (# example4.py) Tj T* (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* ( 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
+BT 1 0 0 1 0 125.71 Tm 12 TL /F4 10 Tf 0 0 0 rg (# example4.py) Tj T* (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* ( args = sys.argv[1:]) Tj T* ( if not args:) Tj T* ET
Q
Q
Q
Q
Q
q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 238.1649 0 Td (3) Tj T* -238.1649 0 Td ET
Q
Q
+
+endstream
+
+endobj
+% 'R162': class PDFStream
+162 0 obj
+% page stream
+<< /Length 4252 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 703.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 60 re B*
+Q
q
-1 0 0 1 62.69291 202.4236 cm
+BT 1 0 0 1 0 41.71 Tm 12 TL /F4 10 Tf 0 0 0 rg ( 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
-1 0 0 1 62.69291 184.4236 cm
+1 0 0 1 62.69291 635.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 (plac ) Tj 0 0 0 rg (the entire ) Tj /F4 10 Tf (__main__ ) Tj /F1 10 Tf (block reduces to the usual two lines:) Tj T* ET
+BT 1 0 0 1 0 52.82 Tm 1.138935 Tw 12 TL /F1 10 Tf 0 0 0 rg (Here I want to perform a query on a database table, by extracting the today's data: it makes sense for) Tj T* 0 Tw .299988 Tw /F4 10 Tf (today ) Tj /F1 10 Tf (to be a default argument. If there is a most used table \(in this example a table called ) Tj /F4 10 Tf ('product') Tj /F1 10 Tf (\)) Tj T* 0 Tw 2.828735 Tw (it also makes sense to make it a default argument. Performing the parsing of the command lines) Tj T* 0 Tw .083735 Tw (arguments by hand takes 8 ugly lines of boilerplate \(using ) Tj 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (would require about the same number) Tj T* 0 Tw (of lines\). With ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (the entire ) Tj /F4 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 139.2236 cm
+1 0 0 1 62.69291 590.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -3070,31 +3196,14 @@ Q
Q
Q
q
-1 0 0 1 62.69291 119.2236 cm
+1 0 0 1 62.69291 570.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 56.69291 56.69291 cm
-q
-0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 238.1649 0 Td (3) Tj T* -238.1649 0 Td ET
+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 we get the usage message for free:) Tj T* ET
Q
Q
-
-endstream
-
-endobj
-% 'R156': class PDFStream
-156 0 obj
-% page stream
-<< /Length 4724 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 643.8236 cm
+1 0 0 1 62.69291 441.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -3108,28 +3217,20 @@ n -6 -6 468.6898 120 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 101.71 Tm /F4 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
+BT 1 0 0 1 0 101.71 Tm /F4 10 Tf 12 TL (usage: example5.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 611.8236 cm
+1 0 0 1 62.69291 409.4236 cm
q
BT 1 0 0 1 0 16.82 Tm .396235 Tw 12 TL /F1 10 Tf 0 0 .501961 rg (plac ) 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 SQL scripts:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 605.8236 cm
-Q
-q
-1 0 0 1 62.69291 436.6236 cm
-0 0 0 rg
-BT /F3 10 Tf 12 TL ET
-BT 1 0 0 1 0 2 Tm T* ET
-q
-1 0 0 1 20 0 cm
+1 0 0 1 62.69291 220.2236 cm
q
q
1 0 0 1 0 0 cm
@@ -3139,29 +3240,23 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 442.6898 168 re B*
+n -6 -6 468.6898 180 re B*
Q
q
-BT 1 0 0 1 0 149.71 Tm 12 TL /F4 10 Tf 0 0 0 rg (# example6.py) Tj T* (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
+BT 1 0 0 1 0 161.71 Tm 12 TL /F4 10 Tf 0 0 0 rg (# example6.py) Tj T* (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* ( # ...) 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
+1 0 0 1 62.69291 188.2236 cm
q
-1 0 0 1 62.69291 436.6236 cm
-Q
-q
-1 0 0 1 62.69291 406.6236 cm
-q
-BT 1 0 0 1 0 16.82 Tm .563876 Tw 12 TL /F1 10 Tf 0 0 0 rg (Using ) Tj 0 0 .501961 rg (plac) Tj 0 0 0 rg (, you can just replace the ) Tj /F4 10 Tf (__main__ ) Tj /F1 10 Tf (block with the usual two lines \(I have defined an Emacs) Tj T* 0 Tw (keybinding for them\) and you get the following usage message:) Tj T* ET
+BT 1 0 0 1 0 16.82 Tm .563876 Tw 12 TL /F1 10 Tf 0 0 0 rg (Using ) Tj 0 0 .501961 rg (plac) Tj 0 0 0 rg (, you can just replace the ) Tj /F4 10 Tf (__main__ ) Tj /F1 10 Tf (block with the usual two lines \(I have defined an Emacs) Tj T* 0 Tw (keybinding for them\) and then you get the following nice usage message:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 289.4236 cm
+1 0 0 1 62.69291 95.02362 cm
q
q
1 0 0 1 0 0 cm
@@ -3171,79 +3266,86 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 108 re B*
+n -6 -6 468.6898 84 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 89.71 Tm /F4 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
+BT 1 0 0 1 0 65.71 Tm /F4 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* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 245.4236 cm
+1 0 0 1 56.69291 56.69291 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 /F5 10 Tf (plac 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 (plac) Tj 0 0 0 rg (: if my intent is) Tj T* 0 Tw (clear, let's the machine take care of the details.) Tj T* ET
+0 0 0 rg
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 238.1649 0 Td (4) Tj T* -238.1649 0 Td ET
Q
Q
+
+endstream
+
+endobj
+% 'R163': class PDFStream
+163 0 obj
+% page stream
+<< /Length 5195 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 727.8236 cm
+q
+q
+1 0 0 1 0 0 cm
q
-1 0 0 1 62.69291 212.4236 cm
+1 0 0 1 6.6 6.6 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
+.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 /F4 10 Tf 12 TL (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 122.4236 cm
+1 0 0 1 62.69291 683.8236 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 have written \(certainly 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 ) Tj 0 0 .501961 rg (OptionParser) Tj 0 0 0 rg (.) Tj T* ET
+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 /F5 10 Tf (plac is able to figure out the command line arguments) Tj T* 0 Tw .899988 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 (plac) Tj 0 0 0 rg (: if the intent is) Tj T* 0 Tw (clear, let's the machine take care of the details.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 92.42362 cm
+1 0 0 1 62.69291 650.8236 cm
q
-BT 1 0 0 1 0 16.82 Tm .476098 Tw 12 TL /F1 10 Tf 0 0 .501961 rg (plac ) 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 ET
+BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Scripts with options) Tj T* ET
Q
Q
q
-1 0 0 1 56.69291 56.69291 cm
+1 0 0 1 62.69291 560.8236 cm
q
-0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 238.1649 0 Td (4) Tj T* -238.1649 0 Td ET
+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.02311 Tw (a hundred\), compared to the number of scripts with positional arguments I wrote \(certainly more than a) Tj T* 0 Tw .177045 Tw (thousand of them\). Still, this use case cannot be neglected. The standard library modules \(all of them\) are) Tj T* 0 Tw 2.30686 Tw (quite verbose when it comes to specifying the options and frankly I have never used them directly.) Tj T* 0 Tw 3.10561 Tw (Instead, I have always relied on an old recipe of mine, the ) Tj 0 0 .501961 rg (optionparse ) Tj 0 0 0 rg (recipe, which provides a) Tj T* 0 Tw 2.369982 Tw (convenient wrapper over ) Tj 0 0 .501961 rg (optionparse) Tj 0 0 0 rg (. Alternatively, in the simplest cases, I have just performed the) Tj T* 0 Tw (parsing by hand.) Tj T* ET
Q
Q
-
-endstream
-
-endobj
-% 'R157': class PDFStream
-157 0 obj
-% page stream
-<< /Length 5011 >>
-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
+1 0 0 1 62.69291 518.8236 cm
q
-BT 1 0 0 1 0 4.82 Tm 12 TL /F1 10 Tf 0 0 0 rg (extracts it from the signature of the ) Tj /F4 10 Tf (main ) Tj /F1 10 Tf (function.) Tj T* ET
+BT 1 0 0 1 0 28.82 Tm .476098 Tw 12 TL /F1 10 Tf 0 0 .501961 rg (plac ) 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 /F4 10 Tf (main ) Tj /F1 10 Tf (function.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 723.0236 cm
+1 0 0 1 62.69291 488.8236 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 /F5 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 717.0236 cm
-Q
-q
-1 0 0 1 62.69291 607.8236 cm
-0 0 0 rg
-BT /F3 10 Tf 12 TL ET
-BT 1 0 0 1 0 2 Tm T* ET
-q
-1 0 0 1 20 0 cm
+1 0 0 1 62.69291 371.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -3253,7 +3355,7 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 448.6898 108 re B*
+n -6 -6 468.6898 108 re B*
Q
q
0 0 0 rg
@@ -3264,19 +3366,13 @@ Q
Q
Q
q
-Q
-Q
+1 0 0 1 62.69291 303.6236 cm
q
-1 0 0 1 62.69291 607.8236 cm
-Q
-q
-1 0 0 1 62.69291 541.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 /F4 10 Tf (command ) Tj /F1 10 Tf (has been annotated with the tuple ) Tj /F4 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 (plac ) Tj 0 0 0 rg (that ) Tj /F4 10 Tf (command ) Tj /F1 10 Tf (is an option and that it can be abbreviated with the letter ) Tj /F4 10 Tf (c) Tj /F1 10 Tf (. Of course,) Tj T* 0 Tw .89284 Tw (the long option format \() Tj /F4 10 Tf (--command=) Tj /F1 10 Tf (\) comes from the argument name. The resulting usage message is) Tj T* 0 Tw (the following:) Tj T* ET
+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 /F4 10 Tf (command ) Tj /F1 10 Tf (has been annotated with the tuple ) Tj /F4 10 Tf (\("SQL query", 'option',) Tj T* 0 Tw .358409 Tw ('c'\)) Tj /F1 10 Tf (: the first string is the help string which will appear in the usage message, the second string tell ) Tj 0 0 .501961 rg (plac) Tj T* 0 Tw .560988 Tw 0 0 0 rg (that ) Tj /F4 10 Tf (command ) Tj /F1 10 Tf (is an option and the third string that it can be abbreviated with the letter ) Tj /F4 10 Tf (c) Tj /F1 10 Tf (. Of course, the) Tj T* 0 Tw .89284 Tw (long option format \() Tj /F4 10 Tf (--command=) Tj /F1 10 Tf (\) comes from the argument name. The resulting usage message is the) Tj T* 0 Tw (following:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 400.6236 cm
+1 0 0 1 62.69291 174.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -3286,25 +3382,25 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 132 re B*
+n -6 -6 468.6898 120 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 113.71 Tm /F4 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
+BT 1 0 0 1 0 101.71 Tm /F4 10 Tf 12 TL (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 380.6236 cm
+1 0 0 1 62.69291 154.4236 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 299.4236 cm
+1 0 0 1 62.69291 97.22362 cm
q
q
1 0 0 1 0 0 cm
@@ -3314,65 +3410,89 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 72 re B*
+n -6 -6 468.6898 48 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 53.71 Tm /F4 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
+BT 1 0 0 1 0 29.71 Tm /F4 10 Tf 12 TL ($ python3 example8.py -c"select * from table" dsn) Tj T* (executing select * from table on dsn) Tj T* T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 267.4236 cm
+1 0 0 1 56.69291 56.69291 cm
q
-BT 1 0 0 1 0 16.82 Tm 1.34104 Tw 12 TL /F1 10 Tf 0 0 0 rg (Notice that if the option is not passed, the variable ) Tj /F4 10 Tf (command ) Tj /F1 10 Tf (will get the value ) Tj /F4 10 Tf (None) Tj /F1 10 Tf (. It is possible to) Tj T* 0 Tw (specify a non-trivial default for an option. Here is an example:) Tj T* ET
-Q
+0 0 0 rg
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 238.1649 0 Td (5) Tj T* -238.1649 0 Td ET
Q
-q
-1 0 0 1 62.69291 261.4236 cm
Q
+
+endstream
+
+endobj
+% 'R164': class PDFStream
+164 0 obj
+% page stream
+<< /Length 5329 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.6378 178.6719 cm
-0 0 0 rg
-BT /F3 10 Tf 12 TL ET
-BT 1 0 0 1 0 2 Tm T* ET
-q
-1 0 0 1 20 0 cm
+1 0 0 1 62.69291 727.8236 cm
q
q
-.971265 0 0 .971265 0 0 cm
+1 0 0 1 0 0 cm
q
-1 0 0 1 6.6 6.795265 cm
+1 0 0 1 6.6 6.6 cm
q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 462 84 re B*
+n -6 -6 468.6898 36 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 65.71 Tm /F4 10 Tf 12 TL (# example8_.py) Tj T* (def main\(dsn, command: \("SQL query", 'option', 'c'\)='select * from table'\):) Tj T* ( print\('executing %r on %s' % \(command, dsn\)\)) Tj T* T* (if __name__ == '__main__':) Tj T* ( import clap; clap.call\(main\)) Tj T* ET
+BT 1 0 0 1 0 17.71 Tm /F4 10 Tf 12 TL ($ 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 695.8236 cm
+q
+BT 1 0 0 1 0 16.82 Tm 1.34104 Tw 12 TL /F1 10 Tf 0 0 0 rg (Notice that if the option is not passed, the variable ) Tj /F4 10 Tf (command ) Tj /F1 10 Tf (will get the value ) Tj /F4 10 Tf (None) Tj /F1 10 Tf (. It is possible to) Tj T* 0 Tw (specify a non-trivial default for an option. Here is an example:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 178.6719 cm
+1 0 0 1 62.69291 602.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 84 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 65.71 Tm /F4 10 Tf 12 TL (# example8_.py) Tj T* (def main\(dsn, command: \("SQL query", 'option', 'c'\)='select * from table'\):) Tj T* ( print\('executing %r on %s' % \(command, dsn\)\)) Tj T* T* (if __name__ == '__main__':) Tj T* ( import plac; plac.call\(main\)) Tj T* ET
+Q
+Q
+Q
+Q
Q
q
-1 0 0 1 62.69291 160.6719 cm
+1 0 0 1 62.69291 582.6236 cm
q
BT 1 0 0 1 0 4.82 Tm 12 TL /F1 10 Tf 0 0 0 rg (Now if you do not pass the ) Tj /F4 10 Tf (command option) Tj /F1 10 Tf (, the default query will be executed:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 115.4719 cm
+1 0 0 1 62.69291 537.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -3386,38 +3506,21 @@ n -6 -6 468.6898 36 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 17.71 Tm /F4 10 Tf 12 TL ($ python article/example8_.py dsn) Tj T* (executing 'select * from table' on dsn) Tj T* ET
+BT 1 0 0 1 0 17.71 Tm /F4 10 Tf 12 TL ($ python example8_.py dsn) Tj T* (executing 'select * from table' on dsn) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 95.47188 cm
+1 0 0 1 62.69291 517.4236 cm
q
0 0 0 rg
BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (Positional argument can be annotated too:) Tj T* ET
Q
Q
q
-1 0 0 1 56.69291 56.69291 cm
-q
-0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 238.1649 0 Td (5) Tj T* -238.1649 0 Td ET
-Q
-Q
-
-endstream
-
-endobj
-% 'R158': class PDFStream
-158 0 obj
-% page stream
-<< /Length 5429 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
-q
-1 0 0 1 62.69291 715.8236 cm
+1 0 0 1 62.69291 460.2236 cm
q
q
1 0 0 1 0 0 cm
@@ -3438,13 +3541,20 @@ Q
Q
Q
q
-1 0 0 1 62.69291 647.8236 cm
+1 0 0 1 62.69291 392.2236 cm
q
-BT 1 0 0 1 0 52.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 .112339 Tw (practicality beats purity, so ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (is smart enough to convert help messages into tuples; in other words, you) Tj T* 0 Tw 1.706647 Tw (can just write ) Tj /F4 10 Tf ("Database dsn" ) Tj /F1 10 Tf (instead of ) Tj /F4 10 Tf (\("Database dsn", 'positional', None\)) Tj /F1 10 Tf (. In both) Tj T* 0 Tw 2.044431 Tw (cases the usage message will show a nice help string on the right hand side of the ) Tj /F4 10 Tf (dsn ) Tj /F1 10 Tf (positional) Tj T* 0 Tw (argument. varargs \(starred-arguments\) can also be annotated:) Tj T* ET
+BT 1 0 0 1 0 52.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 .112339 Tw (practicality beats purity, so ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (is smart enough to convert help messages into tuples; in other words, you) Tj T* 0 Tw 1.706647 Tw (can just write ) Tj /F4 10 Tf ("Database dsn" ) Tj /F1 10 Tf (instead of ) Tj /F4 10 Tf (\("Database dsn", 'positional', None\)) Tj /F1 10 Tf (. In both) Tj T* 0 Tw 2.044431 Tw (cases the usage message will show a nice help string on the right hand side of the ) Tj /F4 10 Tf (dsn ) Tj /F1 10 Tf (positional) Tj T* 0 Tw (argument.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 602.6236 cm
+1 0 0 1 62.69291 374.2236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (I should also notice that varargs \(starred-arguments\) can be annotated too; here is an example:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 329.0236 cm
q
q
1 0 0 1 0 0 cm
@@ -3465,13 +3575,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 582.6236 cm
+1 0 0 1 62.69291 309.0236 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 (plac) Tj 0 0 0 rg (, which will recognize the help strings for both ) Tj /F4 10 Tf (dsn ) Tj /F1 10 Tf (and ) Tj /F4 10 Tf (scripts) Tj /F1 10 Tf (:) Tj T* ET
+BT 1 0 0 1 0 4.82 Tm 12 TL /F1 10 Tf 0 0 0 rg (This is a valid signature for ) Tj 0 0 .501961 rg (plac) Tj 0 0 0 rg (, which will recognize the help strings for both ) Tj /F4 10 Tf (dsn ) Tj /F1 10 Tf (and ) Tj /F4 10 Tf (scripts) Tj /F1 10 Tf (:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 525.4236 cm
+1 0 0 1 62.69291 251.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -3492,13 +3602,57 @@ Q
Q
Q
q
-1 0 0 1 62.69291 493.4236 cm
+1 0 0 1 62.69291 218.8236 cm
+q
+BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Scripts with flags) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 188.8236 cm
q
BT 1 0 0 1 0 16.82 Tm .765868 Tw 12 TL /F1 10 Tf 0 0 .501961 rg (plac ) Tj 0 0 0 rg (also recognizes flags, i.e. boolean options which are ) Tj /F4 10 Tf (True ) Tj /F1 10 Tf (if they are passed to the command line) Tj T* 0 Tw (and ) Tj /F4 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 448.2236 cm
+1 0 0 1 62.69291 98.65078 cm
+q
+q
+.96447 0 0 .96447 0 0 cm
+q
+1 0 0 1 6.6 6.843137 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 486 84 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 65.71 Tm /F4 10 Tf 12 TL (# example9.py) Tj T* T* (def main\(verbose: \('prints more info', 'flag', 'v'\), dsn: 'connection string'\):) Tj T* ( if verbose:) Tj T* ( print\('connecting to %s' % dsn\)) Tj T* ( # ...) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 238.1649 0 Td (6) Tj T* -238.1649 0 Td ET
+Q
+Q
+
+endstream
+
+endobj
+% 'R165': class PDFStream
+165 0 obj
+% page stream
+<< /Length 4877 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 715.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -3508,18 +3662,18 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 36 re B*
+n -6 -6 468.6898 48 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 17.71 Tm /F4 10 Tf 12 TL ($ python3 example9.py -v dsn) Tj T* (connecting to dsn) Tj T* ET
+BT 1 0 0 1 0 29.71 Tm /F4 10 Tf 12 TL T* (if __name__ == '__main__':) Tj T* ( import plac; plac.call\(main\)) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 319.0236 cm
+1 0 0 1 62.69291 586.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -3540,48 +3694,80 @@ Q
Q
Q
q
-1 0 0 1 62.69291 275.0236 cm
+1 0 0 1 62.69291 541.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 /F4 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 497.4236 cm
q
BT 1 0 0 1 0 28.82 Tm .31408 Tw 12 TL /F1 10 Tf 0 0 0 rg (Notice that it is an error trying to specify a default for flags: the default value for a flag is always ) Tj /F4 10 Tf (False) Tj /F1 10 Tf (. If) Tj T* 0 Tw 2.652485 Tw (you feel the need to implement non-boolean flags, you should use an option with two choices, as) Tj T* 0 Tw (explained in the "more features" section.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 209.0236 cm
+1 0 0 1 62.69291 431.4236 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.895433 Tw (Flag-Option-Required-Default \(FORD\) convention: in the ) Tj /F4 10 Tf (main ) Tj /F1 10 Tf (function write first the flag arguments,) Tj T* 0 Tw .881235 Tw (then the option arguments, then the required arguments and finally the default arguments. This is just a) Tj T* 0 Tw .110574 Tw (convention and you are not forced to use it, except for the default arguments \(including the varargs\) which) Tj T* 0 Tw (must stay at the end since it is required by the Python syntax.) Tj T* ET
+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.895433 Tw (Flag-Option-Required-Default \(FORD\) convention: in the ) Tj /F4 10 Tf (main ) Tj /F1 10 Tf (function write first the flag arguments,) Tj T* 0 Tw .881235 Tw (then the option arguments, then the required arguments and finally the default arguments. This is just a) Tj T* 0 Tw .110574 Tw (convention and you are not forced to use it, except for the default arguments \(including the varargs\) which) Tj T* 0 Tw (must stay at the end as it is required by the Python syntax.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 176.0236 cm
+1 0 0 1 62.69291 398.4236 cm
q
BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (plac for Python 2.X users) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 122.0236 cm
+1 0 0 1 62.69291 332.4236 cm
q
-BT 1 0 0 1 0 40.82 Tm .211807 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. It will take years) Tj T* 0 Tw 1.269988 Tw (before we even think to migrate to Python 3. I am pretty much sure most Pythonistas are in the same) Tj T* 0 Tw .867318 Tw (situation. Therefore ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (provides a way to work with function annotations even in Python 2.X \(including) Tj T* 0 Tw (Python 2.3\). There is no magic involved; you just need to add the annotations by hand. For instance) Tj T* ET
+BT 1 0 0 1 0 52.82 Tm .211807 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. It will take years) Tj T* 0 Tw .304724 Tw (before we think to migrate to Python 3. I am pretty much sure most Pythonistas are in the same situation.) Tj T* 0 Tw 1.459984 Tw (Therefore ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (provides a way to work with function annotations even in Python 2.X \(including Python) Tj T* 0 Tw .226098 Tw (2.3\). There is no magic involved; you just need to add the annotations by hand. For instance the annotate) Tj T* 0 Tw (function declaration) Tj T* ET
Q
Q
q
-1 0 0 1 56.69291 56.69291 cm
+1 0 0 1 62.69291 287.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 36 re B*
+Q
q
0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 238.1649 0 Td (6) Tj T* -238.1649 0 Td ET
+BT 1 0 0 1 0 17.71 Tm /F4 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 267.2236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (is equivalent to the following code:) Tj T* ET
Q
Q
-
-endstream
-
-endobj
-% 'R159': class PDFStream
-159 0 obj
-% page stream
-<< /Length 5824 >>
-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
+1 0 0 1 62.69291 186.0236 cm
q
q
1 0 0 1 0 0 cm
@@ -3591,25 +3777,24 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 24 re B*
+n -6 -6 468.6898 72 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 5.71 Tm /F4 10 Tf 12 TL (def main\(dsn: "Database dsn", *scripts: "SQL scripts"\):) Tj T* ET
+BT 1 0 0 1 0 53.71 Tm /F4 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 719.8236 cm
+1 0 0 1 62.69291 142.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
+BT 1 0 0 1 0 28.82 Tm .536098 Tw 12 TL /F1 10 Tf 0 0 0 rg (One should be careful to match the keys of the annotation 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 /F4 10 Tf (plac.annotations ) Tj /F1 10 Tf (decorator that performs the check for you:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 638.6236 cm
+1 0 0 1 62.69291 96.82362 cm
q
q
1 0 0 1 0 0 cm
@@ -3619,24 +3804,35 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 72 re B*
+n -6 -6 468.6898 36 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 53.71 Tm /F4 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
+BT 1 0 0 1 0 17.71 Tm /F4 10 Tf 12 TL (@plac.annotations\() Tj T* ( dsn="Database dsn",) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 594.6236 cm
+1 0 0 1 56.69291 56.69291 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 /F4 10 Tf (plac.annotations ) Tj /F1 10 Tf (decorator that performs the check for you.) Tj T* ET
+0 0 0 rg
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 238.1649 0 Td (7) Tj T* -238.1649 0 Td ET
Q
Q
+
+endstream
+
+endobj
+% 'R166': class PDFStream
+166 0 obj
+% page stream
+<< /Length 5487 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 513.4236 cm
+1 0 0 1 62.69291 715.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -3646,39 +3842,39 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 72 re B*
+n -6 -6 468.6898 48 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 53.71 Tm /F4 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
+BT 1 0 0 1 0 29.71 Tm /F4 10 Tf 12 TL ( 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 469.4236 cm
+1 0 0 1 62.69291 683.8236 cm
q
-BT 1 0 0 1 0 28.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 /F4 10 Tf (X >) Tj (= 4 ) Tj /F1 10 Tf (and I will use the) Tj T* 0 Tw 1.574983 Tw /F4 10 Tf (plac.annotations ) Tj /F1 10 Tf (decorator. Notice however that the tests for ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (are supposed to run even with) Tj T* 0 Tw (Python 2.3.) Tj T* ET
+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 /F4 10 Tf (X >) Tj (= 4 ) Tj /F1 10 Tf (and I will use the) Tj T* 0 Tw /F4 10 Tf (plac.annotations ) Tj /F1 10 Tf (decorator. Notice however that the tests for ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (runs even on Python 2.3.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 436.4236 cm
+1 0 0 1 62.69291 650.8236 cm
q
BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (More features) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 382.4236 cm
+1 0 0 1 62.69291 596.8236 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 plac is to have a learning curve of ) Tj /F5 10 Tf (minutes) Tj /F1 10 Tf (, compared to the learning curve of ) Tj /F5 10 Tf (hours ) Tj /F1 10 Tf (of) Tj T* 0 Tw .412765 Tw 0 0 .501961 rg (argparse) Tj 0 0 0 rg (. That does not mean that I have removed all the features of ) Tj 0 0 .501961 rg (argparse) Tj 0 0 0 rg (. Actually a lot of ) Tj 0 0 .501961 rg (argparse) Tj T* 0 Tw .104987 Tw 0 0 0 rg (power persists in ) Tj 0 0 .501961 rg (plac) Tj 0 0 0 rg (. Until now, I have only showed simple annotations, but in general an annotation is a) Tj T* 0 Tw (5-tuple of the form) Tj T* ET
+BT 1 0 0 1 0 40.82 Tm .486179 Tw 12 TL /F1 10 Tf 0 0 0 rg (Even if one of the goals of plac is to have a learning curve of ) Tj /F5 10 Tf (minutes) Tj /F1 10 Tf (, compared to the learning curve of) Tj T* 0 Tw 1.356303 Tw /F5 10 Tf (hours ) Tj /F1 10 Tf (of ) Tj 0 0 .501961 rg (argparse) Tj 0 0 0 rg (, it does not mean that I have removed all the features of ) Tj 0 0 .501961 rg (argparse) Tj 0 0 0 rg (. Actually a lot of) Tj T* 0 Tw 1.71686 Tw 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (power persists in ) Tj 0 0 .501961 rg (plac) Tj 0 0 0 rg (. Until now, I have only showed simple annotations, but in general an) Tj T* 0 Tw (annotation is a 5-tuple of the form) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 376.4236 cm
+1 0 0 1 62.69291 590.8236 cm
Q
q
-1 0 0 1 62.69291 364.4236 cm
+1 0 0 1 62.69291 578.8236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
BT 1 0 0 1 0 2 Tm T* ET
@@ -3693,94 +3889,68 @@ q
Q
Q
q
-1 0 0 1 62.69291 364.4236 cm
+1 0 0 1 62.69291 578.8236 cm
Q
q
-1 0 0 1 62.69291 322.4236 cm
+1 0 0 1 62.69291 536.8236 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 /F4 10 Tf (help ) Tj /F1 10 Tf (is the help message, ) Tj /F4 10 Tf (kind ) Tj /F1 10 Tf (is one of {"flag", "option ", "positional"}, ) Tj /F4 10 Tf (abbrev ) Tj /F1 10 Tf (is a) Tj T* 0 Tw 2.203735 Tw (one-character string, ) Tj /F4 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 /F4 10 Tf (metavar ) Tj /F1 10 Tf (is a string.) Tj T* ET
+BT 1 0 0 1 0 28.82 Tm 1.068735 Tw 12 TL /F1 10 Tf 0 0 0 rg (where ) Tj /F4 10 Tf (help ) Tj /F1 10 Tf (is the help message, ) Tj /F4 10 Tf (kind ) Tj /F1 10 Tf (is a string in the set { ) Tj /F4 10 Tf ("flag") Tj /F1 10 Tf (, ) Tj /F4 10 Tf ("option") Tj /F1 10 Tf (, ) Tj /F4 10 Tf ("positional") Tj /F1 10 Tf (},) Tj T* 0 Tw 1.711163 Tw /F4 10 Tf (abbrev ) Tj /F1 10 Tf (is a one-character string, ) Tj /F4 10 Tf (type ) Tj /F1 10 Tf (is a callable taking a string in input, ) Tj /F4 10 Tf (choices ) Tj /F1 10 Tf (is a discrete) Tj T* 0 Tw (sequence of values and ) Tj /F4 10 Tf (metavar ) Tj /F1 10 Tf (is a string.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 292.4236 cm
+1 0 0 1 62.69291 506.8236 cm
q
-BT 1 0 0 1 0 16.82 Tm .006654 Tw 12 TL /F4 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 /F4 10 Tf (type=None) Tj /F1 10 Tf (.) Tj T* ET
+BT 1 0 0 1 0 16.82 Tm 1.05061 Tw 12 TL /F4 10 Tf 0 0 0 rg (type ) Tj /F1 10 Tf (is used to automagically convert the command line arguments from the string type to any Python) Tj T* 0 Tw (type; by default there is no convertion and ) Tj /F4 10 Tf (type=None) Tj /F1 10 Tf (.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 262.4236 cm
+1 0 0 1 62.69291 476.8236 cm
q
BT 1 0 0 1 0 16.82 Tm 2.904692 Tw 12 TL /F4 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 /F4 10 Tf (choices=None) Tj /F1 10 Tf (.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 220.4236 cm
+1 0 0 1 62.69291 434.8236 cm
q
-BT 1 0 0 1 0 28.82 Tm 1.071751 Tw 12 TL /F4 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 .787988 Tw (metavar is equal to the name of the argument, unless the argument has a default and in such a case is) Tj T* 0 Tw (equal to the stringified form of the default.) Tj T* ET
+BT 1 0 0 1 0 28.82 Tm 1.071751 Tw 12 TL /F4 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 1.056654 Tw (metavar is ) Tj /F4 10 Tf (None) Tj /F1 10 Tf (: this means that the name in the usage message is the same as the argument name,) Tj T* 0 Tw (unless the argument has a default and in such a case is equal to the stringified form of the default.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 202.4236 cm
+1 0 0 1 62.69291 416.8236 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 many of the features \(shamelessly stolen from the ) Tj 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (documentation\):) Tj T* ET
+BT 1 0 0 1 0 4.82 Tm 12 TL /F1 10 Tf 0 0 0 rg (Here is an example showing many of the features \(taken 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 196.4236 cm
-Q
-q
-1 0 0 1 62.69291 88.86614 cm
-0 0 0 rg
-BT /F3 10 Tf 12 TL ET
-BT 1 0 0 1 0 2 Tm T* ET
-q
-1 0 0 1 20 0 cm
+1 0 0 1 62.69291 208.4467 cm
q
q
-.922464 0 0 .922464 0 0 cm
+.976496 0 0 .976496 0 0 cm
q
-1 0 0 1 6.6 7.154749 cm
+1 0 0 1 6.6 6.758862 cm
q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 480 96 re B*
+n -6 -6 480 204 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 77.71 Tm /F4 10 Tf 12 TL (# example10.py) Tj T* (import plac) Tj T* T* (@plac.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* ET
-Q
+BT 1 0 0 1 0 185.71 Tm /F4 10 Tf 12 TL (# example10.py) Tj T* (import plac) Tj T* T* (@plac.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* ( "A script to add and multiply 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* ( plac.call\(main\)) Tj T* ET
Q
Q
Q
Q
-q
-Q
Q
q
-1 0 0 1 56.69291 56.69291 cm
+1 0 0 1 62.69291 188.4467 cm
q
0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 238.1649 0 Td (7) Tj T* -238.1649 0 Td ET
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (Here is the usage:) Tj T* ET
Q
Q
-
-endstream
-
-endobj
-% 'R160': class PDFStream
-160 0 obj
-% page stream
-<< /Length 4061 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 643.8236 cm
-0 0 0 rg
-BT /F3 10 Tf 12 TL ET
-BT 1 0 0 1 0 2 Tm T* ET
-q
-1 0 0 1 20 0 cm
+1 0 0 1 62.69291 95.24669 cm
q
q
1 0 0 1 0 0 cm
@@ -3790,31 +3960,35 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 442.6898 120 re B*
+n -6 -6 468.6898 84 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 101.71 Tm /F4 10 Tf 12 TL ( "A script to add and multiply 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* ( plac.call\(main\)) Tj T* ET
+BT 1 0 0 1 0 65.71 Tm /F4 10 Tf 12 TL (usage: example10.py [-h] {add,mul} [n [n ...]]) Tj T* T* (A script to add and multiply numbers) Tj T* T* (positional arguments:) Tj T* ( {add,mul} The name of an operator) Tj T* ET
Q
Q
Q
Q
Q
q
-Q
-Q
-q
-1 0 0 1 62.69291 643.8236 cm
-Q
-q
-1 0 0 1 62.69291 625.8236 cm
+1 0 0 1 56.69291 56.69291 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
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 238.1649 0 Td (8) Tj T* -238.1649 0 Td ET
Q
Q
+
+endstream
+
+endobj
+% 'R167': class PDFStream
+167 0 obj
+% page stream
+<< /Length 3858 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 484.6236 cm
+1 0 0 1 62.69291 703.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -3824,24 +3998,24 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 132 re B*
+n -6 -6 468.6898 60 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 113.71 Tm /F4 10 Tf 12 TL (usage: example10.py [-h] {add,mul} [n [n ...]]) Tj T* T* (A script to add and multiply numbers) 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
+BT 1 0 0 1 0 41.71 Tm /F4 10 Tf 12 TL ( 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 452.6236 cm
+1 0 0 1 62.69291 671.8236 cm
q
BT 1 0 0 1 0 16.82 Tm .15186 Tw 12 TL /F1 10 Tf 0 0 0 rg (Notice that the docstring of the ) Tj /F4 10 Tf (main ) Tj /F1 10 Tf (function has been automatically added to the usage message. Here) Tj T* 0 Tw (are a couple of examples of use:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 359.2849 cm
+1 0 0 1 62.69291 578.4849 cm
q
q
.87797 0 0 .87797 0 0 cm
@@ -3862,27 +4036,19 @@ Q
Q
Q
q
-1 0 0 1 62.69291 326.2849 cm
+1 0 0 1 62.69291 545.4849 cm
q
-BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (A somewhat realistic example) Tj T* ET
+BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (A more realistic example) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 284.2849 cm
+1 0 0 1 62.69291 503.4849 cm
q
BT 1 0 0 1 0 28.82 Tm 1.234488 Tw 12 TL /F1 10 Tf 0 0 0 rg (Here is a more realistic script using most of the features of ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (to run SQL queries on a database by) Tj T* 0 Tw .930697 Tw (relying on ) Tj 0 0 .501961 rg (SQLAlchemy) Tj 0 0 0 rg (. Notice the usage of the ) Tj /F4 10 Tf (type ) Tj /F1 10 Tf (feature to automagically convert a SQLAlchemy) Tj T* 0 Tw (connection string into a ) Tj 0 0 .501961 rg (SqlSoup ) Tj 0 0 0 rg (object:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 278.2849 cm
-Q
-q
-1 0 0 1 62.69291 88.86614 cm
-0 0 0 rg
-BT /F3 10 Tf 12 TL ET
-BT 1 0 0 1 0 2 Tm T* ET
-q
-1 0 0 1 20 0 cm
+1 0 0 1 62.69291 170.2849 cm
q
q
1 0 0 1 0 0 cm
@@ -3892,43 +4058,25 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 442.6898 180 re B*
+n -6 -6 468.6898 324 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 161.71 Tm /F4 10 Tf 12 TL (# dbcli.py) Tj T* (import plac) Tj T* (from sqlalchemy.ext.sqlsoup import SqlSoup) Tj T* T* (@plac.annotations\() Tj T* ( db=\("Connection string", 'positional', None, SqlSoup\),) Tj T* ( header=\("Header", 'flag', 'H'\),) Tj T* ( sqlcmd=\("SQL command", 'option', 'c', str, None, "SQL"\),) Tj T* ( delimiter=\("Column separator", 'option', 'd'\),) Tj T* ( scripts="SQL scripts",) Tj T* ( \)) Tj T* (def main\(db, header, sqlcmd, delimiter="|", *scripts\):) Tj T* ( "A script to run queries and SQL scripts on a database") Tj T* ( print\('Working on %s' % db.bind.url\)) Tj T* ET
+BT 1 0 0 1 0 305.71 Tm /F4 10 Tf 12 TL (# dbcli.py) Tj T* (import plac) Tj T* (from sqlalchemy.ext.sqlsoup import SqlSoup) Tj T* T* (@plac.annotations\() Tj T* ( db=\("Connection string", 'positional', None, SqlSoup\),) Tj T* ( header=\("Header", 'flag', 'H'\),) Tj T* ( sqlcmd=\("SQL command", 'option', 'c', str, None, "SQL"\),) Tj T* ( delimiter=\("Column separator", 'option', 'd'\),) Tj T* ( scripts="SQL scripts",) Tj T* ( \)) Tj T* (def main\(db, header, sqlcmd, delimiter="|", *scripts\):) Tj T* ( "A script to run queries and SQL scripts on a database") Tj T* ( print\('Working on %s' % db.bind.url\)) Tj T* ( if sqlcmd:) Tj T* ( result = db.bind.execute\(sqlcmd\)) Tj T* ( if header: # print the header) Tj T* ( print\(delimiter.join\(result.keys\(\)\)\)) Tj T* ( for row in result: # print the rows) Tj T* ( print\(delimiter.join\(map\(str, row\)\)\)) Tj T* T* ( for script in scripts:) Tj T* ( db.bind.execute\(file\(script\).read\(\)\)) Tj T* T* (if __name__ == '__main__':) Tj T* ( plac.call\(main\)) Tj T* ET
Q
Q
Q
Q
Q
q
-Q
-Q
-q
-1 0 0 1 56.69291 56.69291 cm
+1 0 0 1 62.69291 150.2849 cm
q
0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 238.1649 0 Td (8) Tj T* -238.1649 0 Td ET
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (Here is the usage message:) Tj T* ET
Q
Q
-
-endstream
-
-endobj
-% 'R161': class PDFStream
-161 0 obj
-% page stream
-<< /Length 5032 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 607.8236 cm
-0 0 0 rg
-BT /F3 10 Tf 12 TL ET
-BT 1 0 0 1 0 2 Tm T* ET
-q
-1 0 0 1 20 0 cm
+1 0 0 1 62.69291 93.0849 cm
q
q
1 0 0 1 0 0 cm
@@ -3938,31 +4086,35 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 442.6898 156 re B*
+n -6 -6 468.6898 48 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 137.71 Tm /F4 10 Tf 12 TL ( if sqlcmd:) Tj T* ( result = db.bind.execute\(sqlcmd\)) Tj T* ( if header: # print the header) Tj T* ( print\(delimiter.join\(result.keys\(\)\)\)) Tj T* ( for row in result: # print the rows) Tj T* ( print\(delimiter.join\(map\(str, row\)\)\)) Tj T* T* ( for script in scripts:) Tj T* ( db.bind.execute\(file\(script\).read\(\)\)) Tj T* T* (if __name__ == '__main__':) Tj T* ( plac.call\(main\)) Tj T* ET
+BT 1 0 0 1 0 29.71 Tm /F4 10 Tf 12 TL ($ python dbcli.py -h) Tj T* (usage: dbcli.py [-h] [-H] [-c SQL] [-d |] db [scripts [scripts ...]]) Tj T* T* ET
Q
Q
Q
Q
Q
q
-Q
-Q
-q
-1 0 0 1 62.69291 607.8236 cm
-Q
-q
-1 0 0 1 62.69291 589.8236 cm
+1 0 0 1 56.69291 56.69291 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
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 238.1649 0 Td (9) Tj T* -238.1649 0 Td ET
Q
Q
+
+endstream
+
+endobj
+% 'R168': class PDFStream
+168 0 obj
+% page stream
+<< /Length 5891 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 400.6236 cm
+1 0 0 1 62.69291 619.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -3972,42 +4124,42 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 180 re B*
+n -6 -6 468.6898 144 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 161.71 Tm /F4 10 Tf 12 TL ($ python article/dbcli.py -h) Tj T* (usage: dbcli.py [-h] [-H] [-c SQL] [-d |] db [scripts [scripts ...]]) Tj T* T* (A script to run queries and SQL scripts on a database) Tj T* T* (positional arguments:) Tj T* ( db Connection string) Tj T* ( scripts SQL scripts) Tj T* T* (optional arguments:) Tj T* ( -h, --help show this help message and exit) Tj T* ( -H, --header Header) Tj T* ( -c SQL, --sqlcmd SQL SQL command) Tj T* ( -d |, --delimiter | Column separator) Tj T* ET
+BT 1 0 0 1 0 125.71 Tm /F4 10 Tf 12 TL (A script to run queries and SQL scripts on a database) Tj T* T* (positional arguments:) Tj T* ( db Connection string) Tj T* ( scripts SQL scripts) Tj T* T* (optional arguments:) Tj T* ( -h, --help show this help message and exit) Tj T* ( -H, --header Header) Tj T* ( -c SQL, --sqlcmd SQL SQL command) Tj T* ( -d |, --delimiter | Column separator) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 367.6236 cm
+1 0 0 1 62.69291 586.8236 cm
q
-BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (A few notes about the underlying implementation) Tj T* ET
+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 337.6236 cm
+1 0 0 1 62.69291 556.8236 cm
q
BT 1 0 0 1 0 16.82 Tm .094988 Tw 12 TL /F1 10 Tf 0 0 .501961 rg (plac ) 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 and it is possible to leverage on ) Tj 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (features) Tj T* 0 Tw (directly or indirectly.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 295.6236 cm
+1 0 0 1 62.69291 514.8236 cm
q
BT 1 0 0 1 0 28.82 Tm 5.575697 Tw 12 TL /F1 10 Tf 0 0 0 rg (For instance, you can make invisible an argument in the usage message simply by using) Tj T* 0 Tw 1.435976 Tw /F4 10 Tf ('==SUPPRESS==' ) Tj /F1 10 Tf (as help string \(or ) Tj /F4 10 Tf (argparse.SUPPRESS) Tj /F1 10 Tf (\). Similarly, you can use ) Tj 0 0 .501961 rg (argparse.FileType) Tj T* 0 Tw 0 0 0 rg (directly.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 241.6236 cm
+1 0 0 1 62.69291 460.8236 cm
q
BT 1 0 0 1 0 40.82 Tm 1.639213 Tw 12 TL /F1 10 Tf 0 0 0 rg (It is also possible to pass options to the underlying ) Tj /F4 10 Tf (argparse.ArgumentParser ) Tj /F1 10 Tf (object \(currently it) Tj T* 0 Tw .285529 Tw (accepts the default arguments ) Tj /F4 10 Tf (description) Tj /F1 10 Tf (, ) Tj /F4 10 Tf (epilog) Tj /F1 10 Tf (, ) Tj /F4 10 Tf (prog) Tj /F1 10 Tf (, ) Tj /F4 10 Tf (usage) Tj /F1 10 Tf (, ) Tj /F4 10 Tf (add_help) Tj /F1 10 Tf (, ) Tj /F4 10 Tf (argument_default) Tj /F1 10 Tf (,) Tj T* 0 Tw 1.439953 Tw /F4 10 Tf (parents) Tj /F1 10 Tf (, ) Tj /F4 10 Tf (prefix_chars) Tj /F1 10 Tf (, ) Tj /F4 10 Tf (fromfile_prefix_chars) Tj /F1 10 Tf (, ) Tj /F4 10 Tf (conflict_handler) Tj /F1 10 Tf (, ) Tj /F4 10 Tf (formatter_class) Tj /F1 10 Tf (\). It) Tj T* 0 Tw (is enough to set such attributes on the ) Tj /F4 10 Tf (main ) Tj /F1 10 Tf (function. For instance) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 172.4236 cm
+1 0 0 1 62.69291 391.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -4028,30 +4180,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 92.42362 cm
+1 0 0 1 62.69291 311.6236 cm
q
BT 1 0 0 1 0 64.82 Tm 1.256457 Tw 12 TL /F1 10 Tf 0 0 0 rg (disable the recognition of the help flag ) Tj /F4 10 Tf (-h, --help) Tj /F1 10 Tf (. This is not particularly elegant, but I assume the) Tj T* 0 Tw .275703 Tw (typical user of ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (will be happy with the defaults and would not want to change them; still it is possible if) Tj T* 0 Tw .365542 Tw (she wants to. For instance, by setting the ) Tj /F4 10 Tf (description ) Tj /F1 10 Tf (attribute, it is possible to add a comment to the) Tj T* 0 Tw .602339 Tw (usage message \(by default the docstring of the ) Tj /F4 10 Tf (main ) Tj /F1 10 Tf (function is used as description\). It is also possible) Tj T* 0 Tw .322988 Tw (to change the option prefix; for instance if your script must run under Windows and you want to use "/" as) Tj T* 0 Tw (option prefix you can add the lines:) Tj T* ET
Q
Q
q
-1 0 0 1 56.69291 56.69291 cm
-q
-0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 238.1649 0 Td (9) Tj T* -238.1649 0 Td ET
-Q
-Q
-
-endstream
-
-endobj
-% 'R162': class PDFStream
-162 0 obj
-% page stream
-<< /Length 5108 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
-q
-1 0 0 1 62.69291 727.8236 cm
+1 0 0 1 62.69291 266.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -4072,19 +4207,19 @@ Q
Q
Q
q
-1 0 0 1 62.69291 659.8236 cm
+1 0 0 1 62.69291 198.4236 cm
q
-BT 1 0 0 1 0 52.82 Tm 3.694269 Tw 12 TL /F1 10 Tf 0 0 0 rg (The recognition of the ) Tj /F4 10 Tf (short_prefix ) Tj /F1 10 Tf (attribute is a ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (extension; there is also a companion) Tj T* 0 Tw 2.348314 Tw /F4 10 Tf (long_prefix ) Tj /F1 10 Tf (attribute with default value of ) Tj /F4 10 Tf (--) Tj /F1 10 Tf (. ) Tj /F4 10 Tf (prefix_chars ) Tj /F1 10 Tf (is an ) Tj 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (feature. Interested) Tj T* 0 Tw 1.419984 Tw (readers should read the documentation of ) Tj 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (to understand the meaning of the other options. If) Tj T* 0 Tw .098935 Tw (there is a set of options that you use very often, you may consider writing a decorator adding such options) Tj T* 0 Tw (to the ) Tj /F4 10 Tf (main ) Tj /F1 10 Tf (function for you. For simplicity, ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (does not perform any magic of that kind.) Tj T* ET
+BT 1 0 0 1 0 52.82 Tm 3.694269 Tw 12 TL /F1 10 Tf 0 0 0 rg (The recognition of the ) Tj /F4 10 Tf (short_prefix ) Tj /F1 10 Tf (attribute is a ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (extension; there is also a companion) Tj T* 0 Tw 1.348314 Tw /F4 10 Tf (long_prefix ) Tj /F1 10 Tf (attribute with default value of ) Tj /F4 10 Tf ("--") Tj /F1 10 Tf (. ) Tj /F4 10 Tf (prefix_chars ) Tj /F1 10 Tf (is an ) Tj 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (feature. Interested) Tj T* 0 Tw 1.419984 Tw (readers should read the documentation of ) Tj 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (to understand the meaning of the other options. If) Tj T* 0 Tw .098935 Tw (there is a set of options that you use very often, you may consider writing a decorator adding such options) Tj T* 0 Tw (to the ) Tj /F4 10 Tf (main ) Tj /F1 10 Tf (function for you. For simplicity, ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (does not perform any magic of that kind.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 629.8236 cm
+1 0 0 1 62.69291 168.4236 cm
q
BT 1 0 0 1 0 16.82 Tm 7.709147 Tw 12 TL /F1 10 Tf 0 0 0 rg (It is possible to access directly the underlying ) Tj 0 0 .501961 rg (ArgumentParser ) Tj 0 0 0 rg (object, by invoking the) Tj T* 0 Tw /F4 10 Tf (plac.parser_from ) Tj /F1 10 Tf (utility function:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 512.6236 cm
+1 0 0 1 62.69291 99.22362 cm
q
q
1 0 0 1 0 0 cm
@@ -4094,50 +4229,34 @@ 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 /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( import plac) Tj T* (>) Tj (>) Tj (>) Tj ( def main\(arg\):) Tj T* (... pass) Tj T* (...) Tj T* (>) Tj (>) Tj (>) Tj ( print plac.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
+n -6 -6 468.6898 60 re B*
Q
q
-1 0 0 1 62.69291 492.6236 cm
-q
-BT 1 0 0 1 0 4.82 Tm 12 TL /F1 10 Tf 0 0 0 rg (I use ) Tj /F4 10 Tf (plac.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
+BT 1 0 0 1 0 41.71 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( import plac) Tj T* (>) Tj (>) Tj (>) Tj ( def main\(arg\):) Tj T* (... pass) Tj T* (...) Tj T* ET
Q
Q
-q
-1 0 0 1 62.69291 459.6236 cm
-q
-BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Custom annotation objects) Tj T* ET
Q
Q
-q
-1 0 0 1 62.69291 429.6236 cm
-q
-BT 1 0 0 1 0 16.82 Tm .578651 Tw 12 TL /F1 10 Tf 0 0 0 rg (Internally ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (uses an ) Tj /F4 10 Tf (Annotation ) Tj /F1 10 Tf (class to convert the tuples in the function signature into annotation) Tj T* 0 Tw (objects, i.e. objects with six attributes ) Tj /F4 10 Tf (help, kind, short, type, choices, metavar) Tj /F1 10 Tf (.) Tj T* ET
-Q
Q
q
-1 0 0 1 62.69291 399.6236 cm
+1 0 0 1 56.69291 56.69291 cm
q
0 0 0 rg
-BT 1 0 0 1 0 16.82 Tm /F1 10 Tf 12 TL .083735 Tw (Advanced users can implement their own annotation objects. For instance, here is an example of how you) Tj T* 0 Tw (could implement annotations for positional arguments:) Tj T* ET
-Q
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 235.3849 0 Td (10) Tj T* -235.3849 0 Td ET
Q
-q
-1 0 0 1 62.69291 393.6236 cm
Q
+
+endstream
+
+endobj
+% 'R169': class PDFStream
+169 0 obj
+% page stream
+<< /Length 3843 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 272.4236 cm
-0 0 0 rg
-BT /F3 10 Tf 12 TL ET
-BT 1 0 0 1 0 2 Tm T* ET
-q
-1 0 0 1 20 0 cm
+1 0 0 1 62.69291 703.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -4147,39 +4266,42 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 448.6898 120 re B*
+n -6 -6 468.6898 60 re B*
Q
q
-0 0 0 rg
-BT 1 0 0 1 0 101.71 Tm /F4 10 Tf 12 TL (# annotations.py) Tj T* (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
+BT 1 0 0 1 0 41.71 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( print plac.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 683.8236 cm
+q
+BT 1 0 0 1 0 4.82 Tm 12 TL /F1 10 Tf 0 0 0 rg (I use ) Tj /F4 10 Tf (plac.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 272.4236 cm
+1 0 0 1 62.69291 650.8236 cm
+q
+BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Custom annotation objects) Tj T* ET
+Q
Q
q
-1 0 0 1 62.69291 254.4236 cm
+1 0 0 1 62.69291 620.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
+BT 1 0 0 1 0 16.82 Tm .578651 Tw 12 TL /F1 10 Tf 0 0 0 rg (Internally ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (uses an ) Tj /F4 10 Tf (Annotation ) Tj /F1 10 Tf (class to convert the tuples in the function signature into annotation) Tj T* 0 Tw (objects, i.e. objects with six attributes ) Tj /F4 10 Tf (help, kind, short, type, choices, metavar) Tj /F1 10 Tf (.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 248.4236 cm
-Q
+1 0 0 1 62.69291 590.8236 cm
q
-1 0 0 1 62.69291 88.86614 cm
0 0 0 rg
-BT /F3 10 Tf 12 TL ET
-BT 1 0 0 1 0 2 Tm T* ET
+BT 1 0 0 1 0 16.82 Tm /F1 10 Tf 12 TL .083735 Tw (Advanced users can implement their own annotation objects. For instance, here is an example of how you) Tj T* 0 Tw (could implement annotations for positional arguments:) Tj T* ET
+Q
+Q
q
-1 0 0 1 20 0 cm
+1 0 0 1 62.69291 461.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -4189,43 +4311,25 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 442.6898 144 re B*
+n -6 -6 468.6898 120 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 125.71 Tm /F4 10 Tf 12 TL (# example11.py) Tj T* (import plac) Tj T* (from annotations import Positional) Tj T* T* (@plac.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* ET
-Q
-Q
+BT 1 0 0 1 0 101.71 Tm /F4 10 Tf 12 TL (# annotations.py) Tj T* (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
-1 0 0 1 56.69291 56.69291 cm
+1 0 0 1 62.69291 441.6236 cm
q
0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 235.3849 0 Td (10) Tj T* -235.3849 0 Td ET
+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
-
-endstream
-
-endobj
-% 'R163': class PDFStream
-163 0 obj
-% page stream
-<< /Length 8268 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
-q
-1 0 0 1 62.69291 727.8236 cm
-0 0 0 rg
-BT /F3 10 Tf 12 TL ET
-BT 1 0 0 1 0 2 Tm T* ET
q
-1 0 0 1 20 0 cm
+1 0 0 1 62.69291 264.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -4235,31 +4339,25 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 442.6898 36 re B*
+n -6 -6 468.6898 168 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 17.71 Tm /F4 10 Tf 12 TL (if __name__ == '__main__':) Tj T* ( import plac; plac.call\(main\)) Tj T* ET
+BT 1 0 0 1 0 149.71 Tm /F4 10 Tf 12 TL (# example11.py) Tj T* (import plac) Tj T* (from annotations import Positional) Tj T* T* (@plac.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 plac; plac.call\(main\)) Tj T* ET
Q
Q
Q
Q
Q
q
-Q
-Q
-q
-1 0 0 1 62.69291 727.8236 cm
-Q
-q
-1 0 0 1 62.69291 709.8236 cm
+1 0 0 1 62.69291 244.4236 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 you get:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 580.6236 cm
+1 0 0 1 62.69291 115.2236 cm
q
q
1 0 0 1 0 0 cm
@@ -4280,31 +4378,48 @@ Q
Q
Q
q
-1 0 0 1 62.69291 536.6236 cm
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 235.3849 0 Td (11) Tj T* -235.3849 0 Td ET
+Q
+Q
+
+endstream
+
+endobj
+% 'R170': class PDFStream
+170 0 obj
+% page stream
+<< /Length 8993 >>
+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 .713516 Tw 12 TL /F1 10 Tf 0 0 0 rg (You can go on and define ) Tj /F4 10 Tf (Option ) Tj /F1 10 Tf (and ) Tj /F4 10 Tf (Flag ) Tj /F1 10 Tf (classes, if you like. Using custom annotation objects you) Tj T* 0 Tw .17528 Tw (could do advanced things like extracting the annotations from a configuration file or from a database, but I) Tj T* 0 Tw (expect such use cases to be quite rare: the default mechanism should work pretty well for most users.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 503.6236 cm
+1 0 0 1 62.69291 696.0236 cm
q
BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (plac vs argparse) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 461.6236 cm
+1 0 0 1 62.69291 654.0236 cm
q
-BT 1 0 0 1 0 28.82 Tm 1.677882 Tw 12 TL /F1 10 Tf 0 0 .501961 rg (plac ) Tj 0 0 0 rg (is opinionated and by design it does not try to make available all of the features of ) Tj 0 0 .501961 rg (argparse) Tj 0 0 0 rg (. In) Tj T* 0 Tw .85498 Tw (particular you should be aware of the following limitations/differences \(the following assumes knowledge) Tj T* 0 Tw (of ) Tj 0 0 .501961 rg (argparse) Tj 0 0 0 rg (\):) Tj T* ET
+BT 1 0 0 1 0 28.82 Tm 1.065988 Tw 12 TL /F1 10 Tf 0 0 .501961 rg (plac ) Tj 0 0 0 rg (is opinionated and by design it does not try to make available all of the features of ) Tj 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (in an) Tj T* 0 Tw .177126 Tw (easy way. In particular you should be aware of the following limitations/differences \(the following assumes) Tj T* 0 Tw (knowledge of ) Tj 0 0 .501961 rg (argparse) Tj 0 0 0 rg (\):) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 455.6236 cm
+1 0 0 1 62.69291 648.0236 cm
Q
q
-1 0 0 1 62.69291 455.6236 cm
+1 0 0 1 62.69291 648.0236 cm
Q
q
-1 0 0 1 62.69291 401.6236 cm
+1 0 0 1 62.69291 594.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -4324,13 +4439,13 @@ q
Q
Q
q
-1 0 0 1 62.69291 401.6236 cm
+1 0 0 1 62.69291 594.0236 cm
Q
q
-1 0 0 1 62.69291 401.6236 cm
+1 0 0 1 62.69291 594.0236 cm
Q
q
-1 0 0 1 62.69291 323.6236 cm
+1 0 0 1 62.69291 516.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -4350,13 +4465,13 @@ q
Q
Q
q
-1 0 0 1 62.69291 323.6236 cm
+1 0 0 1 62.69291 516.0236 cm
Q
q
-1 0 0 1 62.69291 323.6236 cm
+1 0 0 1 62.69291 516.0236 cm
Q
q
-1 0 0 1 62.69291 281.6236 cm
+1 0 0 1 62.69291 474.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -4376,13 +4491,13 @@ q
Q
Q
q
-1 0 0 1 62.69291 281.6236 cm
+1 0 0 1 62.69291 474.0236 cm
Q
q
-1 0 0 1 62.69291 281.6236 cm
+1 0 0 1 62.69291 474.0236 cm
Q
q
-1 0 0 1 62.69291 215.6236 cm
+1 0 0 1 62.69291 408.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -4402,13 +4517,13 @@ q
Q
Q
q
-1 0 0 1 62.69291 215.6236 cm
+1 0 0 1 62.69291 408.0236 cm
Q
q
-1 0 0 1 62.69291 215.6236 cm
+1 0 0 1 62.69291 408.0236 cm
Q
q
-1 0 0 1 62.69291 173.6236 cm
+1 0 0 1 62.69291 366.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -4421,20 +4536,20 @@ Q
q
1 0 0 1 23 3 cm
q
-BT 1 0 0 1 0 28.82 Tm 1.797126 Tw 12 TL /F1 10 Tf 0 0 .501961 rg (plac ) Tj 0 0 0 rg (does not support ) Tj /F4 10 Tf (nargs ) Tj /F1 10 Tf (options directly \(it uses them internally, though, to implement flag) Tj T* 0 Tw .90683 Tw (recognition\). The reason it that all the use cases of interest to me are covered by ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (and did not) Tj T* 0 Tw (feel the need to increase the learning curve by adding direct support to ) Tj /F4 10 Tf (nargs) Tj /F1 10 Tf (.) Tj T* ET
+BT 1 0 0 1 0 28.82 Tm 1.797126 Tw 12 TL /F1 10 Tf 0 0 .501961 rg (plac ) Tj 0 0 0 rg (does not support ) Tj /F4 10 Tf (nargs ) Tj /F1 10 Tf (options directly \(it uses them internally, though, to implement flag) Tj T* 0 Tw .90683 Tw (recognition\). The reason it that all the use cases of interest to me are covered by ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (and did not) Tj T* 0 Tw (feel the need to increase the learning curve by adding direct support for ) Tj /F4 10 Tf (nargs) Tj /F1 10 Tf (.) Tj T* ET
Q
Q
q
Q
Q
q
-1 0 0 1 62.69291 173.6236 cm
+1 0 0 1 62.69291 366.0236 cm
Q
q
-1 0 0 1 62.69291 173.6236 cm
+1 0 0 1 62.69291 366.0236 cm
Q
q
-1 0 0 1 62.69291 143.6236 cm
+1 0 0 1 62.69291 336.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -4454,13 +4569,13 @@ q
Q
Q
q
-1 0 0 1 62.69291 143.6236 cm
+1 0 0 1 62.69291 336.0236 cm
Q
q
-1 0 0 1 62.69291 143.6236 cm
+1 0 0 1 62.69291 336.0236 cm
Q
q
-1 0 0 1 62.69291 101.6236 cm
+1 0 0 1 62.69291 294.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -4480,66 +4595,66 @@ q
Q
Q
q
-1 0 0 1 62.69291 101.6236 cm
+1 0 0 1 62.69291 294.0236 cm
Q
q
-1 0 0 1 62.69291 101.6236 cm
+1 0 0 1 62.69291 294.0236 cm
Q
q
-1 0 0 1 56.69291 56.69291 cm
+1 0 0 1 62.69291 240.0236 cm
q
-0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 235.3849 0 Td (11) Tj T* -235.3849 0 Td ET
+BT 1 0 0 1 0 40.82 Tm 2.14683 Tw 12 TL /F1 10 Tf 0 0 0 rg (I should stress again that if you want to access all of the ) Tj 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (features from ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (you can use) Tj T* 0 Tw 2.723059 Tw /F4 10 Tf (plac.parser_from ) Tj /F1 10 Tf (and you will get the underlying ) Tj 0 0 .501961 rg (ArgumentParser ) Tj 0 0 0 rg (object. The the full power of) Tj T* 0 Tw 2.44152 Tw 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (is then available to you: you can use ) Tj /F4 10 Tf (add_argument) Tj /F1 10 Tf (, ) Tj /F4 10 Tf (add_subparsers\(\)) Tj /F1 10 Tf (, etc. In other) Tj T* 0 Tw (words, while some features are not supported directly, ) Tj /F5 10 Tf (all ) Tj /F1 10 Tf (features are supported indirectly.) Tj T* ET
Q
Q
-
-endstream
-
-endobj
-% 'R164': class PDFStream
-164 0 obj
-% page stream
-<< /Length 5386 >>
-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
+1 0 0 1 62.69291 207.0236 cm
q
-BT 1 0 0 1 0 40.82 Tm 2.14683 Tw 12 TL /F1 10 Tf 0 0 0 rg (I should stress again that if you want to access all of the ) Tj 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (features from ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (you can use) Tj T* 0 Tw 2.723059 Tw /F4 10 Tf (plac.parser_from ) Tj /F1 10 Tf (and you will get the underlying ) Tj 0 0 .501961 rg (ArgumentParser ) Tj 0 0 0 rg (object. The the full power of) Tj T* 0 Tw 2.44152 Tw 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (is then available to you: you can use ) Tj /F4 10 Tf (add_argument) Tj /F1 10 Tf (, ) Tj /F4 10 Tf (add_subparsers\(\)) Tj /F1 10 Tf (, etc. In other) Tj T* 0 Tw (words, while some features are not supported directly, ) Tj /F5 10 Tf (all ) Tj /F1 10 Tf (features are supported indirectly.) Tj T* ET
+BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (The future) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 684.0236 cm
+1 0 0 1 62.69291 129.0236 cm
q
-BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (The future) Tj T* ET
+BT 1 0 0 1 0 64.82 Tm .444431 Tw 12 TL /F1 10 Tf 0 0 0 rg (Currently plac is below 100 lines of code, not counting blanks, comments and docstrings. I do not plan to) Tj T* 0 Tw .035444 Tw (extend it much in the future. The idea is to keep the module short: it is and it should remain a little wrapper) Tj T* 0 Tw 1.903318 Tw (over ) Tj 0 0 .501961 rg (argparse) Tj 0 0 0 rg (. Actually I have thought about contributing the code back to ) Tj 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (if ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (becomes) Tj T* 0 Tw 4.105697 Tw (successfull and gains a reasonable number of users. For the moment it should be considered) Tj T* 0 Tw .351654 Tw (experimental: after all I wrote it in three days, including the tests, the documentation and the time to learn) Tj T* 0 Tw 0 0 .501961 rg (argparse) Tj 0 0 0 rg (.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 606.0236 cm
+1 0 0 1 56.69291 56.69291 cm
q
-BT 1 0 0 1 0 64.82 Tm .444431 Tw 12 TL /F1 10 Tf 0 0 0 rg (Currently plac is below 100 lines of code, not counting blanks, comments and docstrings. I do not plan to) Tj T* 0 Tw .035444 Tw (extend it much in the future. The idea is to keep the module short: it is and it should remain a little wrapper) Tj T* 0 Tw 1.903318 Tw (over ) Tj 0 0 .501961 rg (argparse) Tj 0 0 0 rg (. Actually I have thought about contributing the code back to ) Tj 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (if ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (becomes) Tj T* 0 Tw 4.105697 Tw (successfull and gains a reasonable number of users. For the moment it should be considered) Tj T* 0 Tw .351654 Tw (experimental: after all I wrote it in three days, including the tests, the documentation and the time to learn) Tj T* 0 Tw 0 0 .501961 rg (argparse) Tj 0 0 0 rg (.) Tj T* ET
+0 0 0 rg
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 235.3849 0 Td (12) Tj T* -235.3849 0 Td ET
Q
Q
+
+endstream
+
+endobj
+% 'R171': class PDFStream
+171 0 obj
+% page stream
+<< /Length 3729 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 573.0236 cm
+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 (Trivia: the story behind the name) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 507.0236 cm
+1 0 0 1 62.69291 678.0236 cm
q
BT 1 0 0 1 0 52.82 Tm .942651 Tw 12 TL /F1 10 Tf 0 0 0 rg (The ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (project started very humble: I just wanted to make easy_installable my old ) Tj 0 0 .501961 rg (optionparse ) Tj 0 0 0 rg (recipe,) Tj T* 0 Tw .565988 Tw (and to publish it on PyPI. The original name of ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (was optionparser and the idea behind it was to build) Tj T* 0 Tw .603735 Tw (an ) Tj 0 0 .501961 rg (OptionParser ) Tj 0 0 0 rg (object from the docstring of the module. However, before doing that, I decided to check) Tj T* 0 Tw .244198 Tw (out the ) Tj 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (module, since I knew it was going into Python 2.7 and Python 2.7 was coming out. Soon) Tj T* 0 Tw (enough I realized two things:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 501.0236 cm
+1 0 0 1 62.69291 672.0236 cm
Q
q
-1 0 0 1 62.69291 501.0236 cm
+1 0 0 1 62.69291 672.0236 cm
Q
q
-1 0 0 1 62.69291 471.0236 cm
+1 0 0 1 62.69291 642.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -4559,13 +4674,13 @@ q
Q
Q
q
-1 0 0 1 62.69291 471.0236 cm
+1 0 0 1 62.69291 642.0236 cm
Q
q
-1 0 0 1 62.69291 471.0236 cm
+1 0 0 1 62.69291 642.0236 cm
Q
q
-1 0 0 1 62.69291 441.0236 cm
+1 0 0 1 62.69291 612.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -4586,143 +4701,158 @@ q
Q
Q
q
-1 0 0 1 62.69291 441.0236 cm
+1 0 0 1 62.69291 612.0236 cm
Q
q
-1 0 0 1 62.69291 441.0236 cm
+1 0 0 1 62.69291 612.0236 cm
Q
q
-1 0 0 1 62.69291 387.0236 cm
+1 0 0 1 62.69291 558.0236 cm
q
-BT 1 0 0 1 0 40.82 Tm .600574 Tw 12 TL /F1 10 Tf 0 0 0 rg (Putting together these two observations with the original idea of inferring the parser I decided to build an) Tj T* 0 Tw .516905 Tw 0 0 .501961 rg (ArgumentParser ) Tj 0 0 0 rg (object from function annotations. The ) Tj /F4 10 Tf (optionparser ) Tj /F1 10 Tf (name was ruled out, since I was) Tj T* 0 Tw .122651 Tw (using ) Tj 0 0 .501961 rg (argparse) Tj 0 0 0 rg (; a name like ) Tj /F4 10 Tf (argparse_plus ) Tj /F1 10 Tf (was also ruled out, since the typical usage was completely) Tj T* 0 Tw (different from the ) Tj 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (usage.) Tj T* ET
+BT 1 0 0 1 0 40.82 Tm .600574 Tw 12 TL /F1 10 Tf 0 0 0 rg (Putting together these two observations with the original idea of inferring the parser I decided to build an) Tj T* 0 Tw .516905 Tw 0 0 .501961 rg (ArgumentParser ) Tj 0 0 0 rg (object from function annotations. The ) Tj /F4 10 Tf (optionparser ) Tj /F1 10 Tf (name was ruled out, since I was) Tj T* 0 Tw 2.085984 Tw (now using ) Tj 0 0 .501961 rg (argparse) Tj 0 0 0 rg (; a name like ) Tj /F4 10 Tf (argparse_plus ) Tj /F1 10 Tf (was also ruled out, since the typical usage was) Tj T* 0 Tw (completely different from the ) Tj 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (usage.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 357.0236 cm
+1 0 0 1 62.69291 528.0236 cm
q
-BT 1 0 0 1 0 16.82 Tm 1.093876 Tw 12 TL /F1 10 Tf 0 0 0 rg (I made a research on PyPI and the name clap \(Command Line Arguments Parser\) was not taken, so I) Tj T* 0 Tw (renamed everything to clap. After two days a ) Tj 0 0 .501961 rg (Clap ) Tj 0 0 0 rg (module appeared on PyPI! <) Tj (expletives deleted) Tj (>) Tj T* ET
+BT 1 0 0 1 0 16.82 Tm 1.093876 Tw 12 TL /F1 10 Tf 0 0 0 rg (I made a research on PyPI and the name plac \(Command Line Arguments Parser\) was not taken, so I) Tj T* 0 Tw (renamed everything to plac. After two days a ) Tj 0 0 .501961 rg (Clap ) Tj 0 0 0 rg (module appeared on PyPI <) Tj (expletives deleted) Tj (>) Tj (!) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 327.0236 cm
+1 0 0 1 62.69291 498.0236 cm
q
0 0 0 rg
-BT 1 0 0 1 0 16.82 Tm /F1 10 Tf 12 TL .877209 Tw (Having little imagination, I decided to rename everything again to plac, an anagram of clap: since it is a) Tj T* 0 Tw (non-existing English name, I hope nobody will steal it from me!) Tj T* ET
+BT 1 0 0 1 0 16.82 Tm /F1 10 Tf 12 TL .877209 Tw (Having little imagination, I decided to rename everything again to plac, an anagram of plac: since it is a) Tj T* 0 Tw (non-existing English name, I hope nobody will steal it from me!) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 480.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (That's all, I hope you will enjoy working with plac!) Tj T* ET
Q
Q
q
1 0 0 1 56.69291 56.69291 cm
q
0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 235.3849 0 Td (12) Tj T* -235.3849 0 Td ET
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 235.3849 0 Td (13) Tj T* -235.3849 0 Td ET
Q
Q
endstream
endobj
-% 'R165': class PDFPageLabels
-165 0 obj
+% 'R172': class PDFPageLabels
+172 0 obj
% Document Root
<< /Nums [ 0
- 166 0 R
+ 173 0 R
1
- 167 0 R
+ 174 0 R
2
- 168 0 R
+ 175 0 R
3
- 169 0 R
+ 176 0 R
4
- 170 0 R
+ 177 0 R
5
- 171 0 R
+ 178 0 R
6
- 172 0 R
+ 179 0 R
7
- 173 0 R
+ 180 0 R
8
- 174 0 R
+ 181 0 R
9
- 175 0 R
+ 182 0 R
10
- 176 0 R
+ 183 0 R
11
- 177 0 R ] >>
+ 184 0 R
+ 12
+ 185 0 R ] >>
endobj
-% 'R166': class PDFPageLabel
-166 0 obj
+% 'R173': class PDFPageLabel
+173 0 obj
% None
<< /S /D
/St 1 >>
endobj
-% 'R167': class PDFPageLabel
-167 0 obj
+% 'R174': class PDFPageLabel
+174 0 obj
% None
<< /S /D
/St 2 >>
endobj
-% 'R168': class PDFPageLabel
-168 0 obj
+% 'R175': class PDFPageLabel
+175 0 obj
% None
<< /S /D
/St 3 >>
endobj
-% 'R169': class PDFPageLabel
-169 0 obj
+% 'R176': class PDFPageLabel
+176 0 obj
% None
<< /S /D
/St 4 >>
endobj
-% 'R170': class PDFPageLabel
-170 0 obj
+% 'R177': class PDFPageLabel
+177 0 obj
% None
<< /S /D
/St 5 >>
endobj
-% 'R171': class PDFPageLabel
-171 0 obj
+% 'R178': class PDFPageLabel
+178 0 obj
% None
<< /S /D
/St 6 >>
endobj
-% 'R172': class PDFPageLabel
-172 0 obj
+% 'R179': class PDFPageLabel
+179 0 obj
% None
<< /S /D
/St 7 >>
endobj
-% 'R173': class PDFPageLabel
-173 0 obj
+% 'R180': class PDFPageLabel
+180 0 obj
% None
<< /S /D
/St 8 >>
endobj
-% 'R174': class PDFPageLabel
-174 0 obj
+% 'R181': class PDFPageLabel
+181 0 obj
% None
<< /S /D
/St 9 >>
endobj
-% 'R175': class PDFPageLabel
-175 0 obj
+% 'R182': class PDFPageLabel
+182 0 obj
% None
<< /S /D
/St 10 >>
endobj
-% 'R176': class PDFPageLabel
-176 0 obj
+% 'R183': class PDFPageLabel
+183 0 obj
% None
<< /S /D
/St 11 >>
endobj
-% 'R177': class PDFPageLabel
-177 0 obj
+% 'R184': class PDFPageLabel
+184 0 obj
% None
<< /S /D
/St 12 >>
endobj
+% 'R185': class PDFPageLabel
+185 0 obj
+% None
+<< /S /D
+ /St 13 >>
+endobj
xref
-0 178
+0 186
0000000000 65535 f
0000000113 00000 n
0000000258 00000 n
@@ -4730,185 +4860,193 @@ xref
0000000598 00000 n
0000000779 00000 n
0000001031 00000 n
-0000001269 00000 n
-0000001443 00000 n
-0000001684 00000 n
-0000001925 00000 n
-0000002167 00000 n
-0000002409 00000 n
-0000002651 00000 n
-0000002893 00000 n
-0000003136 00000 n
-0000003379 00000 n
-0000003622 00000 n
-0000003865 00000 n
-0000004108 00000 n
-0000004351 00000 n
-0000004594 00000 n
-0000004837 00000 n
-0000005080 00000 n
-0000005323 00000 n
-0000005566 00000 n
-0000005809 00000 n
-0000006053 00000 n
-0000006297 00000 n
-0000006541 00000 n
-0000006785 00000 n
-0000007029 00000 n
-0000007272 00000 n
-0000007534 00000 n
-0000007797 00000 n
-0000008047 00000 n
+0000001281 00000 n
+0000001539 00000 n
+0000001713 00000 n
+0000001954 00000 n
+0000002196 00000 n
+0000002438 00000 n
+0000002680 00000 n
+0000002922 00000 n
+0000003165 00000 n
+0000003408 00000 n
+0000003651 00000 n
+0000003894 00000 n
+0000004137 00000 n
+0000004380 00000 n
+0000004623 00000 n
+0000004866 00000 n
+0000005109 00000 n
+0000005352 00000 n
+0000005595 00000 n
+0000005839 00000 n
+0000006083 00000 n
+0000006327 00000 n
+0000006571 00000 n
+0000006815 00000 n
+0000007059 00000 n
+0000007303 00000 n
+0000007547 00000 n
+0000007791 00000 n
+0000008034 00000 n
0000008296 00000 n
-0000008562 00000 n
-0000008814 00000 n
-0000009064 00000 n
-0000009316 00000 n
-0000009566 00000 n
-0000009818 00000 n
-0000010068 00000 n
-0000010305 00000 n
-0000010952 00000 n
-0000011191 00000 n
-0000011386 00000 n
-0000011648 00000 n
-0000011912 00000 n
-0000012147 00000 n
-0000012492 00000 n
-0000012744 00000 n
-0000012996 00000 n
-0000013247 00000 n
-0000013497 00000 n
-0000013749 00000 n
-0000013986 00000 n
-0000014349 00000 n
-0000014601 00000 n
-0000014853 00000 n
-0000015105 00000 n
-0000015393 00000 n
-0000015677 00000 n
-0000015986 00000 n
-0000016238 00000 n
-0000016511 00000 n
-0000016892 00000 n
-0000017129 00000 n
-0000017447 00000 n
-0000017699 00000 n
-0000017951 00000 n
-0000018203 00000 n
-0000018440 00000 n
-0000018785 00000 n
-0000019037 00000 n
-0000019287 00000 n
-0000019537 00000 n
-0000019787 00000 n
-0000020039 00000 n
-0000020274 00000 n
-0000020637 00000 n
-0000020889 00000 n
-0000021135 00000 n
-0000021397 00000 n
-0000021733 00000 n
-0000021984 00000 n
-0000022234 00000 n
-0000022484 00000 n
-0000022800 00000 n
-0000023035 00000 n
-0000023389 00000 n
-0000023641 00000 n
-0000023890 00000 n
-0000024140 00000 n
-0000024392 00000 n
-0000024679 00000 n
-0000024917 00000 n
-0000025280 00000 n
-0000025531 00000 n
-0000025781 00000 n
-0000026032 00000 n
-0000026285 00000 n
-0000026550 00000 n
-0000026801 00000 n
-0000027066 00000 n
-0000027317 00000 n
-0000027570 00000 n
-0000027821 00000 n
-0000028074 00000 n
-0000028325 00000 n
-0000028578 00000 n
-0000028829 00000 n
-0000029081 00000 n
-0000029334 00000 n
-0000029587 00000 n
-0000029841 00000 n
-0000030080 00000 n
-0000030579 00000 n
-0000030831 00000 n
-0000031084 00000 n
-0000031373 00000 n
-0000031625 00000 n
-0000031877 00000 n
-0000032128 00000 n
-0000032382 00000 n
-0000032634 00000 n
-0000032888 00000 n
-0000033175 00000 n
-0000033429 00000 n
-0000033740 00000 n
-0000033992 00000 n
-0000034244 00000 n
-0000034533 00000 n
-0000034785 00000 n
-0000035037 00000 n
-0000035280 00000 n
-0000035757 00000 n
-0000035921 00000 n
-0000036255 00000 n
-0000036384 00000 n
-0000036578 00000 n
-0000036800 00000 n
-0000037010 00000 n
-0000037207 00000 n
-0000037412 00000 n
-0000037605 00000 n
-0000037813 00000 n
-0000038040 00000 n
-0000038245 00000 n
-0000038443 00000 n
-0000038635 00000 n
-0000038818 00000 n
-0000039030 00000 n
-0000047599 00000 n
-0000052996 00000 n
-0000057452 00000 n
-0000062279 00000 n
-0000067393 00000 n
-0000072925 00000 n
-0000078852 00000 n
-0000083016 00000 n
-0000088151 00000 n
-0000093362 00000 n
-0000101733 00000 n
-0000107226 00000 n
-0000107478 00000 n
-0000107557 00000 n
-0000107636 00000 n
-0000107715 00000 n
-0000107794 00000 n
-0000107873 00000 n
-0000107952 00000 n
-0000108031 00000 n
-0000108110 00000 n
-0000108189 00000 n
-0000108269 00000 n
-0000108349 00000 n
+0000008559 00000 n
+0000008809 00000 n
+0000009058 00000 n
+0000009324 00000 n
+0000009576 00000 n
+0000009811 00000 n
+0000010440 00000 n
+0000010692 00000 n
+0000010942 00000 n
+0000011194 00000 n
+0000011444 00000 n
+0000011696 00000 n
+0000011947 00000 n
+0000012186 00000 n
+0000012381 00000 n
+0000012642 00000 n
+0000012906 00000 n
+0000013140 00000 n
+0000013539 00000 n
+0000013791 00000 n
+0000014043 00000 n
+0000014294 00000 n
+0000014544 00000 n
+0000014781 00000 n
+0000015135 00000 n
+0000015384 00000 n
+0000015636 00000 n
+0000015888 00000 n
+0000016125 00000 n
+0000016470 00000 n
+0000016722 00000 n
+0000017010 00000 n
+0000017298 00000 n
+0000017550 00000 n
+0000017838 00000 n
+0000018075 00000 n
+0000018438 00000 n
+0000018690 00000 n
+0000018942 00000 n
+0000019179 00000 n
+0000019515 00000 n
+0000019752 00000 n
+0000020070 00000 n
+0000020322 00000 n
+0000020572 00000 n
+0000020822 00000 n
+0000021072 00000 n
+0000021324 00000 n
+0000021559 00000 n
+0000021922 00000 n
+0000022174 00000 n
+0000022420 00000 n
+0000022682 00000 n
+0000023018 00000 n
+0000023269 00000 n
+0000023519 00000 n
+0000023769 00000 n
+0000024085 00000 n
+0000024335 00000 n
+0000024587 00000 n
+0000024836 00000 n
+0000025086 00000 n
+0000025338 00000 n
+0000025611 00000 n
+0000026011 00000 n
+0000026250 00000 n
+0000026570 00000 n
+0000026822 00000 n
+0000027073 00000 n
+0000027324 00000 n
+0000027577 00000 n
+0000027842 00000 n
+0000028093 00000 n
+0000028358 00000 n
+0000028609 00000 n
+0000028862 00000 n
+0000029113 00000 n
+0000029366 00000 n
+0000029617 00000 n
+0000029870 00000 n
+0000030122 00000 n
+0000030375 00000 n
+0000030629 00000 n
+0000030883 00000 n
+0000031137 00000 n
+0000031391 00000 n
+0000031643 00000 n
+0000031896 00000 n
+0000032185 00000 n
+0000032437 00000 n
+0000032689 00000 n
+0000032940 00000 n
+0000033194 00000 n
+0000033431 00000 n
+0000034012 00000 n
+0000034266 00000 n
+0000034553 00000 n
+0000034807 00000 n
+0000035118 00000 n
+0000035370 00000 n
+0000035622 00000 n
+0000035911 00000 n
+0000036163 00000 n
+0000036415 00000 n
+0000036658 00000 n
+0000037055 00000 n
+0000037219 00000 n
+0000037554 00000 n
+0000037683 00000 n
+0000037877 00000 n
+0000038088 00000 n
+0000038298 00000 n
+0000038498 00000 n
+0000038696 00000 n
+0000038901 00000 n
+0000039094 00000 n
+0000039298 00000 n
+0000039493 00000 n
+0000039700 00000 n
+0000039898 00000 n
+0000040090 00000 n
+0000040273 00000 n
+0000040496 00000 n
+0000048871 00000 n
+0000054323 00000 n
+0000058359 00000 n
+0000062714 00000 n
+0000068012 00000 n
+0000073444 00000 n
+0000078424 00000 n
+0000084014 00000 n
+0000087975 00000 n
+0000093969 00000 n
+0000097915 00000 n
+0000107011 00000 n
+0000110847 00000 n
+0000111114 00000 n
+0000111193 00000 n
+0000111272 00000 n
+0000111351 00000 n
+0000111430 00000 n
+0000111509 00000 n
+0000111588 00000 n
+0000111667 00000 n
+0000111746 00000 n
+0000111825 00000 n
+0000111905 00000 n
+0000111985 00000 n
+0000112065 00000 n
trailer
<< /ID
% ReportLab generated PDF document -- digest (http://www.reportlab.com)
- [(\346\011\317\303+\313.*\300:\327\373\2730\202\036) (\346\011\317\303+\313.*\300:\327\373\2730\202\036)]
+ [(\334\356J>\024\306\353\212b\246'\270\354\2445\340) (\334\356J>\024\306\353\212b\246'\270\354\2445\340)]
- /Info 138 0 R
- /Root 137 0 R
- /Size 178 >>
+ /Info 143 0 R
+ /Root 142 0 R
+ /Size 186 >>
startxref
-108398
+112114
%%EOF
diff --git a/plac/doc/plac.txt b/plac/doc/plac.txt
index 661a0ca..d540e91 100644
--- a/plac/doc/plac.txt
+++ b/plac/doc/plac.txt
@@ -1,10 +1,11 @@
-Parsing the Command Line the Easy Way: Introducing plac, the EasiestArgument Parser in the Python World
+Parsing the Command Line the Easy Way: Introducing plac, the Easiest Argument Parser in the Python World
==========================================================================================================
:Author: Michele Simionato
:E-mail: michele.simionato@gmail.com
:Requires: Python 2.3+
:Download page: http://pypi.python.org/pypi/plac
+:Project page: http://micheles.googlecode.com/hg/plac/doc/plac.html
:Installation: ``easy_install plac``
:License: BSD license
@@ -19,73 +20,75 @@ 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 feature a non-zero learning
-curve and a certain verbosity.
-
-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. This is an old meme in the computing world:
-programs should address the common cases simply, simple things should
-be kept simple, while at the same keeping difficult things
-possible. plac_ adhere as much as possible to this philosophy and it
-is designed to handle well the simple cases, while retaining the
-ability to handle complex cases by relying on the underlying power of
-argparse_.
-
-Technically plac_ is just a simple wrapper over argparse_, hiding most
-of its complexity while retaining most of its power. The complexity is
-removed by using a declarative interface instead of an imperative one.
-Still, plac_ is surprisingly scalable upwards, even without
-using the underlying argparse_. I have been using Python for
-8 years and in my experience it is extremely unlikely that you will
-ever need to go beyond the features provided by the declarative interface
-of plac_: they should be more than enough for 99.9% of the typical use cases.
-
-plac_ is targetting 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 are interested in a small
-learning curve: 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 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.
-
-Scripts with required positional arguments
+curve and a certain verbosity. They do not scale down well enough, at
+least in my opinion.
+
+It should not be necessary to stress the importance `scaling down`_;
+nevertheless most people are obsessed with features and concerned with
+the possibility of scaling up, whereas I think that we should be even
+more concerned with the issue of scaling down. This is an old meme in
+the computing world: programs should address the common cases simply,
+simple things should be kept simple, while at the same keeping
+difficult things possible. plac_ adhere as much as possible to this
+philosophy and it is designed to handle well the simple cases, while
+retaining the ability to handle complex cases by relying on the
+underlying power of argparse_.
+
+Technically plac_ is just a simple wrapper over argparse_ which hides
+most of its complexity by using a declarative interface: the argument
+parser is inferred rather than written down by imperatively. Still, plac_ is
+surprisingly scalable upwards, even without using the underlying
+argparse_. I have been using Python for 8 years and in my experience
+it is extremely unlikely that you will ever need to go beyond the
+features provided by the declarative interface of plac_: they should
+be more than enough for 99.9% of the use cases.
+
+plac_ is targetting especially unsophisticated users,
+programmers, sys-admins, scientists and in general people writing
+throw-away scripts for themselves, choosing the command line
+interface because it is the quick and simple. Such users are not
+interested in features, they are interested in a small learning curve:
+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 modules in the standard library forces them
+to go the hard way. They are designed to implement power user tools
+and they have a non-trivial learning curve. On the contrary, plac_
+is designed to be simple to use and extremely concise, as the examples
+below will show.
+
+Scripts with required arguments
---------------------------------------------
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
+single argument and does something to it. It cannot get simpler
+than that, unless you consider a script without command line
+arguments, where there is nothing to parse. Still, 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:
+.. 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 pass to it the
-command line arguments behind the scenes; unfortunaly this is unlikely to
+As you see the whole ``if __name__ == '__main__'`` block (nine lines)
+is essentially boilerplate that should not exists. Actually I think
+the language should recognize the main function and pass to it the
+command line arguments automatically; 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 does 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:
+trivial. Unfortunately the standard library does not help for this
+incredibly common use case. 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:
+.. 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
+dependency: most people will not switch to 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.
@@ -94,8 +97,8 @@ The plac_ 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
plac_ module all you need to write is
- .. include:: example3.py
- :literal:
+.. include:: example3.py
+ :literal:
The plac_ module provides for free (actually the work is done by the
underlying argparse_ module) a nice usage message::
@@ -111,23 +114,31 @@ underlying argparse_ module) a nice usage message::
This is only the tip of the iceberg: plac_ is able to do much more than that.
-Scritps with default arguments
+Scripts with default arguments
--------------------------------------------------
-I have encountered this use case at work hundreds of times:
+The need to have suitable defaults for command line arguments is quite
+common. For instance I have encountered this use case at work hundreds
+of times:
- .. include:: example4.py
- :literal:
+.. include:: example4.py
+ :literal:
+Here I want to perform a query on a database table, by extracting the
+today's data: it makes sense for ``today`` to be a default argument.
+If there is a most used table (in this example a table called ``'product'``)
+it also makes sense to make it a default argument. Performing the parsing
+of the command lines arguments by hand takes 8 ugly lines of boilerplate
+(using argparse_ would require about the same number of lines).
With plac_ the entire ``__main__`` block reduces to the usual two lines::
if __name__ == '__main__':
import plac; plac.call(main)
-In other words, six lines of boilerplate have been removed, and I have
+In other words, six lines of boilerplate have been removed, and we get
the usage message for free::
- usage: example4_.py [-h] dsn [table] [today]
+ usage: example5.py [-h] dsn [table] [today]
positional arguments:
dsn
@@ -141,12 +152,12 @@ plac_ 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:
+.. include:: example6.py
+ :literal:
Using plac_, you can just replace the ``__main__`` block with the
usual two lines (I have defined an Emacs keybinding for them)
-and you get the following usage message::
+and then you get the following nice usage message::
usage: example7.py [-h] dsn [scripts [scripts ...]]
@@ -159,23 +170,22 @@ and you get the following usage message::
The examples here should have made clear that *plac 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 plac_: if my intent is clear,
+function*. This is the whole idea behind plac_: if the intent is clear,
let's the machine take care of the details.
-Options and flags
+Scripts with options
---------------------------------------
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 have written (certainly
-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_.
+number of scripts with positional arguments I wrote (certainly more
+than a thousand of them). Still, this use case 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.
plac_ is inspired to the optionparse_ recipe, in the sense that it
delivers the programmer from the burden of writing the parser, but is
@@ -187,18 +197,17 @@ 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:
+.. 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 plac_ that ``command`` is an option and that
-it can be abbreviated with the letter ``c``. Of course, the long option
-format (``--command=``) comes from the argument name.
-The resulting usage message is the following::
+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, the second string tell plac_
+that ``command`` is an option and the third string that it can be
+abbreviated with the letter ``c``. Of course, the long option format
+(``--command=``) comes from the argument name. The resulting usage
+message is the following::
- $ python3 example8.py -h
usage: example8.py [-h] [-c COMMAND] dsn
positional arguments:
@@ -221,13 +230,13 @@ Notice that if the option is not passed, the variable ``command``
will get the value ``None``. It is possible to specify a non-trivial
default for an option. Here is an example:
- .. include:: example8_.py
- :literal:
+.. include:: example8_.py
+ :literal:
Now if you do not pass the ``command option``, the
default query will be executed::
- $ python article/example8_.py dsn
+ $ python example8_.py dsn
executing 'select * from table' on dsn
Positional argument can be annotated too::
@@ -242,24 +251,30 @@ smart enough to convert help messages into tuples; in other words, you
can just write ``"Database dsn"`` instead of ``("Database dsn",
'positional', None)``. 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::
+argument.
+
+I should also notice that varargs (starred-arguments) can be annotated too;
+here is an example::
def main(dsn: "Database dsn", *scripts: "SQL scripts"):
...
-is a valid signature for plac_, which will recognize the help strings
+This is a valid signature for plac_, which will recognize the help strings
for both ``dsn`` and ``scripts``::
positional arguments:
dsn Database dsn
scripts SQL scripts
+Scripts with flags
+--------------------
+
plac_ 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::
+if they are absent. Here is an example:
- $ python3 example9.py -v dsn
- connecting to dsn
+.. include:: example9.py
+ :literal:
::
@@ -273,6 +288,11 @@ if they are absent. Here is an example::
-h, --help show this help message and exit
-v, --verbose prints more info
+::
+
+ $ python3 example9.py -v dsn
+ connecting to dsn
+
Notice that it is an error trying to specify a default for flags: the
default value for a flag is always ``False``. If you feel the need to
implement non-boolean flags, you should use an option with two
@@ -284,39 +304,38 @@ the ``main`` function write first the flag arguments, then the option
arguments, then the required arguments and finally the default
arguments. This is just a convention and you are not forced to use it,
except for the default arguments (including the varargs) which must
-stay at the end since it is required by the Python syntax.
+stay at the end as it is required by the Python syntax.
plac for Python 2.X users
--------------------------------------------------
I do not use Python 3. At work we are just starting to think about
-migrating to Python 2.6. It will take years before we even
+migrating to Python 2.6. It will take years before we
think to migrate to Python 3. I am pretty much sure most Pythonistas
are in the same situation. Therefore plac_ 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
+by hand. For instance the annotate function declaration
::
def main(dsn: "Database dsn", *scripts: "SQL scripts"):
+ ...
-becomes::
+is equivalent to the following code::
def main(dsn, *scripts):
...
main.__annotations__ = dict(
- dsn="Database dsn",
- scripts="SQL scripts")
+ dsn="Database dsn",
+ scripts="SQL scripts")
-One should be careful to much the keys of the annotations dictionary
+One should be careful to match the keys of the annotation 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
-``plac.annotations`` decorator that performs the check for you.
+``plac.annotations`` decorator that performs the check for you::
-::
-
- @annotations(
+ @plac.annotations(
dsn="Database dsn",
scripts="SQL scripts")
def main(dsn, *scripts):
@@ -324,43 +343,45 @@ people with Python 2.4 available the simplest way is to use the
In the rest of this article I will assume that you are using Python 2.X with
``X >= 4`` and I will use the ``plac.annotations`` decorator. Notice however
-that the tests for plac_ are supposed to run even with Python 2.3.
+that the tests for plac_ runs even on Python 2.3.
More features
--------------------------------------------------
-One of the goals of plac 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 features of argparse_. Actually
-a lot of argparse_ power persists in plac_.
-Until now, I have only showed simple annotations, but in general
-an annotation is a 5-tuple of the form
+Even if one of the goals of plac is to have a learning curve of
+*minutes*, compared to the learning curve of *hours* of
+argparse_, it does not mean that I have removed all the features of
+argparse_. Actually a lot of argparse_ power persists in plac_. 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.
+where ``help`` is the help message, ``kind`` is a string in the set {
+``"flag"``, ``"option"``, ``"positional"``}, ``abbrev`` is a
+one-character string, ``type`` is a callable taking a string in input,
+``choices`` is a discrete 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``.
+``type`` is used to automagically convert the command line arguments
+from the string type to any Python type; by default there is no
+convertion and ``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, unless the argument has a default and in such a case is
+(and only there); by default the metavar is ``None``: this means that
+the name in the usage message is the same as the argument name,
+unless the argument has a default and in such a case is
equal to the stringified form of the default.
-Here is an example showing many of the features (shamelessly stolen
-from the argparse_ documentation):
+Here is an example showing many of the features (taken from the
+argparse_ documentation):
- .. include:: example10.py
- :literal:
+.. include:: example10.py
+ :literal:
-Here is the usage for the script::
+Here is the usage::
usage: example10.py [-h] {add,mul} [n [n ...]]
@@ -384,7 +405,7 @@ to the usage message. Here are a couple of examples of use::
usage: example10.py [-h] {add,mul} [n [n ...]]
example10.py: error: argument operator: invalid choice: 'ad' (choose from 'add', 'mul')
-A somewhat realistic example
+A more realistic example
---------------------------------------
Here is a more realistic script using most of the features of plac_ to
@@ -392,12 +413,12 @@ run SQL queries on a database by relying on SQLAlchemy_. Notice the usage
of the ``type`` feature to automagically convert a SQLAlchemy connection
string into a SqlSoup_ object:
- .. include:: dbcli.py
- :literal:
+.. include:: dbcli.py
+ :literal:
Here is the usage message::
- $ python article/dbcli.py -h
+ $ python dbcli.py -h
usage: dbcli.py [-h] [-H] [-c SQL] [-d |] db [scripts [scripts ...]]
A script to run queries and SQL scripts on a database
@@ -412,7 +433,7 @@ Here is the usage message::
-c SQL, --sqlcmd SQL SQL command
-d |, --delimiter | Column separator
-A few notes about the underlying implementation
+Advanced usage
----------------------------------------------------
plac_ relies on a argparse_ for all of the heavy lifting work and it is
@@ -453,7 +474,7 @@ as option prefix you can add the lines::
The recognition of the ``short_prefix`` attribute is a plac_
extension; there is also a companion ``long_prefix`` attribute with
-default value of ``--``. ``prefix_chars`` is an argparse_ feature.
+default value of ``"--"``. ``prefix_chars`` is an argparse_ feature.
Interested readers should read the documentation of argparse_ to
understand the meaning of the other options. If there is a set of
options that you use very often, you may consider writing a decorator
@@ -486,13 +507,13 @@ 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:
+.. include:: annotations.py
+ :literal:
You can use such annotations objects as follows:
- .. include:: example11.py
- :literal:
+.. include:: example11.py
+ :literal:
Here is the usage message you get::
@@ -516,9 +537,9 @@ plac vs argparse
---------------------------------------------
plac_ is opinionated and by design it does not try to make available
-all of the features of argparse_. In particular you should be aware
-of the following limitations/differences (the following assumes knowledge
-of argparse_):
+all of the features of argparse_ in an easy way. In particular you
+should be aware of the following limitations/differences (the
+following assumes knowledge of argparse_):
- plac_ automatically defines both a long and short form for each options,
just like optparse_. argparse_ allows you to define only a long form,
@@ -551,7 +572,7 @@ of argparse_):
- plac_ does not support ``nargs`` options directly (it uses them internally,
though, to implement flag recognition). The reason it that all the use
cases of interest to me are covered by plac_ and did not feel the need
- to increase the learning curve by adding direct support to ``nargs``.
+ to increase the learning curve by adding direct support for ``nargs``.
- plac_ does not support subparsers directly. For the moment, this
looks like a feature too advanced for the goals of plac_.
@@ -599,17 +620,19 @@ Soon enough I realized two things:
Putting together these two observations with the original idea of inferring the
parser I decided to build an ArgumentParser_ object from function
annotations. The ``optionparser`` name was ruled out, since I was
-using argparse_; a name like ``argparse_plus`` was also ruled out,
+now using argparse_; a name like ``argparse_plus`` was also ruled out,
since the typical usage was completely different from the argparse_ usage.
-I made a research on PyPI and the name clap (Command Line Arguments Parser)
-was not taken, so I renamed everything to clap. After two days
-a Clap_ module appeared on PyPI! <expletives deleted>
+I made a research on PyPI and the name plac (Command Line Arguments Parser)
+was not taken, so I renamed everything to plac. After two days
+a Clap_ module appeared on PyPI <expletives deleted>!
Having little imagination, I decided to rename everything again to plac,
-an anagram of clap: since it is a non-existing English name, I hope nobody
+an anagram of plac: since it is a non-existing English name, I hope nobody
will steal it from me!
+That's all, I hope you will enjoy working with plac!
+
.. _argparse: http://argparse.googlecode.com
.. _optparse: http://docs.python.org/library/optparse.html
.. _getopt: http://docs.python.org/library/getopt.html
diff --git a/plac/plac.py b/plac/plac.py
index ef0bf75..82c5095 100644
--- a/plac/plac.py
+++ b/plac/plac.py
@@ -71,7 +71,7 @@ def is_annotation(obj):
and hasattr(obj, 'choices') and hasattr(obj, 'metavar'))
class Annotation(object):
- def __init__(self, help="", kind="positional", abbrev=None, type=str,
+ def __init__(self, help="", kind="positional", abbrev=None, type=None,
choices=None, metavar=None):
assert kind in ('positional', 'option', 'flag'), kind
if kind == "positional":
diff --git a/plac/test_plac.py b/plac/test_plac.py
index c961759..79b2cd9 100644
--- a/plac/test_plac.py
+++ b/plac/test_plac.py
@@ -45,7 +45,6 @@ def test_p2():
expect(SystemExit, p2.parse_args, [])
-
p3 = parser_from(lambda arg1, delete: None,
delete=('delete a file', 'option', 'd'))