summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichele Simionato <michele.simionato@gmail.com>2010-06-03 21:24:10 +0200
committerMichele Simionato <michele.simionato@gmail.com>2010-06-03 21:24:10 +0200
commit17f2a4ec22415f6959ee20532568577191ddfa07 (patch)
tree39ce51909e61c5ff1a8d4a6ddea36bab05bb3a12
parente10ca8849a5b306519a187128c0ba37cfdcc0f06 (diff)
downloadmicheles-17f2a4ec22415f6959ee20532568577191ddfa07.tar.gz
Added tests. Fixed the help message formatting. Version 0.4.1plac-0.4.1
-rw-r--r--plac/CHANGES.txt2
-rw-r--r--plac/doc/dbcli.help13
-rw-r--r--plac/doc/example10.help10
-rw-r--r--plac/doc/example11.help9
-rw-r--r--plac/doc/example12.help9
-rw-r--r--plac/doc/example5.help11
-rw-r--r--plac/doc/example7.help10
-rw-r--r--plac/doc/example8.help9
-rw-r--r--plac/doc/example9.help8
-rw-r--r--plac/doc/plac.html170
-rw-r--r--plac/doc/plac.pdf785
-rw-r--r--plac/doc/plac.txt109
-rw-r--r--plac/plac.py47
-rw-r--r--plac/test_plac.py26
14 files changed, 641 insertions, 577 deletions
diff --git a/plac/CHANGES.txt b/plac/CHANGES.txt
index 8fca7f9..2fb6f07 100644
--- a/plac/CHANGES.txt
+++ b/plac/CHANGES.txt
@@ -1,6 +1,8 @@
HISTORY
----------
+0.4.1. Changed the default formatting class and fixed a bug in the
+ display of the default arguments. Added more stringent tests. (2010-06-03)
0.4.0 abbrev is now optional. Added a note about CLIArgs and opterate.
Added keyword arguments recognition. ``plac.call`` now returns the
the output of the main function. (2010-06-03)
diff --git a/plac/doc/dbcli.help b/plac/doc/dbcli.help
new file mode 100644
index 0000000..c606181
--- /dev/null
+++ b/plac/doc/dbcli.help
@@ -0,0 +1,13 @@
+usage: dbcli.py [-h] [-H] [-c SQL] [-d |] db [scripts [scripts ...]]
+
+A script to run queries and SQL scripts on a database
+
+positional arguments:
+ db Connection string
+ scripts SQL scripts
+
+optional arguments:
+ -h, --help show this help message and exit
+ -H, --header Header
+ -c, --sqlcmd SQL SQL command
+ -d, --delimiter | Column separator
diff --git a/plac/doc/example10.help b/plac/doc/example10.help
new file mode 100644
index 0000000..8ac3e9f
--- /dev/null
+++ b/plac/doc/example10.help
@@ -0,0 +1,10 @@
+usage: example10.py [-h] {add,mul} [n [n ...]]
+
+A script to add and multiply numbers
+
+positional arguments:
+ {add,mul} The name of an operator
+ n A number
+
+optional arguments:
+ -h, --help show this help message and exit
diff --git a/plac/doc/example11.help b/plac/doc/example11.help
new file mode 100644
index 0000000..4d36924
--- /dev/null
+++ b/plac/doc/example11.help
@@ -0,0 +1,9 @@
+usage: example11.py [-h] i n [rest [rest ...]]
+
+positional arguments:
+ i This is an int
+ n This is a float
+ rest Other arguments
+
+optional arguments:
+ -h, --help show this help message and exit
diff --git a/plac/doc/example12.help b/plac/doc/example12.help
new file mode 100644
index 0000000..cceb8be
--- /dev/null
+++ b/plac/doc/example12.help
@@ -0,0 +1,9 @@
+usage: example12.py [-h] [-o OPT] [args [args ...]] [kw [kw ...]]
+
+positional arguments:
+ args default arguments
+ kw keyword arguments
+
+optional arguments:
+ -h, --help show this help message and exit
+ -o, --opt OPT some option
diff --git a/plac/doc/example5.help b/plac/doc/example5.help
new file mode 100644
index 0000000..0d6a630
--- /dev/null
+++ b/plac/doc/example5.help
@@ -0,0 +1,11 @@
+usage: example5.py [-h] dsn [table] [today]
+
+Do something on the database
+
+positional arguments:
+ dsn
+ table
+ today
+
+optional arguments:
+ -h, --help show this help message and exit
diff --git a/plac/doc/example7.help b/plac/doc/example7.help
new file mode 100644
index 0000000..0834858
--- /dev/null
+++ b/plac/doc/example7.help
@@ -0,0 +1,10 @@
+usage: example7.py [-h] dsn [scripts [scripts ...]]
+
+Run the given scripts on the database
+
+positional arguments:
+ dsn
+ scripts
+
+optional arguments:
+ -h, --help show this help message and exit
diff --git a/plac/doc/example8.help b/plac/doc/example8.help
new file mode 100644
index 0000000..c7fa3a5
--- /dev/null
+++ b/plac/doc/example8.help
@@ -0,0 +1,9 @@
+usage: example8.py [-h] [-c COMMAND] dsn
+
+positional arguments:
+ dsn
+
+optional arguments:
+ -h, --help show this help message and exit
+ -c, --command COMMAND
+ SQL query
diff --git a/plac/doc/example9.help b/plac/doc/example9.help
new file mode 100644
index 0000000..cda79b3
--- /dev/null
+++ b/plac/doc/example9.help
@@ -0,0 +1,8 @@
+usage: example9.py [-h] [-v] dsn
+
+positional arguments:
+ dsn connection string
+
+optional arguments:
+ -h, --help show this help message and exit
+ -v, --verbose prints more info
diff --git a/plac/doc/plac.html b/plac/doc/plac.html
index 62c668e..4ac326d 100644
--- a/plac/doc/plac.html
+++ b/plac/doc/plac.html
@@ -3,7 +3,7 @@
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="generator" content="Docutils 0.5: http://docutils.sourceforge.net/" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
<title>Plac: Parsing the Command Line the Easy Way</title>
<meta name="author" content="Michele Simionato" />
<style type="text/css">
@@ -428,7 +428,7 @@ h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
</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"><span class="pre">easy_install</span> <span class="pre">plac</span></tt></td>
+<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>
</tr>
@@ -523,7 +523,7 @@ if __name__ == '__main__':
sys.exit('Unrecognized arguments: %s' % ' '.join(sys.argv[2:]))
</pre>
-<p>As you see the whole <tt class="docutils literal"><span class="pre">if</span> <span class="pre">__name__</span> <span class="pre">==</span> <span class="pre">'__main__'</span></tt> block (nine lines)
+<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
@@ -607,12 +607,12 @@ if __name__ == '__main__':
</pre>
<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"><span class="pre">today</span></tt> to be a default argument.
-If there is a most used table (in this example a table called <tt class="docutils literal"><span class="pre">'product'</span></tt>)
+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"><span class="pre">__main__</span></tt> block reduces to the usual two lines:</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>
<pre class="literal-block">
if __name__ == '__main__':
import plac; plac.call(main)
@@ -622,6 +622,8 @@ the usage message for free:</p>
<pre class="literal-block">
usage: example5.py [-h] dsn [table] [today]
+Do something on the database
+
positional arguments:
dsn
table
@@ -629,6 +631,7 @@ positional arguments:
optional arguments:
-h, --help show this help message and exit
+
</pre>
<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
@@ -650,18 +653,21 @@ if __name__ == '__main__':
main(sys.argv[1:])
</pre>
-<p>Using <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a>, you can just replace the <tt class="docutils literal"><span class="pre">__main__</span></tt> block with the
+<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 then you get the following nice usage message:</p>
<pre class="literal-block">
usage: example7.py [-h] dsn [scripts [scripts ...]]
+Run the given scripts on the database
+
positional arguments:
dsn
scripts
optional arguments:
-h, --help show this help message and exit
+
</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
@@ -683,7 +689,7 @@ 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
-the module, it extracts it from the signature of the <tt class="docutils literal"><span class="pre">main</span></tt>
+the module, it extracts it from the signature of the <tt class="docutils literal">main</tt>
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
@@ -699,11 +705,11 @@ if __name__ == '__main__':
import plac; plac.call(main)
</pre>
-<p>As you see, the argument <tt class="docutils literal"><span class="pre">command</span></tt> has been annotated with the tuple
-<tt class="docutils literal"><span class="pre">(&quot;SQL</span> <span class="pre">query&quot;,</span> <span class="pre">'option',</span> <span class="pre">'c')</span></tt>: the first string is the help string
+<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"><span class="pre">command</span></tt> is an option and the third string that it can be
-abbreviated with the letter <tt class="docutils literal"><span class="pre">c</span></tt>. Of course, the long option format
+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">
@@ -714,8 +720,9 @@ positional arguments:
optional arguments:
-h, --help show this help message and exit
- -c COMMAND, --command COMMAND
+ -c, --command COMMAND
SQL query
+
</pre>
<p>Here are two examples of usage:</p>
<pre class="literal-block">
@@ -725,8 +732,8 @@ executing select * from table on dsn
$ python3 example8.py --command=&quot;select * from table&quot; dsn
executing select * from table on dsn
</pre>
-<p>Notice that if the option is not passed, the variable <tt class="docutils literal"><span class="pre">command</span></tt>
-will get the value <tt class="docutils literal"><span class="pre">None</span></tt>. It is possible to specify a non-trivial
+<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>
<pre class="literal-block">
# example8_.py
@@ -737,7 +744,7 @@ if __name__ == '__main__':
import plac; plac.call(main)
</pre>
-<p>Now if you do not pass the <tt class="docutils literal"><span class="pre">command</span> <span class="pre">option</span></tt>, the
+<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">
$ python3 example8_.py dsn
@@ -759,10 +766,10 @@ def main(command: (&quot;SQL query&quot;, 'option'),
...
</pre>
<p>When omitted, the third argument is assumed to be the first letter of
-the variable name for options and flags, and <tt class="docutils literal"><span class="pre">None</span></tt> for positional
+the variable name for options and flags, and <tt class="docutils literal">None</tt> for positional
arguments. Moreover, smart enough to convert help messages into tuples;
-in other words, you can just write <tt class="docutils literal"><span class="pre">&quot;Database</span> <span class="pre">dsn&quot;</span></tt> instead of
-<tt class="docutils literal"><span class="pre">(&quot;Database</span> <span class="pre">dsn&quot;,</span> <span class="pre">'positional')</span></tt>.</p>
+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')</tt>.</p>
<p>I should notice that varargs (starred-arguments) can be annotated too;
here is an example:</p>
<pre class="literal-block">
@@ -770,7 +777,7 @@ def main(dsn: &quot;Database dsn&quot;, *scripts: &quot;SQL scripts&quot;):
...
</pre>
<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"><span class="pre">dsn</span></tt> and <tt class="docutils literal"><span class="pre">scripts</span></tt>:</p>
+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
@@ -780,7 +787,7 @@ positional arguments:
<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"><span class="pre">True</span></tt> if they are passed to the command line and <tt class="docutils literal"><span class="pre">False</span></tt>
+<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">
# example9.py
@@ -795,7 +802,6 @@ if __name__ == '__main__':
</pre>
<pre class="literal-block">
-$ python3 example9.py -h
usage: example9.py [-h] [-v] dsn
positional arguments:
@@ -804,18 +810,19 @@ positional arguments:
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"><span class="pre">False</span></tt>. If you feel the need to
+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
choices, as explained in the &quot;more features&quot; section.</p>
<p>For consistency with the way the usage message is printed, I suggest
you to follow the Flag-Option-Required-Default (FORD) convention: in
-the <tt class="docutils literal"><span class="pre">main</span></tt> function write first the flag arguments, then the option
+the <tt class="docutils literal">main</tt> 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
@@ -845,7 +852,7 @@ main.__annotations__ = dict(
<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"><span class="pre">plac.annotations</span></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;plac.annotations(
dsn=&quot;Database dsn&quot;,
@@ -854,7 +861,7 @@ 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"><span class="pre">X</span> <span class="pre">&gt;=</span> <span class="pre">4</span></tt> and I will use the <tt class="docutils literal"><span class="pre">plac.annotations</span></tt> decorator. Notice however
+<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> runs even on Python 2.3.</p>
</div>
<div class="section" id="more-features">
@@ -866,18 +873,18 @@ that the tests for <a class="reference external" href="http://pypi.python.org/py
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"><span class="pre">(help,</span> <span class="pre">kind,</span> <span class="pre">abbrev,</span> <span class="pre">type,</span> <span class="pre">choices,</span> <span class="pre">metavar)</span></tt></blockquote>
-<p>where <tt class="docutils literal"><span class="pre">help</span></tt> is the help message, <tt class="docutils literal"><span class="pre">kind</span></tt> is a string in the set {
-<tt class="docutils literal"><span class="pre">&quot;flag&quot;</span></tt>, <tt class="docutils literal"><span class="pre">&quot;option&quot;</span></tt>, <tt class="docutils literal"><span class="pre">&quot;positional&quot;</span></tt>}, <tt class="docutils literal"><span class="pre">abbrev</span></tt> is a
-one-character string, <tt class="docutils literal"><span class="pre">type</span></tt> is a callable taking a string in input,
-<tt class="docutils literal"><span class="pre">choices</span></tt> is a discrete sequence of values and <tt class="docutils literal"><span class="pre">metavar</span></tt> is a string.</p>
-<p><tt class="docutils literal"><span class="pre">type</span></tt> is used to automagically convert the command line arguments
+<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 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"><span class="pre">type=None</span></tt>.</p>
-<p><tt class="docutils literal"><span class="pre">choices</span></tt> is used to restrict the number of the valid
-options; by default there is no restriction i.e. <tt class="docutils literal"><span class="pre">choices=None</span></tt>.</p>
-<p><tt class="docutils literal"><span class="pre">metavar</span></tt> is used to change the argument name in the usage message
-(and only there); by default the metavar is <tt class="docutils literal"><span class="pre">None</span></tt>: this means that
+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 <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>
@@ -914,8 +921,9 @@ positional arguments:
optional arguments:
-h, --help show this help message and exit
+
</pre>
-<p>Notice that the docstring of the <tt class="docutils literal"><span class="pre">main</span></tt> function has been automatically added
+<p>Notice that the docstring of the <tt class="docutils literal">main</tt> function has been automatically added
to the usage message. Here are a couple of examples of use:</p>
<pre class="literal-block">
$ python example10.py add 1 2 3 4
@@ -930,7 +938,7 @@ example10.py: error: argument operator: invalid choice: 'ad' (choose from 'add',
<div class="section" id="keyword-arguments">
<h1><a class="toc-backref" href="#id8">Keyword arguments</a></h1>
<p>Starting from release 0.4, if your main function has keyword arguments,
-<a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> recognizes arguments of the form <tt class="docutils literal"><span class="pre">&quot;name=value&quot;</span></tt> in the command line.
+<a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> recognizes arguments of the form <tt class="docutils literal">&quot;name=value&quot;</tt> in the command line.
Here is an example:</p>
<pre class="literal-block">
# example12.py
@@ -952,12 +960,13 @@ if __name__ == '__main__':
usage: example12.py [-h] [-o OPT] [args [args ...]] [kw [kw ...]]
positional arguments:
- args default arguments
- kw keyword arguments
+ args default arguments
+ kw keyword arguments
optional arguments:
- -h, --help show this help message and exit
- -o OPT, --opt OPT some option
+ -h, --help show this help message and exit
+ -o, --opt OPT some option
+
</pre>
<p>Here is how you call the script:</p>
<pre class="literal-block">
@@ -965,7 +974,7 @@ $ python example12.py 1 2 kw1=1 kw2=2 --opt=0
('0', ('1', '2'), {'kw1': '1', 'kw2': '2'})
</pre>
<p>When using keyword arguments, one must be careful to use names which
-are not alreay taken; for instance in this examples the name <tt class="docutils literal"><span class="pre">opt</span></tt>
+are not alreay taken; for instance in this examples the name <tt class="docutils literal">opt</tt>
is taken:</p>
<pre class="literal-block">
$ python example12.py 1 2 kw1=1 kw2=2 opt=0
@@ -981,7 +990,7 @@ by the Python language.</p>
<h1><a class="toc-backref" href="#id9">A 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"><span class="pre">type</span></tt> feature to automagically convert a SQLAlchemy connection
+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>
<pre class="literal-block">
# dbcli.py
@@ -1014,20 +1023,20 @@ if __name__ == '__main__':
</pre>
<p>Here is the usage message:</p>
<pre class="literal-block">
-$ 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
positional arguments:
- db Connection string
- scripts SQL scripts
+ db Connection string
+ scripts SQL scripts
optional arguments:
- -h, --help show this help message and exit
- -H, --header Header
- -c SQL, --sqlcmd SQL SQL command
- -d |, --delimiter | Column separator
+ -h, --help show this help message and exit
+ -H, --header Header
+ -c, --sqlcmd SQL SQL command
+ -d, --delimiter | Column separator
+
</pre>
</div>
<div class="section" id="advanced-usage">
@@ -1036,14 +1045,14 @@ optional arguments:
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
simply by using <tt class="docutils literal"><span class="pre">'==SUPPRESS=='</span></tt> as help string (or
-<tt class="docutils literal"><span class="pre">argparse.SUPPRESS</span></tt>). Similarly, you can use <a class="reference external" href="http://argparse.googlecode.com/svn/tags/r11/doc/other-utilities.html?highlight=filetype#FileType">argparse.FileType</a>
+<tt class="docutils literal">argparse.SUPPRESS</tt>). Similarly, you can use <a class="reference external" href="http://argparse.googlecode.com/svn/tags/r11/doc/other-utilities.html?highlight=filetype#FileType">argparse.FileType</a>
directly.</p>
<p>It is also possible to pass options to the underlying
-<tt class="docutils literal"><span class="pre">argparse.ArgumentParser</span></tt> object (currently it accepts the default
-arguments <tt class="docutils literal"><span class="pre">description</span></tt>, <tt class="docutils literal"><span class="pre">epilog</span></tt>, <tt class="docutils literal"><span class="pre">prog</span></tt>, <tt class="docutils literal"><span class="pre">usage</span></tt>,
-<tt class="docutils literal"><span class="pre">add_help</span></tt>, <tt class="docutils literal"><span class="pre">argument_default</span></tt>, <tt class="docutils literal"><span class="pre">parents</span></tt>, <tt class="docutils literal"><span class="pre">prefix_chars</span></tt>,
-<tt class="docutils literal"><span class="pre">fromfile_prefix_chars</span></tt>, <tt class="docutils literal"><span class="pre">conflict_handler</span></tt>, <tt class="docutils literal"><span class="pre">formatter_class</span></tt>).
-It is enough to set such attributes on the <tt class="docutils literal"><span class="pre">main</span></tt> function. For
+<tt class="docutils literal">argparse.ArgumentParser</tt> object (currently it accepts the default
+arguments <tt class="docutils literal">description</tt>, <tt class="docutils literal">epilog</tt>, <tt class="docutils literal">prog</tt>, <tt class="docutils literal">usage</tt>,
+<tt class="docutils literal">add_help</tt>, <tt class="docutils literal">argument_default</tt>, <tt class="docutils literal">parents</tt>, <tt class="docutils literal">prefix_chars</tt>,
+<tt class="docutils literal">fromfile_prefix_chars</tt>, <tt class="docutils literal">conflict_handler</tt>, <tt class="docutils literal">formatter_class</tt>).
+It is enough to set such attributes on the <tt class="docutils literal">main</tt> function. For
instance</p>
<pre class="literal-block">
def main(...):
@@ -1054,9 +1063,9 @@ main.add_help = False
<p>disable the recognition of the help flag <tt class="docutils literal"><span class="pre">-h,</span> <span class="pre">--help</span></tt>. This is not
particularly elegant, but I assume the typical user of <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> will be
happy with the defaults and would not want to change them; still it is
-possible if she wants to. For instance, by setting the <tt class="docutils literal"><span class="pre">description</span></tt>
+possible if she wants to. For instance, by setting the <tt class="docutils literal">description</tt>
attribute, it is possible to add a comment to the usage message (by
-default the docstring of the <tt class="docutils literal"><span class="pre">main</span></tt> function is used as
+default the docstring of the <tt class="docutils literal">main</tt> function is used as
description). It is also possible to change the option prefix; for
instance if your script must run under Windows and you want to use &quot;/&quot;
as option prefix you can add the lines:</p>
@@ -1064,16 +1073,16 @@ as option prefix you can add the lines:</p>
main.prefix_chars='-/'
main.short_prefix = '/'
</pre>
-<p>The recognition of the <tt class="docutils literal"><span class="pre">short_prefix</span></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"><span class="pre">long_prefix</span></tt> attribute with
-default value of <tt class="docutils literal"><span class="pre">&quot;--&quot;</span></tt>. <tt class="docutils literal"><span class="pre">prefix_chars</span></tt> is an <a class="reference external" href="http://argparse.googlecode.com">argparse</a> feature.
+<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">&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
-adding such options to the <tt class="docutils literal"><span class="pre">main</span></tt> function for you. For simplicity,
+adding such options to the <tt class="docutils literal">main</tt> function for you. For simplicity,
<a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> does not perform any magic of that kind.</p>
<p>It is possible to access directly the underlying <a class="reference external" href="http://argparse.googlecode.com/svn/tags/r11/doc/ArgumentParser.html">ArgumentParser</a> object, by
-invoking the <tt class="docutils literal"><span class="pre">plac.parser_from</span></tt> utility function:</p>
+invoking the <tt class="docutils literal">plac.parser_from</tt> utility function:</p>
<pre class="doctest-block">
&gt;&gt;&gt; import plac
&gt;&gt;&gt; def main(arg):
@@ -1084,14 +1093,14 @@ ArgumentParser(prog='', usage=None, description=None, version=None,
formatter_class=&lt;class 'argparse.HelpFormatter'&gt;, conflict_handler='error',
add_help=True)
</pre>
-<p>I use <tt class="docutils literal"><span class="pre">plac.parser_from</span></tt> in the unit tests of the module, but regular
+<p>I use <tt class="docutils literal">plac.parser_from</tt> in the unit tests of the module, but regular
users should never need to use it.</p>
</div>
<div class="section" id="custom-annotation-objects">
<h1><a class="toc-backref" href="#id11">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"><span class="pre">Annotation</span></tt> class to convert the tuples
+<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"><span class="pre">help,</span> <span class="pre">kind,</span> <span class="pre">short,</span> <span class="pre">type,</span> <span class="pre">choices,</span> <span class="pre">metavar</span></tt>.</p>
+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>
@@ -1135,8 +1144,9 @@ positional arguments:
optional arguments:
-h, --help show this help message and exit
+
</pre>
-<p>You can go on and define <tt class="docutils literal"><span class="pre">Option</span></tt> and <tt class="docutils literal"><span class="pre">Flag</span></tt> classes, if you like.
+<p>You can go on and define <tt class="docutils literal">Option</tt> and <tt class="docutils literal">Flag</tt> classes, if you like.
Using custom annotation objects you could do advanced things like extracting the
annotations from a configuration file or from a database, but I expect such
use cases to be quite rare: the default mechanism should work
@@ -1157,7 +1167,7 @@ consistent, I have decided not to support this feature.</li>
<li>plac does not support the destination concept: the destination
coincides with the name of the argument, always. This restriction
has some drawbacks. For instance, suppose you want to define a long
-option called <tt class="docutils literal"><span class="pre">--yield</span></tt>. In this case the destination would be <tt class="docutils literal"><span class="pre">yield</span></tt>,
+option called <tt class="docutils literal"><span class="pre">--yield</span></tt>. In this case the destination would be <tt class="docutils literal">yield</tt>,
which is a Python keyword, and since you cannot introduce an
argument with that name in a function definition, it is impossible
to implement it. Your choices are to change the name of the long
@@ -1167,16 +1177,16 @@ documentation puts it: <em>Required options are generally considered bad
form - normal users expect options to be optional. You should avoid
the use of required options whenever possible.</em></li>
<li><a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> supports only regular boolean flags. <a class="reference external" href="http://argparse.googlecode.com">argparse</a> has the ability to
-define generalized two-value flags with values different from <tt class="docutils literal"><span class="pre">True</span></tt>
-and <tt class="docutils literal"><span class="pre">False</span></tt>. An earlier version of <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> had this feature too, but
+define generalized two-value flags with values different from <tt class="docutils literal">True</tt>
+and <tt class="docutils literal">False</tt>. An earlier version of <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> had this feature too, but
since you can use options with two choices instead, and in any case
-the conversion from <tt class="docutils literal"><span class="pre">{True,</span> <span class="pre">False}</span></tt> to any couple of values
+the conversion from <tt class="docutils literal">{True, False}</tt> to any couple of values
can be trivially implemented with a ternary operator
-(<tt class="docutils literal"><span class="pre">value1</span> <span class="pre">if</span> <span class="pre">flag</span> <span class="pre">else</span> <span class="pre">value2</span></tt>), I have removed it (KISS rules!).</li>
-<li><a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> does not support <tt class="docutils literal"><span class="pre">nargs</span></tt> options directly (it uses them internally,
+(<tt class="docutils literal">value1 if flag else value2</tt>), I have removed it (KISS rules!).</li>
+<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 for <tt class="docutils literal"><span class="pre">nargs</span></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
@@ -1185,9 +1195,9 @@ that the ability to define your own annotation objects may mitigate the
need for custom actions.</li>
</ul>
<p>I should stress again that if you want to access all of the <a class="reference external" href="http://argparse.googlecode.com">argparse</a> features
-from <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> you can use <tt class="docutils literal"><span class="pre">plac.parser_from</span></tt> and you will get
+from <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> you can use <tt class="docutils literal">plac.parser_from</tt> and you will get
the underlying <a class="reference external" href="http://argparse.googlecode.com/svn/tags/r11/doc/ArgumentParser.html">ArgumentParser</a> object. The the full power of <a class="reference external" href="http://argparse.googlecode.com">argparse</a>
-is then available to you: you can use <tt class="docutils literal"><span class="pre">add_argument</span></tt>, <tt class="docutils literal"><span class="pre">add_subparsers()</span></tt>,
+is then available to you: you can use <tt class="docutils literal">add_argument</tt>, <tt class="docutils literal">add_subparsers()</tt>,
etc. In other words, while some features are not supported directly,
<em>all</em> features are supported indirectly.</p>
</div>
@@ -1235,8 +1245,8 @@ of functions annotations in Python 3.</li>
</ol>
<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"><span class="pre">optionparser</span></tt> name was ruled out, since I was
-now using <a class="reference external" href="http://argparse.googlecode.com">argparse</a>; a name like <tt class="docutils literal"><span class="pre">argparse_plus</span></tt> was also ruled out,
+annotations. The <tt class="docutils literal">optionparser</tt> name was ruled out, since I was
+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
diff --git a/plac/doc/plac.pdf b/plac/doc/plac.pdf
index 9b3a793..229e51f 100644
--- a/plac/doc/plac.pdf
+++ b/plac/doc/plac.pdf
@@ -207,7 +207,7 @@ endobj
/Dest [ 76 0 R
/XYZ
62.69291
- 671.8236
+ 623.8236
0 ]
/Rect [ 62.69291
509.5936
@@ -225,7 +225,7 @@ endobj
/Dest [ 76 0 R
/XYZ
62.69291
- 671.8236
+ 623.8236
0 ]
/Rect [ 527.0227
509.5936
@@ -240,10 +240,10 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 80 0 R
+ /Dest [ 82 0 R
/XYZ
62.69291
- 162.6236
+ 765.0236
0 ]
/Rect [ 62.69291
491.5936
@@ -258,10 +258,10 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 80 0 R
+ /Dest [ 82 0 R
/XYZ
62.69291
- 162.6236
+ 765.0236
0 ]
/Rect [ 527.0227
491.5936
@@ -279,7 +279,7 @@ endobj
/Dest [ 82 0 R
/XYZ
62.69291
- 351.7299
+ 304.7299
0 ]
/Rect [ 62.69291
473.5936
@@ -297,7 +297,7 @@ endobj
/Dest [ 82 0 R
/XYZ
62.69291
- 351.7299
+ 304.7299
0 ]
/Rect [ 527.0227
473.5936
@@ -315,7 +315,7 @@ endobj
/Dest [ 89 0 R
/XYZ
62.69291
- 603.8236
+ 558.6236
0 ]
/Rect [ 62.69291
455.5936
@@ -333,7 +333,7 @@ endobj
/Dest [ 89 0 R
/XYZ
62.69291
- 603.8236
+ 558.6236
0 ]
/Rect [ 527.0227
455.5936
@@ -351,7 +351,7 @@ endobj
/Dest [ 91 0 R
/XYZ
62.69291
- 494.4849
+ 474.4849
0 ]
/Rect [ 62.69291
437.5936
@@ -369,7 +369,7 @@ endobj
/Dest [ 91 0 R
/XYZ
62.69291
- 494.4849
+ 474.4849
0 ]
/Rect [ 527.0227
437.5936
@@ -423,7 +423,7 @@ endobj
/Dest [ 106 0 R
/XYZ
62.69291
- 619.8236
+ 631.8236
0 ]
/Rect [ 62.69291
401.5936
@@ -441,7 +441,7 @@ endobj
/Dest [ 106 0 R
/XYZ
62.69291
- 619.8236
+ 631.8236
0 ]
/Rect [ 521.4627
401.5936
@@ -459,7 +459,7 @@ endobj
/Dest [ 108 0 R
/XYZ
62.69291
- 683.8236
+ 695.8236
0 ]
/Rect [ 62.69291
383.5936
@@ -477,7 +477,7 @@ endobj
/Dest [ 108 0 R
/XYZ
62.69291
- 683.8236
+ 695.8236
0 ]
/Rect [ 521.4627
383.5936
@@ -495,7 +495,7 @@ endobj
/Dest [ 138 0 R
/XYZ
62.69291
- 741.0236
+ 765.0236
0 ]
/Rect [ 62.69291
365.5936
@@ -513,7 +513,7 @@ endobj
/Dest [ 138 0 R
/XYZ
62.69291
- 741.0236
+ 765.0236
0 ]
/Rect [ 521.4627
365.5936
@@ -531,7 +531,7 @@ endobj
/Dest [ 138 0 R
/XYZ
62.69291
- 252.0236
+ 276.0236
0 ]
/Rect [ 62.69291
347.5936
@@ -549,7 +549,7 @@ endobj
/Dest [ 138 0 R
/XYZ
62.69291
- 252.0236
+ 276.0236
0 ]
/Rect [ 521.4627
347.5936
@@ -1120,9 +1120,9 @@ endobj
0
0 ]
/Rect [ 62.69291
- 424.9936
+ 400.9936
84.20915
- 436.9936 ]
+ 412.9936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1135,9 +1135,9 @@ endobj
0
0 ]
/Rect [ 91.59679
- 203.7936
+ 179.7936
109.9368
- 215.7936 ]
+ 191.7936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1173,9 +1173,9 @@ endobj
0
0 ]
/Rect [ 446.1627
- 699.3936
+ 651.3936
464.5027
- 711.3936 ]
+ 663.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1188,9 +1188,9 @@ endobj
0
0 ]
/Rect [ 357.8702
- 588.3936
+ 540.3936
416.0058
- 600.3936 ]
+ 552.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1203,9 +1203,9 @@ endobj
0
0 ]
/Rect [ 182.0729
- 576.3936
+ 528.3936
234.3229
- 588.3936 ]
+ 540.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1218,9 +1218,9 @@ endobj
0
0 ]
/Rect [ 62.69291
- 546.3936
+ 498.3936
84.28901
- 558.3936 ]
+ 510.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1233,9 +1233,9 @@ endobj
0
0 ]
/Rect [ 161.7834
- 546.3936
+ 498.3936
217.2895
- 558.3936 ]
+ 510.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1248,9 +1248,9 @@ endobj
0
0 ]
/Rect [ 514.2427
- 343.1936
+ 295.1936
532.2243
- 355.1936 ]
+ 307.1936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1288,9 +1288,9 @@ endobj
0
0 ]
/Rect [ 183.9662
- 431.7936
+ 395.7936
205.2545
- 443.7936 ]
+ 407.7936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1303,33 +1303,17 @@ endobj
0
0 ]
/Rect [ 184.4029
- 235.3936
+ 199.3936
202.7429
- 247.3936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER68': class PDFDictionary
-79 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://pypi.python.org/pypi/plac) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 62.69291
- 127.1936
- 84.57878
- 139.1936 ]
+ 211.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
% 'Page6': class PDFPage
-80 0 obj
+79 0 obj
% Page dictionary
<< /Annots [ 77 0 R
- 78 0 R
- 79 0 R ]
+ 78 0 R ]
/Contents 178 0 R
/MediaBox [ 0
0
@@ -1346,6 +1330,21 @@ endobj
/Trans << >>
/Type /Page >>
endobj
+% 'Annot.NUMBER68': class PDFDictionary
+80 0 obj
+<< /A << /S /URI
+ /Type /Action
+ /URI (http://pypi.python.org/pypi/plac) >>
+ /Border [ 0
+ 0
+ 0 ]
+ /Rect [ 62.69291
+ 729.5936
+ 84.57878
+ 741.5936 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
% 'Annot.NUMBER69': class PDFDictionary
81 0 obj
<< /A << /S /URI
@@ -1355,16 +1354,17 @@ endobj
0
0 ]
/Rect [ 110.2829
- 292.2999
+ 245.2999
132.8629
- 304.2999 ]
+ 257.2999 ]
/Subtype /Link
/Type /Annot >>
endobj
% 'Page7': class PDFPage
82 0 obj
% Page dictionary
-<< /Annots [ 81 0 R ]
+<< /Annots [ 80 0 R
+ 81 0 R ]
/Contents 179 0 R
/MediaBox [ 0
0
@@ -1390,9 +1390,9 @@ endobj
0
0 ]
/Rect [ 358.6729
- 619.3936
+ 574.1936
379.7929
- 631.3936 ]
+ 586.1936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1405,9 +1405,9 @@ endobj
0
0 ]
/Rect [ 104.3155
- 556.3936
+ 511.1936
143.7755
- 568.3936 ]
+ 523.1936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1420,9 +1420,9 @@ endobj
0
0 ]
/Rect [ 414.3275
- 556.3936
+ 511.1936
453.7875
- 568.3936 ]
+ 523.1936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1435,9 +1435,9 @@ endobj
0
0 ]
/Rect [ 62.69291
- 544.3936
+ 499.1936
106.6498
- 556.3936 ]
+ 511.1936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1450,9 +1450,9 @@ endobj
0
0 ]
/Rect [ 189.6004
- 544.3936
+ 499.1936
207.9404
- 556.3936 ]
+ 511.1936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1465,9 +1465,9 @@ endobj
0
0 ]
/Rect [ 355.0429
- 352.3936
+ 307.1936
397.2829
- 364.3936 ]
+ 319.1936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1505,9 +1505,9 @@ endobj
0
0 ]
/Rect [ 384.3381
- 459.0549
+ 439.0549
405.6967
- 471.0549 ]
+ 451.0549 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1607,9 +1607,9 @@ endobj
0
0 ]
/Rect [ 62.69291
- 584.3936
+ 596.3936
83.9079
- 596.3936 ]
+ 608.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1622,9 +1622,9 @@ endobj
0
0 ]
/Rect [ 133.1029
- 584.3936
+ 596.3936
175.4379
- 596.3936 ]
+ 608.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1637,9 +1637,9 @@ endobj
0
0 ]
/Rect [ 454.1177
- 584.3936
+ 596.3936
496.4527
- 596.3936 ]
+ 608.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1652,9 +1652,9 @@ endobj
0
0 ]
/Rect [ 455.2227
- 542.3936
+ 554.3936
534.3667
- 554.3936 ]
+ 566.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1667,9 +1667,9 @@ endobj
0
0 ]
/Rect [ 127.99
- 375.1936
+ 387.1936
149.3857
- 387.1936 ]
+ 399.1936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1682,9 +1682,9 @@ endobj
0
0 ]
/Rect [ 326.9971
- 261.9936
+ 273.9936
351.8113
- 273.9936 ]
+ 285.9936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1697,9 +1697,9 @@ endobj
0
0 ]
/Rect [ 409.706
- 249.9936
+ 261.9936
453.2944
- 261.9936 ]
+ 273.9936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1712,9 +1712,9 @@ endobj
0
0 ]
/Rect [ 259.0928
- 237.9936
+ 249.9936
302.7528
- 249.9936 ]
+ 261.9936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1727,9 +1727,9 @@ endobj
0
0 ]
/Rect [ 258.3129
- 213.9936
+ 225.9936
279.4329
- 225.9936 ]
+ 237.9936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1742,9 +1742,9 @@ endobj
0
0 ]
/Rect [ 327.2261
- 195.9936
+ 207.9936
410.5152
- 207.9936 ]
+ 219.9936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1786,9 +1786,9 @@ endobj
0
0 ]
/Rect [ 106.6216
- 648.3936
+ 660.3936
128.3202
- 660.3936 ]
+ 672.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1821,9 +1821,9 @@ endobj
0
0 ]
/Rect [ 62.69291
- 705.5936
+ 729.5936
84.8789
- 717.5936 ]
+ 741.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1836,9 +1836,9 @@ endobj
0
0 ]
/Rect [ 466.5307
- 705.5936
+ 729.5936
509.8367
- 717.5936 ]
+ 741.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1851,9 +1851,9 @@ endobj
0
0 ]
/Rect [ 124.3929
- 681.5936
+ 705.5936
163.8529
- 693.5936 ]
+ 717.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1866,9 +1866,9 @@ endobj
0
0 ]
/Rect [ 85.69291
- 660.5936
+ 684.5936
107.7029
- 672.5936 ]
+ 696.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1881,9 +1881,9 @@ endobj
0
0 ]
/Rect [ 447.7627
- 660.5936
+ 684.5936
486.6727
- 672.5936 ]
+ 696.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1896,9 +1896,9 @@ endobj
0
0 ]
/Rect [ 493.1227
- 660.5936
+ 684.5936
531.6927
- 672.5936 ]
+ 696.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1911,9 +1911,9 @@ endobj
0
0 ]
/Rect [ 232.9652
- 636.5936
+ 660.5936
271.8752
- 648.5936 ]
+ 672.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1926,9 +1926,9 @@ endobj
0
0 ]
/Rect [ 85.69291
- 546.5936
+ 570.5936
127.9329
- 558.5936 ]
+ 582.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1941,9 +1941,9 @@ endobj
0
0 ]
/Rect [ 85.69291
- 528.5936
+ 552.5936
107.9337
- 540.5936 ]
+ 564.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1956,9 +1956,9 @@ endobj
0
0 ]
/Rect [ 308.5389
- 528.5936
+ 552.5936
351.8997
- 540.5936 ]
+ 564.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1971,9 +1971,9 @@ endobj
0
0 ]
/Rect [ 85.69291
- 486.5936
+ 510.5936
108.3529
- 498.5936 ]
+ 522.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -1986,9 +1986,9 @@ endobj
0
0 ]
/Rect [ 277.2428
- 486.5936
+ 510.5936
321.0228
- 498.5936 ]
+ 522.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -2001,9 +2001,9 @@ endobj
0
0 ]
/Rect [ 404.5839
- 474.5936
+ 498.5936
426.0657
- 486.5936 ]
+ 510.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -2016,9 +2016,9 @@ endobj
0
0 ]
/Rect [ 85.69291
- 420.5936
+ 444.5936
108.61
- 432.5936 ]
+ 456.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -2031,9 +2031,9 @@ endobj
0
0 ]
/Rect [ 459.2622
- 408.5936
+ 432.5936
481.289
- 420.5936 ]
+ 444.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -2046,9 +2046,9 @@ endobj
0
0 ]
/Rect [ 85.69291
- 378.5936
+ 402.5936
107.0573
- 390.5936 ]
+ 414.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -2061,9 +2061,9 @@ endobj
0
0 ]
/Rect [ 140.1729
- 366.5936
+ 390.5936
158.5129
- 378.5936 ]
+ 402.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -2076,9 +2076,9 @@ endobj
0
0 ]
/Rect [ 85.69291
- 348.5936
+ 372.5936
107.9247
- 360.5936 ]
+ 384.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -2091,9 +2091,9 @@ endobj
0
0 ]
/Rect [ 85.69291
- 336.5936
+ 360.5936
104.0329
- 348.5936 ]
+ 372.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -2106,9 +2106,9 @@ endobj
0
0 ]
/Rect [ 340.7317
- 303.5936
+ 327.5936
385.1185
- 315.5936 ]
+ 339.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -2121,9 +2121,9 @@ endobj
0
0 ]
/Rect [ 451.1022
- 303.5936
+ 327.5936
474.369
- 315.5936 ]
+ 339.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -2136,9 +2136,9 @@ endobj
0
0 ]
/Rect [ 321.0443
- 291.5936
+ 315.5936
399.3474
- 303.5936 ]
+ 327.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -2151,9 +2151,9 @@ endobj
0
0 ]
/Rect [ 62.69291
- 279.5936
+ 303.5936
107.3744
- 291.5936 ]
+ 315.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -2166,9 +2166,9 @@ endobj
0
0 ]
/Rect [ 109.0098
- 216.5936
+ 240.5936
131.9967
- 228.5936 ]
+ 252.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -2181,9 +2181,9 @@ endobj
0
0 ]
/Rect [ 397.2929
- 192.5936
+ 216.5936
415.6329
- 204.5936 ]
+ 228.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -2196,9 +2196,9 @@ endobj
0
0 ]
/Rect [ 85.69291
- 171.5936
+ 195.5936
128.4929
- 183.5936 ]
+ 207.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -2211,9 +2211,9 @@ endobj
0
0 ]
/Rect [ 85.69291
- 153.5936
+ 177.5936
124.5929
- 165.5936 ]
+ 189.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -2226,9 +2226,9 @@ endobj
0
0 ]
/Rect [ 464.3898
- 132.5936
+ 156.5936
503.8498
- 144.5936 ]
+ 168.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -2241,9 +2241,9 @@ endobj
0
0 ]
/Rect [ 305.0429
- 120.5936
+ 144.5936
323.3829
- 132.5936 ]
+ 156.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -2550,7 +2550,7 @@ endobj
% 'R155': class PDFInfo
155 0 obj
<< /Author (Michele Simionato)
- /CreationDate (D:20100603134000-01'00')
+ /CreationDate (D:20100603212333-01'00')
/Keywords ()
/Producer (ReportLab http://www.reportlab.com)
/Subject (\(unspecified\))
@@ -2603,7 +2603,7 @@ endobj
<< /Dest [ 76 0 R
/XYZ
62.69291
- 671.8236
+ 623.8236
0 ]
/Next 161 0 R
/Parent 156 0 R
@@ -2612,10 +2612,10 @@ endobj
endobj
% 'Outline.4': class OutlineEntryObject
161 0 obj
-<< /Dest [ 80 0 R
+<< /Dest [ 82 0 R
/XYZ
62.69291
- 162.6236
+ 765.0236
0 ]
/Next 162 0 R
/Parent 156 0 R
@@ -2627,7 +2627,7 @@ endobj
<< /Dest [ 82 0 R
/XYZ
62.69291
- 351.7299
+ 304.7299
0 ]
/Next 163 0 R
/Parent 156 0 R
@@ -2639,7 +2639,7 @@ endobj
<< /Dest [ 89 0 R
/XYZ
62.69291
- 603.8236
+ 558.6236
0 ]
/Next 164 0 R
/Parent 156 0 R
@@ -2651,7 +2651,7 @@ endobj
<< /Dest [ 91 0 R
/XYZ
62.69291
- 494.4849
+ 474.4849
0 ]
/Next 165 0 R
/Parent 156 0 R
@@ -2675,7 +2675,7 @@ endobj
<< /Dest [ 106 0 R
/XYZ
62.69291
- 619.8236
+ 631.8236
0 ]
/Next 167 0 R
/Parent 156 0 R
@@ -2687,7 +2687,7 @@ endobj
<< /Dest [ 108 0 R
/XYZ
62.69291
- 683.8236
+ 695.8236
0 ]
/Next 168 0 R
/Parent 156 0 R
@@ -2699,7 +2699,7 @@ endobj
<< /Dest [ 138 0 R
/XYZ
62.69291
- 741.0236
+ 765.0236
0 ]
/Next 169 0 R
/Parent 156 0 R
@@ -2711,7 +2711,7 @@ endobj
<< /Dest [ 138 0 R
/XYZ
62.69291
- 252.0236
+ 276.0236
0 ]
/Next 170 0 R
/Parent 156 0 R
@@ -2750,7 +2750,7 @@ endobj
64 0 R
69 0 R
76 0 R
- 80 0 R
+ 79 0 R
82 0 R
89 0 R
91 0 R
@@ -3000,7 +3000,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
@@ -3405,7 +3405,7 @@ endobj
% 'R176': class PDFStream
176 0 obj
% page stream
-<< /Length 4252 >>
+<< /Length 4277 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
@@ -3463,7 +3463,7 @@ BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (In other words, six lines of boilerplate h
Q
Q
q
-1 0 0 1 62.69291 441.4236 cm
+1 0 0 1 62.69291 417.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -3473,24 +3473,24 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 120 re B*
+n -6 -6 468.6898 144 re B*
Q
q
0 0 0 rg
-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
+BT 1 0 0 1 0 125.71 Tm /F4 10 Tf 12 TL (usage: example5.py [-h] dsn [table] [today]) Tj T* T* (Do something on the database) 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 409.4236 cm
+1 0 0 1 62.69291 385.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 220.2236 cm
+1 0 0 1 62.69291 196.2236 cm
q
q
1 0 0 1 0 0 cm
@@ -3510,7 +3510,7 @@ Q
Q
Q
q
-1 0 0 1 62.69291 188.2236 cm
+1 0 0 1 62.69291 164.2236 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 then you get the following nice usage message:) Tj T* ET
Q
@@ -3526,11 +3526,11 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 84 re B*
+n -6 -6 468.6898 60 re B*
Q
q
0 0 0 rg
-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
+BT 1 0 0 1 0 41.71 Tm /F4 10 Tf 12 TL (usage: example7.py [-h] dsn [scripts [scripts ...]]) Tj T* T* (Run the given scripts on the database) Tj T* T* ET
Q
Q
Q
@@ -3550,11 +3550,11 @@ endobj
% 'R177': class PDFStream
177 0 obj
% page stream
-<< /Length 5195 >>
+<< /Length 4903 >>
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 679.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -3564,48 +3564,48 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 36 re B*
+n -6 -6 468.6898 84 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
+BT 1 0 0 1 0 65.71 Tm /F4 10 Tf 12 TL (positional arguments:) Tj T* ( dsn) Tj T* ( scripts) Tj T* T* (optional arguments:) Tj T* ( -h, --help show this help message and exit) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 683.8236 cm
+1 0 0 1 62.69291 635.8236 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 .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 650.8236 cm
+1 0 0 1 62.69291 602.8236 cm
q
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 62.69291 560.8236 cm
+1 0 0 1 62.69291 512.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.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
q
-1 0 0 1 62.69291 518.8236 cm
+1 0 0 1 62.69291 470.8236 cm
q
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 488.8236 cm
+1 0 0 1 62.69291 440.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 371.6236 cm
+1 0 0 1 62.69291 323.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -3626,13 +3626,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 303.6236 cm
+1 0 0 1 62.69291 255.6236 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 .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 174.4236 cm
+1 0 0 1 62.69291 126.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -3646,41 +3646,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: 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) Tj T* ( SQL query) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 154.4236 cm
+1 0 0 1 62.69291 106.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 97.22362 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 468.6898 48 re B*
-Q
-q
-0 0 0 rg
-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 56.69291 56.69291 cm
q
0 0 0 rg
@@ -3694,11 +3673,11 @@ endobj
% 'R178': class PDFStream
178 0 obj
% page stream
-<< /Length 5451 >>
+<< /Length 5073 >>
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 691.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -3708,24 +3687,24 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 36 re B*
+n -6 -6 468.6898 72 re B*
Q
q
0 0 0 rg
-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
+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
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 695.8236 cm
+1 0 0 1 62.69291 659.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 602.6236 cm
+1 0 0 1 62.69291 566.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -3746,13 +3725,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 582.6236 cm
+1 0 0 1 62.69291 546.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 537.4236 cm
+1 0 0 1 62.69291 501.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -3773,14 +3752,14 @@ Q
Q
Q
q
-1 0 0 1 62.69291 517.4236 cm
+1 0 0 1 62.69291 481.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 62.69291 460.2236 cm
+1 0 0 1 62.69291 424.2236 cm
q
q
1 0 0 1 0 0 cm
@@ -3801,13 +3780,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 416.2236 cm
+1 0 0 1 62.69291 380.2236 cm
q
BT 1 0 0 1 0 28.82 Tm 3.203318 Tw 12 TL /F1 10 Tf 0 0 0 rg (Of course explicit is better than implicit, an no special cases are special enough, but sometimes) Tj T* 0 Tw .16832 Tw (practicality beats purity, so ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (is able to use smart defaults; in particular you can omit the third argument) Tj T* 0 Tw (and write:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 359.0236 cm
+1 0 0 1 62.69291 323.0236 cm
q
q
1 0 0 1 0 0 cm
@@ -3828,20 +3807,20 @@ Q
Q
Q
q
-1 0 0 1 62.69291 315.0236 cm
+1 0 0 1 62.69291 279.0236 cm
q
BT 1 0 0 1 0 28.82 Tm 1.123876 Tw 12 TL /F1 10 Tf 0 0 0 rg (When omitted, the third argument is assumed to be the first letter of the variable name for options and) Tj T* 0 Tw .334983 Tw (flags, and ) Tj /F4 10 Tf (None ) Tj /F1 10 Tf (for positional arguments. Moreover, smart enough to convert help messages into tuples;) Tj T* 0 Tw (in other words, you can just write ) Tj /F4 10 Tf ("Database dsn" ) Tj /F1 10 Tf (instead of ) Tj /F4 10 Tf (\("Database dsn", 'positional'\)) Tj /F1 10 Tf (.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 297.0236 cm
+1 0 0 1 62.69291 261.0236 cm
q
0 0 0 rg
BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (I should 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 251.8236 cm
+1 0 0 1 62.69291 215.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -3862,13 +3841,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 231.8236 cm
+1 0 0 1 62.69291 195.8236 cm
q
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 174.6236 cm
+1 0 0 1 62.69291 138.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -3889,18 +3868,6 @@ Q
Q
Q
q
-1 0 0 1 62.69291 141.6236 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 111.6236 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 56.69291 56.69291 cm
q
0 0 0 rg
@@ -3914,11 +3881,23 @@ endobj
% 'R179': class PDFStream
179 0 obj
% page stream
-<< /Length 4359 >>
+<< /Length 4742 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 648.1299 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 (Scripts with flags) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 714.0236 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 589.1299 cm
q
q
.96447 0 0 .96447 0 0 cm
@@ -3939,7 +3918,7 @@ Q
Q
Q
q
-1 0 0 1 62.69291 518.9299 cm
+1 0 0 1 62.69291 471.9299 cm
q
q
1 0 0 1 0 0 cm
@@ -3949,18 +3928,18 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 120 re B*
+n -6 -6 468.6898 108 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 101.71 Tm /F4 10 Tf 12 TL ($ python3 example9.py -h) Tj T* (usage: example9.py [-h] [-v] dsn) Tj T* T* (positional arguments:) Tj T* ( dsn connection string) Tj T* T* (optional arguments:) Tj T* ( -h, --help show this help message and exit) Tj T* ( -v, --verbose prints more info) Tj T* ET
+BT 1 0 0 1 0 89.71 Tm /F4 10 Tf 12 TL (usage: example9.py [-h] [-v] dsn) Tj T* T* (positional arguments:) Tj T* ( dsn connection string) Tj T* T* (optional arguments:) Tj T* ( -h, --help show this help message and exit) Tj T* ( -v, --verbose prints more info) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 473.7299 cm
+1 0 0 1 62.69291 426.7299 cm
q
q
1 0 0 1 0 0 cm
@@ -3981,31 +3960,31 @@ Q
Q
Q
q
-1 0 0 1 62.69291 429.7299 cm
+1 0 0 1 62.69291 382.7299 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 363.7299 cm
+1 0 0 1 62.69291 316.7299 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 as it is required by the Python syntax.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 330.7299 cm
+1 0 0 1 62.69291 283.7299 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 264.7299 cm
+1 0 0 1 62.69291 217.7299 cm
q
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 62.69291 219.5299 cm
+1 0 0 1 62.69291 172.5299 cm
q
q
1 0 0 1 0 0 cm
@@ -4026,14 +4005,14 @@ Q
Q
Q
q
-1 0 0 1 62.69291 199.5299 cm
+1 0 0 1 62.69291 152.5299 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
q
-1 0 0 1 62.69291 118.3299 cm
+1 0 0 1 62.69291 95.32986 cm
q
q
1 0 0 1 0 0 cm
@@ -4043,11 +4022,11 @@ 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 (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 29.71 Tm /F4 10 Tf 12 TL (def main\(dsn, *scripts\):) Tj T* ( ...) Tj T* (main.__annotations__ = dict\() Tj T* ET
Q
Q
Q
@@ -4067,17 +4046,38 @@ endobj
% 'R180': class PDFStream
180 0 obj
% page stream
-<< /Length 5557 >>
+<< /Length 5748 >>
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
+1 0 0 1 62.69291 727.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 36 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 17.71 Tm /F4 10 Tf 12 TL ( dsn="Database dsn",) Tj T* ( scripts="SQL scripts"\)) 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 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 647.8236 cm
+1 0 0 1 62.69291 602.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -4098,28 +4098,28 @@ Q
Q
Q
q
-1 0 0 1 62.69291 615.8236 cm
+1 0 0 1 62.69291 570.6236 cm
q
BT 1 0 0 1 0 16.82 Tm 1.422164 Tw 12 TL /F1 10 Tf 0 0 0 rg (In the rest of this article I will assume that you are using Python 2.X with ) Tj /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 582.8236 cm
+1 0 0 1 62.69291 537.6236 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 528.8236 cm
+1 0 0 1 62.69291 483.6236 cm
q
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 522.8236 cm
+1 0 0 1 62.69291 477.6236 cm
Q
q
-1 0 0 1 62.69291 510.8236 cm
+1 0 0 1 62.69291 465.6236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
BT 1 0 0 1 0 2 Tm T* ET
@@ -4134,40 +4134,40 @@ q
Q
Q
q
-1 0 0 1 62.69291 510.8236 cm
+1 0 0 1 62.69291 465.6236 cm
Q
q
-1 0 0 1 62.69291 468.8236 cm
+1 0 0 1 62.69291 423.6236 cm
q
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 438.8236 cm
+1 0 0 1 62.69291 393.6236 cm
q
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 408.8236 cm
+1 0 0 1 62.69291 363.6236 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 366.8236 cm
+1 0 0 1 62.69291 321.6236 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 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 348.8236 cm
+1 0 0 1 62.69291 303.6236 cm
q
BT 1 0 0 1 0 4.82 Tm 12 TL /F1 10 Tf 0 0 0 rg (Here is an example showing 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 140.4467 cm
+1 0 0 1 62.69291 95.24669 cm
q
q
.976496 0 0 .976496 0 0 cm
@@ -4188,13 +4188,6 @@ Q
Q
Q
q
-1 0 0 1 62.69291 120.4467 cm
-q
-0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (Here is the usage:) Tj T* ET
-Q
-Q
-q
1 0 0 1 56.69291 56.69291 cm
q
0 0 0 rg
@@ -4208,11 +4201,18 @@ endobj
% 'R181': class PDFStream
181 0 obj
% page stream
-<< /Length 3500 >>
+<< /Length 3603 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 631.8236 cm
+1 0 0 1 62.69291 753.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (Here is the usage:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 611.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -4233,13 +4233,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 599.8236 cm
+1 0 0 1 62.69291 579.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 506.4849 cm
+1 0 0 1 62.69291 486.4849 cm
q
q
.87797 0 0 .87797 0 0 cm
@@ -4260,19 +4260,19 @@ Q
Q
Q
q
-1 0 0 1 62.69291 473.4849 cm
+1 0 0 1 62.69291 453.4849 cm
q
BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Keyword arguments) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 443.4849 cm
+1 0 0 1 62.69291 423.4849 cm
q
BT 1 0 0 1 0 16.82 Tm .238651 Tw 12 TL /F1 10 Tf 0 0 0 rg (Starting from release 0.4, if your main function has keyword arguments, ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (recognizes arguments of the) Tj T* 0 Tw (form ) Tj /F4 10 Tf ("name=value" ) Tj /F1 10 Tf (in the command line. Here is an example:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 278.2849 cm
+1 0 0 1 62.69291 258.2849 cm
q
q
1 0 0 1 0 0 cm
@@ -4293,14 +4293,14 @@ Q
Q
Q
q
-1 0 0 1 62.69291 258.2849 cm
+1 0 0 1 62.69291 238.2849 cm
q
0 0 0 rg
BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (Here is the generated usage message:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 129.0849 cm
+1 0 0 1 62.69291 109.0849 cm
q
q
1 0 0 1 0 0 cm
@@ -4314,14 +4314,14 @@ 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: example12.py [-h] [-o OPT] [args [args ...]] [kw [kw ...]]) Tj T* T* (positional arguments:) Tj T* ( args default arguments) Tj T* ( kw keyword arguments) Tj T* T* (optional arguments:) Tj T* ( -h, --help show this help message and exit) Tj T* ( -o OPT, --opt OPT some option) Tj T* ET
+BT 1 0 0 1 0 101.71 Tm /F4 10 Tf 12 TL (usage: example12.py [-h] [-o OPT] [args [args ...]] [kw [kw ...]]) Tj T* T* (positional arguments:) Tj T* ( args default arguments) Tj T* ( kw keyword arguments) Tj T* T* (optional arguments:) Tj T* ( -h, --help show this help message and exit) Tj T* ( -o, --opt OPT some option) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 109.0849 cm
+1 0 0 1 62.69291 89.0849 cm
q
0 0 0 rg
BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (Here is how you call the script:) Tj T* ET
@@ -4341,7 +4341,7 @@ endobj
% 'R182': class PDFStream
182 0 obj
% page stream
-<< /Length 4164 >>
+<< /Length 4139 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
@@ -4454,7 +4454,7 @@ n -6 -6 468.6898 60 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 41.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* (A script to run queries and SQL scripts on a database) Tj T* ET
+BT 1 0 0 1 0 41.71 Tm /F4 10 Tf 12 TL (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* ET
Q
Q
Q
@@ -4474,11 +4474,11 @@ endobj
% 'R183': class PDFStream
183 0 obj
% page stream
-<< /Length 5890 >>
+<< /Length 5945 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 631.8236 cm
+1 0 0 1 62.69291 643.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -4488,42 +4488,42 @@ 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 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 101.71 Tm /F4 10 Tf 12 TL (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, --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 598.8236 cm
+1 0 0 1 62.69291 610.8236 cm
q
BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Advanced usage) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 568.8236 cm
+1 0 0 1 62.69291 580.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 526.8236 cm
+1 0 0 1 62.69291 538.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 472.8236 cm
+1 0 0 1 62.69291 484.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 403.6236 cm
+1 0 0 1 62.69291 415.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -4544,13 +4544,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 323.6236 cm
+1 0 0 1 62.69291 335.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 62.69291 278.4236 cm
+1 0 0 1 62.69291 290.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -4571,13 +4571,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 210.4236 cm
+1 0 0 1 62.69291 222.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 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 180.4236 cm
+1 0 0 1 62.69291 192.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
@@ -4593,10 +4593,10 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 72 re B*
+n -6 -6 468.6898 84 re B*
Q
q
-BT 1 0 0 1 0 53.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* ET
+BT 1 0 0 1 0 65.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* ET
Q
Q
Q
@@ -4616,11 +4616,11 @@ endobj
% 'R184': class PDFStream
184 0 obj
% page stream
-<< /Length 4195 >>
+<< /Length 4227 >>
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 727.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -4630,42 +4630,42 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 48 re B*
+n -6 -6 468.6898 36 re B*
Q
q
-BT 1 0 0 1 0 29.71 Tm 12 TL /F4 10 Tf 0 0 0 rg (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
+BT 1 0 0 1 0 17.71 Tm 12 TL /F4 10 Tf 0 0 0 rg (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 695.8236 cm
+1 0 0 1 62.69291 707.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 662.8236 cm
+1 0 0 1 62.69291 674.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 632.8236 cm
+1 0 0 1 62.69291 644.8236 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 602.8236 cm
+1 0 0 1 62.69291 614.8236 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
Q
q
-1 0 0 1 62.69291 473.6236 cm
+1 0 0 1 62.69291 485.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -4686,14 +4686,14 @@ Q
Q
Q
q
-1 0 0 1 62.69291 453.6236 cm
+1 0 0 1 62.69291 465.6236 cm
q
0 0 0 rg
BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (You can use such annotations objects as follows:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 276.4236 cm
+1 0 0 1 62.69291 288.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -4714,14 +4714,14 @@ Q
Q
Q
q
-1 0 0 1 62.69291 256.4236 cm
+1 0 0 1 62.69291 268.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 127.2236 cm
+1 0 0 1 62.69291 139.2236 cm
q
q
1 0 0 1 0 0 cm
@@ -4744,7 +4744,7 @@ Q
q
1 0 0 1 62.69291 95.22362 cm
q
-BT 1 0 0 1 0 16.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 ET
+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
@@ -4761,36 +4761,29 @@ endobj
% 'R185': class PDFStream
185 0 obj
% page stream
-<< /Length 9534 >>
+<< /Length 9331 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 753.0236 cm
-q
-0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (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 720.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 (plac vs argparse) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 678.0236 cm
+1 0 0 1 62.69291 702.0236 cm
q
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 672.0236 cm
+1 0 0 1 62.69291 696.0236 cm
Q
q
-1 0 0 1 62.69291 672.0236 cm
+1 0 0 1 62.69291 696.0236 cm
Q
q
-1 0 0 1 62.69291 618.0236 cm
+1 0 0 1 62.69291 642.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -4810,13 +4803,13 @@ q
Q
Q
q
-1 0 0 1 62.69291 618.0236 cm
+1 0 0 1 62.69291 642.0236 cm
Q
q
-1 0 0 1 62.69291 618.0236 cm
+1 0 0 1 62.69291 642.0236 cm
Q
q
-1 0 0 1 62.69291 540.0236 cm
+1 0 0 1 62.69291 564.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -4836,13 +4829,13 @@ q
Q
Q
q
-1 0 0 1 62.69291 540.0236 cm
+1 0 0 1 62.69291 564.0236 cm
Q
q
-1 0 0 1 62.69291 540.0236 cm
+1 0 0 1 62.69291 564.0236 cm
Q
q
-1 0 0 1 62.69291 498.0236 cm
+1 0 0 1 62.69291 522.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -4862,13 +4855,13 @@ q
Q
Q
q
-1 0 0 1 62.69291 498.0236 cm
+1 0 0 1 62.69291 522.0236 cm
Q
q
-1 0 0 1 62.69291 498.0236 cm
+1 0 0 1 62.69291 522.0236 cm
Q
q
-1 0 0 1 62.69291 432.0236 cm
+1 0 0 1 62.69291 456.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -4888,13 +4881,13 @@ q
Q
Q
q
-1 0 0 1 62.69291 432.0236 cm
+1 0 0 1 62.69291 456.0236 cm
Q
q
-1 0 0 1 62.69291 432.0236 cm
+1 0 0 1 62.69291 456.0236 cm
Q
q
-1 0 0 1 62.69291 390.0236 cm
+1 0 0 1 62.69291 414.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -4914,13 +4907,13 @@ q
Q
Q
q
-1 0 0 1 62.69291 390.0236 cm
+1 0 0 1 62.69291 414.0236 cm
Q
q
-1 0 0 1 62.69291 390.0236 cm
+1 0 0 1 62.69291 414.0236 cm
Q
q
-1 0 0 1 62.69291 360.0236 cm
+1 0 0 1 62.69291 384.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -4940,13 +4933,13 @@ q
Q
Q
q
-1 0 0 1 62.69291 360.0236 cm
+1 0 0 1 62.69291 384.0236 cm
Q
q
-1 0 0 1 62.69291 360.0236 cm
+1 0 0 1 62.69291 384.0236 cm
Q
q
-1 0 0 1 62.69291 318.0236 cm
+1 0 0 1 62.69291 342.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -4966,37 +4959,37 @@ q
Q
Q
q
-1 0 0 1 62.69291 318.0236 cm
+1 0 0 1 62.69291 342.0236 cm
Q
q
-1 0 0 1 62.69291 318.0236 cm
+1 0 0 1 62.69291 342.0236 cm
Q
q
-1 0 0 1 62.69291 264.0236 cm
+1 0 0 1 62.69291 288.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
Q
Q
q
-1 0 0 1 62.69291 231.0236 cm
+1 0 0 1 62.69291 255.0236 cm
q
BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (plac vs the rest of the world) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 189.0236 cm
+1 0 0 1 62.69291 213.0236 cm
q
BT 1 0 0 1 0 28.82 Tm 1.866905 Tw 12 TL /F1 10 Tf 0 0 0 rg (Originally ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (boasted about being "the easiest command-line arguments parser in the world". Since) Tj T* 0 Tw .306457 Tw (then, people started pointing out to me various projects which are based on the same idea \(extracting the) Tj T* 0 Tw (parser from the main function signature\) and are arguably even easier than ) Tj 0 0 .501961 rg (plac) Tj 0 0 0 rg (:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 183.0236 cm
+1 0 0 1 62.69291 207.0236 cm
Q
q
-1 0 0 1 62.69291 183.0236 cm
+1 0 0 1 62.69291 207.0236 cm
Q
q
-1 0 0 1 62.69291 165.0236 cm
+1 0 0 1 62.69291 189.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -5016,13 +5009,13 @@ q
Q
Q
q
-1 0 0 1 62.69291 165.0236 cm
+1 0 0 1 62.69291 189.0236 cm
Q
q
-1 0 0 1 62.69291 165.0236 cm
+1 0 0 1 62.69291 189.0236 cm
Q
q
-1 0 0 1 62.69291 147.0236 cm
+1 0 0 1 62.69291 171.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -5042,13 +5035,13 @@ q
Q
Q
q
-1 0 0 1 62.69291 147.0236 cm
+1 0 0 1 62.69291 171.0236 cm
Q
q
-1 0 0 1 62.69291 147.0236 cm
+1 0 0 1 62.69291 171.0236 cm
Q
q
-1 0 0 1 62.69291 117.0236 cm
+1 0 0 1 62.69291 141.0236 cm
q
BT 1 0 0 1 0 16.82 Tm 2.136457 Tw 12 TL /F1 10 Tf 0 0 0 rg (Luckily for me none of such projects had the idea of using function annotations and ) Tj 0 0 .501961 rg (argparse) Tj 0 0 0 rg (; as a) Tj T* 0 Tw (consequence, they are no match for the capabilities of ) Tj 0 0 .501961 rg (plac) Tj 0 0 0 rg (.) Tj T* ET
Q
@@ -5387,10 +5380,10 @@ xref
0000019085 00000 n
0000019448 00000 n
0000019700 00000 n
-0000019952 00000 n
-0000020189 00000 n
-0000020525 00000 n
-0000020762 00000 n
+0000019937 00000 n
+0000020264 00000 n
+0000020516 00000 n
+0000020753 00000 n
0000021080 00000 n
0000021332 00000 n
0000021582 00000 n
@@ -5485,39 +5478,39 @@ xref
0000052813 00000 n
0000058265 00000 n
0000062301 00000 n
-0000066656 00000 n
-0000071954 00000 n
-0000077508 00000 n
-0000081970 00000 n
-0000087630 00000 n
-0000091233 00000 n
-0000095500 00000 n
-0000101493 00000 n
-0000105791 00000 n
-0000115428 00000 n
-0000120297 00000 n
-0000120579 00000 n
-0000120658 00000 n
-0000120737 00000 n
-0000120816 00000 n
-0000120895 00000 n
-0000120974 00000 n
-0000121053 00000 n
-0000121132 00000 n
-0000121211 00000 n
-0000121290 00000 n
-0000121370 00000 n
-0000121450 00000 n
-0000121530 00000 n
-0000121610 00000 n
+0000066681 00000 n
+0000071687 00000 n
+0000076863 00000 n
+0000081708 00000 n
+0000087559 00000 n
+0000091265 00000 n
+0000095507 00000 n
+0000101555 00000 n
+0000105885 00000 n
+0000115319 00000 n
+0000120188 00000 n
+0000120470 00000 n
+0000120549 00000 n
+0000120628 00000 n
+0000120707 00000 n
+0000120786 00000 n
+0000120865 00000 n
+0000120944 00000 n
+0000121023 00000 n
+0000121102 00000 n
+0000121181 00000 n
+0000121261 00000 n
+0000121341 00000 n
+0000121421 00000 n
+0000121501 00000 n
trailer
<< /ID
% ReportLab generated PDF document -- digest (http://www.reportlab.com)
- [(\327\356z\177\243/|\227\336\271+MV\360\206~) (\327\356z\177\243/|\227\336\271+MV\360\206~)]
+ [(\004\3357bm\360\021\276[\204N}h[\215K) (\004\3357bm\360\021\276[\204N}h[\215K)]
/Info 155 0 R
/Root 154 0 R
/Size 202 >>
startxref
-121659
+121550
%%EOF
diff --git a/plac/doc/plac.txt b/plac/doc/plac.txt
index 2cd29a6..dc631d9 100644
--- a/plac/doc/plac.txt
+++ b/plac/doc/plac.txt
@@ -136,17 +136,10 @@ With plac_ the entire ``__main__`` block reduces to the usual two lines::
import plac; plac.call(main)
In other words, six lines of boilerplate have been removed, and we get
-the usage message for free::
+the usage message for free:
- usage: example5.py [-h] dsn [table] [today]
-
- positional arguments:
- dsn
- table
- today
-
- optional arguments:
- -h, --help show this help message and exit
+.. include:: example5.help
+ :literal:
plac_ manages transparently even the case when you want to pass a
variable number of arguments. Here is an example, a script running
@@ -157,16 +150,10 @@ on a database a series of SQL scripts:
Using plac_, you can just replace the ``__main__`` block with the
usual two lines (I have defined an Emacs keybinding for them)
-and then you get the following nice usage message::
+and then you get the following nice usage message:
- usage: example7.py [-h] dsn [scripts [scripts ...]]
-
- positional arguments:
- dsn
- scripts
-
- optional arguments:
- -h, --help show this help message and exit
+.. include:: example7.help
+ :literal:
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
@@ -206,17 +193,10 @@ 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::
+message is the following:
- usage: example8.py [-h] [-c COMMAND] dsn
-
- positional arguments:
- dsn
-
- optional arguments:
- -h, --help show this help message and exit
- -c COMMAND, --command COMMAND
- SQL query
+.. include:: example8.help
+ :literal:
Here are two examples of usage::
@@ -283,17 +263,8 @@ if they are absent. Here is an example:
.. include:: example9.py
:literal:
-::
-
- $ python3 example9.py -h
- usage: example9.py [-h] [-v] dsn
-
- positional arguments:
- dsn connection string
-
- optional arguments:
- -h, --help show this help message and exit
- -v, --verbose prints more info
+.. include:: example9.help
+ :literal:
::
@@ -388,18 +359,10 @@ argparse_ documentation):
.. include:: example10.py
:literal:
-Here is the usage::
+Here is the usage:
- usage: example10.py [-h] {add,mul} [n [n ...]]
-
- A script to add and multiply numbers
-
- positional arguments:
- {add,mul} The name of an operator
- n A number
-
- optional arguments:
- -h, --help show this help message and exit
+.. include:: example10.help
+ :literal:
Notice that the docstring of the ``main`` function has been automatically added
to the usage message. Here are a couple of examples of use::
@@ -422,17 +385,10 @@ Here is an example:
.. include:: example12.py
:literal:
-Here is the generated usage message::
+Here is the generated usage message:
- usage: example12.py [-h] [-o OPT] [args [args ...]] [kw [kw ...]]
-
- positional arguments:
- args default arguments
- kw keyword arguments
-
- optional arguments:
- -h, --help show this help message and exit
- -o OPT, --opt OPT some option
+.. include:: example12.help
+ :literal:
Here is how you call the script::
@@ -463,22 +419,10 @@ string into a SqlSoup_ object:
.. include:: dbcli.py
:literal:
-Here is the usage message::
-
- $ python dbcli.py -h
- usage: dbcli.py [-h] [-H] [-c SQL] [-d |] db [scripts [scripts ...]]
+Here is the usage message:
- A script to run queries and SQL scripts on a database
-
- positional arguments:
- db Connection string
- scripts SQL scripts
-
- optional arguments:
- -h, --help show this help message and exit
- -H, --header Header
- -c SQL, --sqlcmd SQL SQL command
- -d |, --delimiter | Column separator
+.. include:: dbcli.help
+ :literal:
Advanced usage
----------------------------------------------------
@@ -562,17 +506,10 @@ You can use such annotations objects as follows:
.. include:: example11.py
:literal:
-Here is the usage message you get::
+Here is the usage message you get:
- usage: example11.py [-h] i n [rest [rest ...]]
-
- positional arguments:
- i This is an int
- n This is a float
- rest Other arguments
-
- optional arguments:
- -h, --help show this help message and exit
+.. include:: example11.help
+ :literal:
You can go on and define ``Option`` and ``Flag`` classes, if you like.
Using custom annotation objects you could do advanced things like extracting the
diff --git a/plac/plac.py b/plac/plac.py
index 309853a..21c4341 100644
--- a/plac/plac.py
+++ b/plac/plac.py
@@ -29,7 +29,7 @@ See plac/doc.html for the documentation.
"""
# this module should be kept Python 2.3 compatible
-__version__ = '0.4.0'
+__version__ = '0.4.1'
import re, sys, inspect, argparse
@@ -39,7 +39,7 @@ else:
class getfullargspec(object):
"A quick and dirty replacement for getfullargspec for Python 2.X"
def __init__(self, f):
- self.args, self.varargs, self.keywords, self.defaults = \
+ self.args, self.varargs, self.varkw, self.defaults = \
inspect.getargspec(f)
self.annotations = getattr(f, '__annotations__', {})
try:
@@ -57,8 +57,8 @@ def annotations(**ann):
args = fas.args
if fas.varargs:
args.append(fas.varargs)
- if fas.keywords:
- args.append(fas.keywords)
+ if fas.varkw:
+ args.append(fas.varkw)
for argname in ann:
if argname not in args:
raise NameError(
@@ -102,6 +102,20 @@ NONE = object() # sentinel use to signal the absence of a default
valid_attrs = getfullargspec(argparse.ArgumentParser.__init__).args[1:]
+class PlacHelpFormatter(argparse.HelpFormatter):
+ "Custom HelpFormatter which does not displau the default value twice"
+
+ def _format_action_invocation(self, action):
+ if not action.option_strings:
+ return self._metavar_formatter(action, action.dest)(1)[0]
+ long_short = tuple(action.option_strings)
+ if action.nargs == 0: # format is -s, --long
+ return '%s, %s' % long_short
+ else: # format is -s, --long ARGS
+ default = action.dest.upper()
+ args_string = self._format_args(action, default)
+ return '%s, %s %s' % (long_short + (args_string,))
+
def parser_from(func):
"""
Extract the arguments from the attributes of the passed function and
@@ -109,11 +123,12 @@ def parser_from(func):
"""
short_prefix = getattr(func, 'short_prefix', '-')
long_prefix = getattr(func, 'long_prefix', '--')
- attrs = {'description': func.__doc__}
+ attrs = dict(description=func.__doc__,
+ formatter_class=PlacHelpFormatter)
for n, v in vars(func).items():
if n in valid_attrs:
attrs[n] = v
- p = argparse.ArgumentParser(**attrs)
+ p = func.parser = argparse.ArgumentParser(**attrs)
f = p.argspec = getfullargspec(func)
defaults = f.defaults or ()
n_args = len(f.args)
@@ -121,10 +136,11 @@ def parser_from(func):
alldefaults = (NONE,) * (n_args - n_defaults) + defaults
for name, default in zip(f.args, alldefaults):
a = Annotation.from_(f.annotations.get(name, ()))
+ metavar = a.metavar
if default is NONE:
- dflt, metavar = None, a.metavar
+ dflt = None
else:
- dflt, metavar = default, a.metavar or str(default)
+ dflt = default
if a.kind in ('option', 'flag'):
short = short_prefix + (a.abbrev or name[0])
long = long_prefix + name
@@ -135,19 +151,22 @@ def parser_from(func):
p.add_argument(name, nargs='?', help=a.help, default=dflt,
type=a.type, choices=a.choices, metavar=metavar)
if a.kind == 'option':
+ if default is not NONE:
+ metavar = metavar or str(default)
p.add_argument(short, long, help=a.help, default=dflt,
type=a.type, choices=a.choices, metavar=metavar)
elif a.kind == 'flag':
- if default is not NONE:
- raise TypeError('Flag %r does not want a default' % name)
+ if default is not NONE and default is not False:
+ raise TypeError('Flag %r wants default False, got %r' %
+ (name, default))
p.add_argument(short, long, action='store_true', help=a.help)
if f.varargs:
a = Annotation.from_(f.annotations.get(f.varargs, ()))
p.add_argument(f.varargs, nargs='*', help=a.help, default=[],
type=a.type, metavar=a.metavar)
- if f.keywords:
- a = Annotation.from_(f.annotations.get(f.keywords, ()))
- p.add_argument(f.keywords, nargs='*', help=a.help, default={},
+ if f.varkw:
+ a = Annotation.from_(f.annotations.get(f.varkw, ()))
+ p.add_argument(f.varkw, nargs='*', help=a.help, default={},
type=a.type, metavar=a.metavar)
return p
@@ -171,7 +190,7 @@ def call(func, arglist=sys.argv[1:]):
provide a custom parse_annotation hook or replace the default one.
"""
p = parser_from(func)
- if p.argspec.keywords:
+ if p.argspec.varkw:
arglist, kwargs = extract_kwargs(arglist)
else:
kwargs = {}
diff --git a/plac/test_plac.py b/plac/test_plac.py
index 526cb7b..350900d 100644
--- a/plac/test_plac.py
+++ b/plac/test_plac.py
@@ -2,9 +2,13 @@
The tests are runnable with nose, with py.test, or even as standalone script
"""
-import sys
+import os, sys
import plac
+sys.path.insert(0, 'doc')
+
+######################## helpers #######################
+
def expect(errclass, func, *args, **kw):
try:
func(*args, **kw)
@@ -17,6 +21,22 @@ def parser_from(f, **kw):
f.__annotations__ = kw
return plac.parser_from(f)
+def compare_help(name):
+ sys.argv[0] = name + '.py'
+ dic = {}
+ try:
+ execfile(os.path.join('doc', name + '.py'), dic)
+ except NameError: # Python 3
+ exec(open(os.path.join('doc', name + '.py')).read(), dic)
+ except SyntaxError: # running Python 2 with some tests
+ return
+ p = plac.parser_from(dic['main'])
+ expected = open(os.path.join('doc', name + '.help')).read().strip()
+ got = p.format_help().strip()
+ assert got == expected, got
+
+####################### tests ############################
+
p1 = parser_from(lambda delete, *args: None,
delete=('delete a file', 'option'))
@@ -90,6 +110,10 @@ def test_kwargs():
expect(SystemExit, plac.call, main, ['arg1', 'arg2', 'a=1', 'opt=2'])
+def test_expected_help():
+ for fname in os.listdir('doc'):
+ if fname.endswith('.help'):
+ compare_help(fname[:-5])
if __name__ == '__main__':
n = 0