diff options
author | Michele Simionato <michele.simionato@gmail.com> | 2010-07-12 10:25:57 +0200 |
---|---|---|
committer | Michele Simionato <michele.simionato@gmail.com> | 2010-07-12 10:25:57 +0200 |
commit | d9cb2ba0701c884855900dadc95ede5b66d9fabf (patch) | |
tree | 581fa61ab0febcacd388099b170401ad4065668f | |
parent | 76e566e7fc5c55d8f03c24a2416b9583daeb3f07 (diff) | |
download | micheles-d9cb2ba0701c884855900dadc95ede5b66d9fabf.tar.gz |
Fixed various bugs (see CHANGES.txt)
-rw-r--r-- | plac/CHANGES.txt | 3 | ||||
-rw-r--r-- | plac/doc/ishelve2.py | 43 | ||||
-rw-r--r-- | plac/doc/plac.html | 176 | ||||
-rw-r--r-- | plac/doc/plac.pdf | 913 | ||||
-rw-r--r-- | plac/doc/plac.txt | 11 | ||||
-rw-r--r-- | plac/doc/plac_adv.txt | 4 | ||||
-rw-r--r-- | plac/doc/sql_interface.py | 11 | ||||
-rw-r--r-- | plac/plac_ext.py | 11 | ||||
-rw-r--r-- | plac/plac_runner.py | 58 |
9 files changed, 721 insertions, 509 deletions
diff --git a/plac/CHANGES.txt b/plac/CHANGES.txt index e7ef6f6..ddd57e0 100644 --- a/plac/CHANGES.txt +++ b/plac/CHANGES.txt @@ -1,6 +1,9 @@ HISTORY ---------- +0.6.1 Fixed the history file location; added the ability to pass a split + function; added two forgotten files; added a reference to cmd2 by + Catherine Devlin (2010-07-12) 0.6.0 Improvement the interactive experience with full readline support and custom help. Added support for long running command, via threads and processes (2010-07-11). diff --git a/plac/doc/ishelve2.py b/plac/doc/ishelve2.py new file mode 100644 index 0000000..9b8b57e --- /dev/null +++ b/plac/doc/ishelve2.py @@ -0,0 +1,43 @@ +# ishelve2.py +import shelve, os, sys, plac + +class ShelveInterface(object): + "A minimal interface over a shelve object." + commands = 'set', 'show', 'showall', 'delete' + @plac.annotations( + configfile=('path name of the shelve', 'option')) + def __init__(self, configfile='~/conf.shelve'): + self.fname = os.path.expanduser(configfile) + self.__doc__ += '\nOperating on %s.\n.help to see '\ + 'the available commands.\n' % self.fname + def __enter__(self): + self.sh = shelve.open(self.fname) + return self + def __exit__(self, etype, exc, tb): + self.sh.close() + def set(self, name, value): + "set name value" + yield 'setting %s=%s' % (name, value) + self.sh[name] = value + def show(self, *names): + "show given parameters" + for name in names: + yield '%s = %s' % (name, self.sh[name]) # no error checking + def showall(self): + "show all parameters" + for name in self.sh: + yield '%s = %s' % (name, self.sh[name]) + def delete(self, name=None): + "delete given parameter (or everything)" + if name is None: + yield 'deleting everything' + self.sh.clear() + else: + yield 'deleting %s' % name + del self.sh[name] # no error checking + +main = ShelveInterface # the main 'function' can also be a class! + +if __name__ == '__main__': + shelve_interface = plac.call(main) + plac.Interpreter(shelve_interface).interact() diff --git a/plac/doc/plac.html b/plac/doc/plac.html index c63e131..37184e5 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.6: http://docutils.sourceforge.net/" /> +<meta name="generator" content="Docutils 0.5: http://docutils.sourceforge.net/" /> <title>Plac: Parsing the Command Line the Easy Way</title> <meta name="author" content="Michele Simionato" /> <meta name="date" content="June 2010" /> @@ -431,7 +431,7 @@ h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { </tr> <tr class="field"><th class="docinfo-name">Requires:</th><td class="field-body">Python 2.3+</td> </tr> -<tr class="field"><th class="docinfo-name">Installation:</th><td class="field-body"><tt class="docutils literal">easy_install <span class="pre">-U</span> plac</tt></td> +<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">-U</span> <span class="pre">plac</span></tt></td> </tr> <tr class="field"><th class="docinfo-name">License:</th><td class="field-body">BSD license</td> </tr> @@ -525,7 +525,7 @@ if __name__ == '__main__': sys.exit('Unrecognized arguments: %s' % ' '.join(sys.argv[2:])) </pre> -<p>As you see the whole <tt class="docutils literal">if __name__ == '__main__'</tt> block (nine lines) +<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) is essentially boilerplate that should not exist. Actually I think the language should recognize the main function and pass to it the command-line arguments automatically; unfortunaly this is unlikely to @@ -615,12 +615,12 @@ if __name__ == '__main__': </pre> <p>Here I want to perform a query on a database table, by extracting the -most recent 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>) +most recent 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>) it also makes sense to make it a default argument. Performing the parsing of the command-line arguments by hand takes 8 ugly lines of boilerplate (using <a class="reference external" href="http://argparse.googlecode.com">argparse</a> would require about the same number of lines). -With <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> the entire <tt class="docutils literal">__main__</tt> block reduces to the usual two lines:</p> +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> <pre class="literal-block"> if __name__ == '__main__': import plac; plac.call(main) @@ -680,7 +680,7 @@ let's the machine take care of the details.</p> 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">main</tt> function.</p> +the <tt class="docutils literal"><span class="pre">main</span></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 it is:</p> @@ -698,7 +698,7 @@ if __name__ == '__main__': import plac; plac.call(main) </pre> -<p>Here the arguments of the <tt class="docutils literal">main</tt> function have been annotated with +<p>Here the arguments of the <tt class="docutils literal"><span class="pre">main</span></tt> function have been annotated with strings which are intented to be used in the help message:</p> <pre class="literal-block"> usage: example7_.py [-h] dsn [scripts [scripts ...]] @@ -740,10 +740,10 @@ if __name__ == '__main__': import plac; plac.call(main) </pre> -<p>Here the argument <tt class="docutils literal">command</tt> has been annotated with the tuple -<tt class="docutils literal">("SQL query", 'option', 'c')</tt>: the first string is the help string +<p>Here 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">("SQL</span> <span class="pre">query",</span> <span class="pre">'option',</span> <span class="pre">'c')</span></tt>: the first string is the help string which will appear in the usage message, the second string tells <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> -that <tt class="docutils literal">command</tt> is an option and the third string that there is also +that <tt class="docutils literal"><span class="pre">command</span></tt> is an option and the third string that there is also a short form of the option <tt class="docutils literal"><span class="pre">-c</span></tt>, the long form being <tt class="docutils literal"><span class="pre">--command</span></tt>. The usage message is the following:</p> <pre class="literal-block"> @@ -767,7 +767,7 @@ $ python3 example8.py --command="select * from table" dsn executing select * from table on dsn </pre> <p>The third argument in the function annotation can be omitted: in such -case it will be assumed to be <tt class="docutils literal">None</tt>. The consequence is that +case it will be assumed to be <tt class="docutils literal"><span class="pre">None</span></tt>. The consequence is that the usual dichotomy between long and short options (GNU-style options) disappears: we get <em>smart options</em>, which have the single character prefix of short options and behave like both long and short options, since @@ -808,8 +808,8 @@ $ python3 example6.py -com="select" dsn usage: example6.py [-h] [-command COMMAND] dsn example6.py: error: unrecognized arguments: -com=select </pre> -<p>If the option is not passed, the variable <tt class="docutils literal">command</tt> -will get the value <tt class="docutils literal">None</tt>. However, it is possible to specify a non-trivial +<p>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>. However, it is possible to specify a non-trivial default. Here is an example:</p> <pre class="literal-block"> # example8_.py @@ -843,7 +843,7 @@ executing 'select * from table' on dsn <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> is able to recognize flags, i.e. boolean options which are -<tt class="docutils literal">True</tt> if they are passed to the command line and <tt class="docutils literal">False</tt> +<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> if they are absent. Here is an example:</p> <pre class="literal-block"> # example9.py @@ -873,12 +873,12 @@ $ python3 example9.py -v dsn connecting to dsn </pre> <p>Notice that it is an error trying to specify a default for flags: the -default value for a flag is always <tt class="docutils literal">False</tt>. If you feel the need to +default value for a flag is always <tt class="docutils literal"><span class="pre">False</span></tt>. If you feel the need to implement non-boolean flags, you should use an option with two choices, as explained in the "more features" 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">main</tt> function write first the flag arguments, then the option +the <tt class="docutils literal"><span class="pre">main</span></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 @@ -913,7 +913,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">plac.annotations</tt> decorator that performs the check for you:</p> +<tt class="docutils literal"><span class="pre">plac.annotations</span></tt> decorator that performs the check for you:</p> <pre class="literal-block"> @plac.annotations( dsn="Database dsn", @@ -922,7 +922,7 @@ def main(dsn, *scripts): ... </pre> <p>In the rest of this article I will assume that you are using Python 2.X with -X >= 4 and I will use the <tt class="docutils literal">plac.annotations</tt> decorator. Notice however +X >= 4 and I will use the <tt class="docutils literal"><span class="pre">plac.annotations</span></tt> decorator. Notice however that the core features of <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> run even on Python 2.3.</p> </div> <div class="section" id="more-features"> @@ -934,19 +934,19 @@ the features of <a class="reference external" href="http://argparse.googlecode.c in <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a>. Until now, I have only showed simple annotations, but in general an annotation is a 6-tuple of the form</p> <blockquote> -<tt class="docutils literal">(help, kind, abbrev, type, choices, metavar)</tt></blockquote> -<p>where <tt class="docutils literal">help</tt> is the help message, <tt class="docutils literal">kind</tt> is a string in the set { -<tt class="docutils literal">"flag"</tt>, <tt class="docutils literal">"option"</tt>, <tt class="docutils literal">"positional"</tt>}, <tt class="docutils literal">abbrev</tt> is a -one-character string or <tt class="docutils literal">None</tt>, <tt class="docutils literal">type</tt> is a callable taking a +<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">"flag"</span></tt>, <tt class="docutils literal"><span class="pre">"option"</span></tt>, <tt class="docutils literal"><span class="pre">"positional"</span></tt>}, <tt class="docutils literal"><span class="pre">abbrev</span></tt> is a +one-character string or <tt class="docutils literal"><span class="pre">None</span></tt>, <tt class="docutils literal"><span class="pre">type</span></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 +<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 from the string type to any Python type; by default there is no -conversion 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 +conversion 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 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> @@ -989,7 +989,7 @@ optional arguments: -h, --help show this help message and exit </pre> -<p>Notice that the docstring of the <tt class="docutils literal">main</tt> function has been automatically added +<p>Notice that the docstring of the <tt class="docutils literal"><span class="pre">main</span></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 @@ -1000,13 +1000,13 @@ $ python example10.py ad 1 2 3 4 # a mispelling error usage: example10.py [-h] {add,mul} [n [n ...]] example10.py: error: argument operator: invalid choice: 'ad' (choose from 'add', 'mul') </pre> -<p><tt class="docutils literal">plac.call</tt> can also be used in doctests like this:</p> +<p><tt class="docutils literal"><span class="pre">plac.call</span></tt> can also be used in doctests like this:</p> <pre class="doctest-block"> >>> import plac, example10 >>> plac.call(example10.main, ['add', '1', '2']) 3.0 </pre> -<p><tt class="docutils literal">plac.call</tt> works for generators too:</p> +<p><tt class="docutils literal"><span class="pre">plac.call</span></tt> works for generators too:</p> <pre class="doctest-block"> >>> def main(n): ... for i in range(int(n)): @@ -1014,12 +1014,12 @@ example10.py: error: argument operator: invalid choice: 'ad' (choose from 'add', >>> plac.call(main, ['3']) [0, 1, 2] </pre> -<p>Internally <tt class="docutils literal">plac.call</tt> tries to convert the output of the main function +<p>Internally <tt class="docutils literal"><span class="pre">plac.call</span></tt> tries to convert the output of the main function into a list, if possible. If the output is not iterable or it is a string, it is left unchanged, but if it is iterable it is converted. -In particular, generator objects are exhausted by <tt class="docutils literal">plac.call</tt>.</p> +In particular, generator objects are exhausted by <tt class="docutils literal"><span class="pre">plac.call</span></tt>.</p> <p>This behavior avoids mistakes like forgetting of applying -<tt class="docutils literal">list(result)</tt> to the result of <tt class="docutils literal">plac.call</tt>; moreover it makes +<tt class="docutils literal"><span class="pre">list(result)</span></tt> to the result of <tt class="docutils literal"><span class="pre">plac.call</span></tt>; moreover it makes errors visible early, and avoids mistakes in code like the following:</p> <pre class="literal-block"> try: @@ -1030,13 +1030,13 @@ except: <p>Without the "listify" functionality, a main function returning a generator object would not raise any exception until the generator is iterated over.</p> -<p>If you are a fan of lazyness, you can still have it by setting the <tt class="docutils literal">eager</tt> -flag to <tt class="docutils literal">False</tt>, as in the following example:</p> +<p>If you are a fan of lazyness, you can still have it by setting the <tt class="docutils literal"><span class="pre">eager</span></tt> +flag to <tt class="docutils literal"><span class="pre">False</span></tt>, as in the following example:</p> <pre class="literal-block"> for line in plac.call(main, args, eager=False): print(line) </pre> -<p>If <tt class="docutils literal">main</tt> returns a generator object this example will print each +<p>If <tt class="docutils literal"><span class="pre">main</span></tt> returns a generator object this example will print each line as soon as available, whereas the default behaviour is to print all the lines together and the end of the computation.</p> </div> @@ -1044,7 +1044,7 @@ all the lines together and the end of the computation.</p> <h1><a class="toc-backref" href="#id8">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">type</tt> feature to automagically convert a SQLAlchemy connection +of the <tt class="docutils literal"><span class="pre">type</span></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 @@ -1079,12 +1079,12 @@ if __name__ == '__main__': </pre> <p>You can see the <em>yield-is-print</em> pattern here: instead of using -<tt class="docutils literal">print</tt> in the main function, I use <tt class="docutils literal">yield</tt>, and I perform the -print in the <tt class="docutils literal">__main__</tt> block. The advantage of the pattern is that -tests invoking <tt class="docutils literal">plac.call</tt> and checking the result become trivial: +<tt class="docutils literal"><span class="pre">print</span></tt> in the main function, I use <tt class="docutils literal"><span class="pre">yield</span></tt>, and I perform the +print in the <tt class="docutils literal"><span class="pre">__main__</span></tt> block. The advantage of the pattern is that +tests invoking <tt class="docutils literal"><span class="pre">plac.call</span></tt> and checking the result become trivial: had I performed the printing in the main function, the test would have -involved an ugly hack like redirecting <tt class="docutils literal">sys.stdout</tt> to a -<tt class="docutils literal">StringIO</tt> object.</p> +involved an ugly hack like redirecting <tt class="docutils literal"><span class="pre">sys.stdout</span></tt> to a +<tt class="docutils literal"><span class="pre">StringIO</span></tt> object.</p> <p>Here is the usage message:</p> <pre class="literal-block"> usage: dbcli.py [-h] [-H] [-c SQL] [-d |] db [scripts [scripts ...]] @@ -1108,7 +1108,7 @@ optional arguments: <h1><a class="toc-backref" href="#id9">Keyword arguments</a></h1> <p>Starting from release 0.4, <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> supports keyword arguments. In practice that means that if your main function has keyword arguments, -<a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> treats specially arguments of the form <tt class="docutils literal">"name=value"</tt> in the +<a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> treats specially arguments of the form <tt class="docutils literal"><span class="pre">"name=value"</span></tt> in the command line. Here is an example:</p> <pre class="literal-block"> # example12.py @@ -1152,7 +1152,7 @@ args=('a1', 'a2') kw={'name': 'value'} </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">opt</tt> +are not alreay taken; for instance in this examples the name <tt class="docutils literal"><span class="pre">opt</span></tt> is taken:</p> <pre class="literal-block"> $ python example12.py 1 2 kw1=1 kw2=2 opt=0 @@ -1187,7 +1187,7 @@ DEFAULT_SHELVE = os.path.expanduser('~/conf.shelve') setters='setters param=value') def main(help, showall, clear, delete, filename=DEFAULT_SHELVE, *params, **setters): - "A simple interface to a shelve" + "A simple interface to a shelve. Use .help to see the available commands." sh = shelve.open(filename) try: if not any([help, showall, clear, delete, params, setters]): @@ -1234,29 +1234,29 @@ if __name__ == '__main__': implemented a custom help command.</li> <li>I have changed the prefix character used to recognize the options to a dot.</li> -<li>Keyword arguments recognition (in the <tt class="docutils literal">**setters</tt>) is used to make it +<li>Keyword arguments recognition (in the <tt class="docutils literal"><span class="pre">**setters</span></tt>) is used to make it possible to store a value in the shelve with the syntax -<tt class="docutils literal">param_name=param_value</tt>.</li> -<li><tt class="docutils literal">*params</tt> are used to retrieve parameters from the shelve and some +<tt class="docutils literal"><span class="pre">param_name=param_value</span></tt>.</li> +<li><tt class="docutils literal"><span class="pre">*params</span></tt> are used to retrieve parameters from the shelve and some error checking is performed in the case of missing parameters</li> -<li>A command to clear the shelve is implemented as a flag (<tt class="docutils literal">.clear</tt>).</li> +<li>A command to clear the shelve is implemented as a flag (<tt class="docutils literal"><span class="pre">.clear</span></tt>).</li> <li>A command to delete a given parameter is implemented as an option -(<tt class="docutils literal">.delete</tt>).</li> -<li>There is an option with default (<tt class="docutils literal">.filename=conf.shelve</tt>) to store +(<tt class="docutils literal"><span class="pre">.delete</span></tt>).</li> +<li>There is an option with default (<tt class="docutils literal"><span class="pre">.filename=conf.shelve</span></tt>) to store the filename of the shelve.</li> <li>All things considered, the code looks like a poor man object oriented interface implemented with a chain of elifs instead of methods. Of course, <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> can do better than that, but let me start from a low-level approach first.</li> </ol> -<p>If you run <tt class="docutils literal">ishelve.py</tt> without arguments you get the following +<p>If you run <tt class="docutils literal"><span class="pre">ishelve.py</span></tt> without arguments you get the following message:</p> <pre class="literal-block"> $ python ishelve.py no arguments passed, use .help to see the available commands </pre> -<p>If you run <tt class="docutils literal">ishelve.py</tt> with the option <tt class="docutils literal">.h</tt> (or any abbreviation -of <tt class="docutils literal">.help</tt>) you get:</p> +<p>If you run <tt class="docutils literal"><span class="pre">ishelve.py</span></tt> with the option <tt class="docutils literal"><span class="pre">.h</span></tt> (or any abbreviation +of <tt class="docutils literal"><span class="pre">.help</span></tt>) you get:</p> <pre class="literal-block"> $ python ishelve.py .h Commands: .help, .showall, .clear, .delete @@ -1296,7 +1296,7 @@ following assumes knowledge of <a class="reference external" href="http://argpar <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">yield</tt>, +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>, 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 @@ -1307,16 +1307,16 @@ form - normal users expect options to be optional. You should avoid the use of required options whenever possible.</em> Notice that since <a class="reference external" href="http://argparse.googlecode.com">argparse</a> supports them, <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> can manage them too, but not directly.</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">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 +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 since you can use options with two choices instead, and in any case -the conversion from <tt class="docutils literal">{True, False}</tt> to any couple of values +the conversion from <tt class="docutils literal"><span class="pre">{True,</span> <span class="pre">False}</span></tt> to any couple of values can be trivially implemented with a ternary operator -(<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, +(<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, 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">nargs</tt>.</li> +to increase the learning curve by adding direct support for <tt class="docutils literal"><span class="pre">nargs</span></tt>.</li> <li><a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> does support subparsers, but you must read the <a class="reference external" href="in-writing">advanced usage document</a> to see how it works.</li> <li><a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> does not support actions directly. This also @@ -1327,14 +1327,14 @@ the <a class="reference external" href="in-writing">advanced usage document</a> <p><a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> can leverage directly on many <a class="reference external" href="http://argparse.googlecode.com">argparse</a> features.</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">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> +<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> directly.</p> <p>It is also possible to pass options to the underlying -<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 +<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 instance</p> <pre class="literal-block"> def main(...): @@ -1347,22 +1347,22 @@ mechanism does not look particularly elegant, but it works well enough. I assume that 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.</p> -<p>For instance, by setting the <tt class="docutils literal">description</tt> attribute, it is possible +<p>For instance, by setting the <tt class="docutils literal"><span class="pre">description</span></tt> attribute, it is possible to add a comment to the usage message (by default the docstring of the -<tt class="docutils literal">main</tt> function is used as description).</p> +<tt class="docutils literal"><span class="pre">main</span></tt> function is used as description).</p> <p>It is also possible to change the option prefix; for instance if your script must run under Windows and you want to use "/" as option prefix you can add the line:</p> <pre class="literal-block"> main.prefix_chars='/-' </pre> -<p>The first prefix char (<tt class="docutils literal">/</tt>) is used +<p>The first prefix char (<tt class="docutils literal"><span class="pre">/</span></tt>) is used as the default for the recognition of options and flags; -the second prefix char (<tt class="docutils literal">-</tt>) is kept to keep the <tt class="docutils literal"><span class="pre">-h/--help</span></tt> option +the second prefix char (<tt class="docutils literal"><span class="pre">-</span></tt>) is kept to keep the <tt class="docutils literal"><span class="pre">-h/--help</span></tt> option working: however you can disable it and reimplement it, if you like, -as seen in the <tt class="docutils literal">ishelve</tt> example.</p> +as seen in the <tt class="docutils literal"><span class="pre">ishelve</span></tt> example.</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">plac.parser_from</tt> utility function:</p> +invoking the <tt class="docutils literal"><span class="pre">plac.parser_from</span></tt> utility function:</p> <pre class="doctest-block"> >>> import plac >>> def main(arg): @@ -1371,17 +1371,17 @@ invoking the <tt class="docutils literal">plac.parser_from</tt> utility function >>> print(plac.parser_from(main)) #doctest: +ELLIPSIS ArgumentParser(prog=...) </pre> -<p>Internally <tt class="docutils literal">plac.call</tt> uses <tt class="docutils literal">plac.parser_from</tt> and adds the parser -to the main function as an attribute. When <tt class="docutils literal">plac.call(func)</tt> is +<p>Internally <tt class="docutils literal"><span class="pre">plac.call</span></tt> uses <tt class="docutils literal"><span class="pre">plac.parser_from</span></tt> and adds the parser +to the main function as an attribute. When <tt class="docutils literal"><span class="pre">plac.call(func)</span></tt> is invoked multiple time, the parser is re-used and not rebuilt from scratch again.</p> -<p>I use <tt class="docutils literal">plac.parser_from</tt> in the unit tests of the module, but regular +<p>I use <tt class="docutils literal"><span class="pre">plac.parser_from</span></tt> in the unit tests of the module, but regular users should not need to use it, unless they want to access <em>all</em> of the features of <a class="reference external" href="http://argparse.googlecode.com">argparse</a> directly without calling the main function.</p> <p>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">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 except the addition of the <tt class="docutils literal">.p</tt> +adding such options to the <tt class="docutils literal"><span class="pre">main</span></tt> function for you. For simplicity, +<a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> does not perform any magic except the addition of the <tt class="docutils literal"><span class="pre">.p</span></tt> attribute.</p> </div> <div class="section" id="plac-vs-the-rest-of-the-world"> @@ -1402,6 +1402,10 @@ no match for the capabilities of <a class="reference external" href="http://pypi line. For instance <a class="reference external" href="http://pypi.python.org/pypi/Clap/0.7">Clap</a> by Matthew Frazier which appeared on PyPI just the day before <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a>; <a class="reference external" href="http://pypi.python.org/pypi/Clap/0.7">Clap</a> is fine but it is certainly not easier than <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a>.</p> +<p><a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> can also be used as a replacement of the <a class="reference external" href="http://docs.python.org/library/cmd.html">cmd</a> module in the standard +library and as such it shares many features with the module <a class="reference external" href="http://packages.python.org/cmd2/">cmd2</a> by +Catherine Devlin. However, this is completely coincidental, since I became +aware of the <a class="reference external" href="http://packages.python.org/cmd2/">cmd2</a> module only after writing <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a>.</p> </div> <div class="section" id="the-future"> <h1><a class="toc-backref" href="#id13">The future</a></h1> @@ -1418,10 +1422,10 @@ quite advanced tool with a domain of applicability which far exceeds the realm of command-line arguments parsers.</p> <p>Version 0.5 of <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> doubled the code base and the documentation: it is based on the idea of using <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> to implement command-line interpreters, -i.e. something akin to the <tt class="docutils literal">cmd</tt> module in the standard library, only better. +i.e. something akin to the <tt class="docutils literal"><span class="pre">cmd</span></tt> module in the standard library, only better. The new features of <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> are described in the <a class="reference external" href="in-writing">advanced usage document</a> . -They are implemented in a separated module (<tt class="docutils literal">plac_ext.py</tt>), since -they require Python 2.5 to work, whereas <tt class="docutils literal">plac_core.py</tt> only requires +They are implemented in a separated module (<tt class="docutils literal"><span class="pre">plac_ext.py</span></tt>), since +they require Python 2.5 to work, whereas <tt class="docutils literal"><span class="pre">plac_core.py</span></tt> only requires Python 2.3.</p> </div> <div class="section" id="trivia-the-story-behind-the-name"> @@ -1441,8 +1445,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">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, +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, 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 <em>clap</em> (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 836a8d6..b8b99fe 100644 --- a/plac/doc/plac.pdf +++ b/plac/doc/plac.pdf @@ -528,10 +528,10 @@ endobj 0
0 ]
/Contents ()
- /Dest [ 162 0 R
+ /Dest [ 167 0 R
/XYZ
62.69291
- 645.0236
+ 603.0236
0 ]
/Rect [ 62.69291
332.5936
@@ -546,10 +546,10 @@ endobj 0
0 ]
/Contents ()
- /Dest [ 162 0 R
+ /Dest [ 167 0 R
/XYZ
62.69291
- 645.0236
+ 603.0236
0 ]
/Rect [ 521.4627
332.5936
@@ -564,10 +564,10 @@ endobj 0
0 ]
/Contents ()
- /Dest [ 162 0 R
+ /Dest [ 167 0 R
/XYZ
62.69291
- 438.0236
+ 396.0236
0 ]
/Rect [ 62.69291
314.5936
@@ -582,10 +582,10 @@ endobj 0
0 ]
/Contents ()
- /Dest [ 162 0 R
+ /Dest [ 167 0 R
/XYZ
62.69291
- 438.0236
+ 396.0236
0 ]
/Rect [ 521.4627
314.5936
@@ -804,12 +804,12 @@ endobj 45 0 R
46 0 R
47 0 R ]
- /Contents 181 0 R
+ /Contents 186 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 180 0 R
+ /Parent 185 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -928,12 +928,12 @@ endobj 53 0 R
54 0 R
55 0 R ]
- /Contents 182 0 R
+ /Contents 187 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 180 0 R
+ /Parent 185 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1043,12 +1043,12 @@ endobj 60 0 R
61 0 R
62 0 R ]
- /Contents 183 0 R
+ /Contents 188 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 180 0 R
+ /Parent 185 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1110,12 +1110,12 @@ endobj << /Annots [ 64 0 R
65 0 R
66 0 R ]
- /Contents 184 0 R
+ /Contents 189 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 180 0 R
+ /Parent 185 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1241,12 +1241,12 @@ endobj 72 0 R
73 0 R
74 0 R ]
- /Contents 185 0 R
+ /Contents 190 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 180 0 R
+ /Parent 185 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1276,12 +1276,12 @@ endobj 77 0 obj
% Page dictionary
<< /Annots [ 76 0 R ]
- /Contents 186 0 R
+ /Contents 191 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 180 0 R
+ /Parent 185 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1311,12 +1311,12 @@ endobj 79 0 obj
% Page dictionary
<< /Annots [ 78 0 R ]
- /Contents 187 0 R
+ /Contents 192 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 180 0 R
+ /Parent 185 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1346,12 +1346,12 @@ endobj 81 0 obj
% Page dictionary
<< /Annots [ 80 0 R ]
- /Contents 188 0 R
+ /Contents 193 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 180 0 R
+ /Parent 185 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1477,12 +1477,12 @@ endobj 86 0 R
87 0 R
88 0 R ]
- /Contents 189 0 R
+ /Contents 194 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 180 0 R
+ /Parent 185 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1496,12 +1496,12 @@ endobj % 'Page10': class PDFPage
90 0 obj
% Page dictionary
-<< /Contents 190 0 R
+<< /Contents 195 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 180 0 R
+ /Parent 185 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1563,12 +1563,12 @@ endobj << /Annots [ 91 0 R
92 0 R
93 0 R ]
- /Contents 191 0 R
+ /Contents 196 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 180 0 R
+ /Parent 185 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1614,12 +1614,12 @@ endobj % Page dictionary
<< /Annots [ 95 0 R
96 0 R ]
- /Contents 192 0 R
+ /Contents 197 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 180 0 R
+ /Parent 185 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1649,12 +1649,12 @@ endobj 99 0 obj
% Page dictionary
<< /Annots [ 98 0 R ]
- /Contents 193 0 R
+ /Contents 198 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 180 0 R
+ /Parent 185 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1700,12 +1700,12 @@ endobj % Page dictionary
<< /Annots [ 100 0 R
101 0 R ]
- /Contents 194 0 R
+ /Contents 199 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 180 0 R
+ /Parent 185 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1930,7 +1930,7 @@ endobj 117 0 obj
<< /A << /S /URI
/Type /Action
- /URI (file:///home/micheles/Dropbox/md/gcodedev/plac/in-writing) >>
+ /URI (file:///home/msimionato/Dropbox/gcode/plac/in-writing) >>
/Border [ 0
0
0 ]
@@ -1975,7 +1975,7 @@ endobj 120 0 obj
<< /A << /S /URI
/Type /Action
- /URI (file:///home/micheles/Dropbox/md/gcodedev/plac/in-writing) >>
+ /URI (file:///home/msimionato/Dropbox/gcode/plac/in-writing) >>
/Border [ 0
0
0 ]
@@ -1990,7 +1990,7 @@ endobj 121 0 obj
<< /A << /S /URI
/Type /Action
- /URI (file:///home/micheles/Dropbox/md/gcodedev/plac/in-writing) >>
+ /URI (file:///home/msimionato/Dropbox/gcode/plac/in-writing) >>
/Border [ 0
0
0 ]
@@ -2055,12 +2055,12 @@ endobj 121 0 R
122 0 R
123 0 R ]
- /Contents 195 0 R
+ /Contents 200 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 180 0 R
+ /Parent 185 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -2202,12 +2202,12 @@ endobj 130 0 R
131 0 R
132 0 R ]
- /Contents 196 0 R
+ /Contents 201 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 180 0 R
+ /Parent 185 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -2346,10 +2346,10 @@ endobj /Border [ 0
0
0 ]
- /Rect [ 156.6051
- 609.5936
- 177.8606
- 621.5936 ]
+ /Rect [ 62.69291
+ 642.5936
+ 84.4354
+ 654.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
@@ -2357,19 +2357,94 @@ endobj 143 0 obj
<< /A << /S /URI
/Type /Action
+ /URI (http://docs.python.org/library/cmd.html) >>
+ /Border [ 0
+ 0
+ 0 ]
+ /Rect [ 275.6978
+ 642.5936
+ 297.9903
+ 654.5936 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER122': class PDFDictionary
+144 0 obj
+<< /A << /S /URI
+ /Type /Action
+ /URI (http://packages.python.org/cmd2/) >>
+ /Border [ 0
+ 0
+ 0 ]
+ /Rect [ 203.5285
+ 630.5936
+ 231.1357
+ 642.5936 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER123': class PDFDictionary
+145 0 obj
+<< /A << /S /URI
+ /Type /Action
+ /URI (http://packages.python.org/cmd2/) >>
+ /Border [ 0
+ 0
+ 0 ]
+ /Rect [ 164.4129
+ 618.5936
+ 191.6429
+ 630.5936 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER124': class PDFDictionary
+146 0 obj
+<< /A << /S /URI
+ /Type /Action
+ /URI (http://pypi.python.org/pypi/plac) >>
+ /Border [ 0
+ 0
+ 0 ]
+ /Rect [ 302.7929
+ 618.5936
+ 321.1329
+ 630.5936 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER125': class PDFDictionary
+147 0 obj
+<< /A << /S /URI
+ /Type /Action
+ /URI (http://pypi.python.org/pypi/plac) >>
+ /Border [ 0
+ 0
+ 0 ]
+ /Rect [ 156.6051
+ 567.5936
+ 177.8606
+ 579.5936 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER126': class PDFDictionary
+148 0 obj
+<< /A << /S /URI
+ /Type /Action
/URI (http://argparse.googlecode.com) >>
/Border [ 0
0
0 ]
/Rect [ 186.6535
- 585.5936
+ 543.5936
226.1135
- 597.5936 ]
+ 555.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER122': class PDFDictionary
-144 0 obj
+% 'Annot.NUMBER127': class PDFDictionary
+149 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
@@ -2377,14 +2452,14 @@ endobj 0
0 ]
/Rect [ 493.1227
- 585.5936
+ 543.5936
532.4646
- 597.5936 ]
+ 555.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER123': class PDFDictionary
-145 0 obj
+% 'Annot.NUMBER128': class PDFDictionary
+150 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -2392,14 +2467,14 @@ endobj 0
0 ]
/Rect [ 72.7804
- 573.5936
+ 531.5936
96.20788
- 585.5936 ]
+ 543.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER124': class PDFDictionary
-146 0 obj
+% 'Annot.NUMBER129': class PDFDictionary
+151 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -2407,14 +2482,14 @@ endobj 0
0 ]
/Rect [ 149.2229
- 543.5936
+ 501.5936
171.2704
- 555.5936 ]
+ 513.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER125': class PDFDictionary
-147 0 obj
+% 'Annot.NUMBER130': class PDFDictionary
+152 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -2422,14 +2497,14 @@ endobj 0
0 ]
/Rect [ 128.0309
- 501.5936
+ 459.5936
149.4369
- 513.5936 ]
+ 471.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER126': class PDFDictionary
-148 0 obj
+% 'Annot.NUMBER131': class PDFDictionary
+153 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -2437,14 +2512,14 @@ endobj 0
0 ]
/Rect [ 502.8367
- 501.5936
+ 459.5936
524.2427
- 513.5936 ]
+ 471.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER127': class PDFDictionary
-149 0 obj
+% 'Annot.NUMBER132': class PDFDictionary
+154 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -2452,29 +2527,29 @@ endobj 0
0 ]
/Rect [ 187.4797
- 477.5936
+ 435.5936
209.0991
- 489.5936 ]
+ 447.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER128': class PDFDictionary
-150 0 obj
+% 'Annot.NUMBER133': class PDFDictionary
+155 0 obj
<< /A << /S /URI
/Type /Action
- /URI (file:///home/micheles/Dropbox/md/gcodedev/plac/in-writing) >>
+ /URI (file:///home/msimionato/Dropbox/gcode/plac/in-writing) >>
/Border [ 0
0
0 ]
/Rect [ 301.6965
- 477.5936
+ 435.5936
426.0446
- 489.5936 ]
+ 447.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER129': class PDFDictionary
-151 0 obj
+% 'Annot.NUMBER134': class PDFDictionary
+156 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -2482,14 +2557,14 @@ endobj 0
0 ]
/Rect [ 83.64556
- 402.5936
+ 360.5936
105.7082
- 414.5936 ]
+ 372.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER130': class PDFDictionary
-152 0 obj
+% 'Annot.NUMBER135': class PDFDictionary
+157 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://code.activestate.com/recipes/278844-parsing-the-command-line/) >>
@@ -2497,14 +2572,14 @@ endobj 0
0 ]
/Rect [ 446.6
- 402.5936
+ 360.5936
502.5727
- 414.5936 ]
+ 372.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER131': class PDFDictionary
-153 0 obj
+% 'Annot.NUMBER136': class PDFDictionary
+158 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -2512,14 +2587,14 @@ endobj 0
0 ]
/Rect [ 275.6828
- 390.5936
+ 348.5936
297.3688
- 402.5936 ]
+ 360.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER132': class PDFDictionary
-154 0 obj
+% 'Annot.NUMBER137': class PDFDictionary
+159 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://docs.python.org/library/optparse.html?highlight=optionparser#optparse.OptionParser) >>
@@ -2527,14 +2602,14 @@ endobj 0
0 ]
/Rect [ 77.19665
- 378.5936
+ 336.5936
139.4904
- 390.5936 ]
+ 348.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER133': class PDFDictionary
-155 0 obj
+% 'Annot.NUMBER138': class PDFDictionary
+160 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
@@ -2542,14 +2617,14 @@ endobj 0
0 ]
/Rect [ 96.54131
- 366.5936
+ 324.5936
139.0255
- 378.5936 ]
+ 336.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER134': class PDFDictionary
-156 0 obj
+% 'Annot.NUMBER139': class PDFDictionary
+161 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
@@ -2557,14 +2632,14 @@ endobj 0
0 ]
/Rect [ 203.5016
- 333.5936
+ 291.5936
245.8453
- 345.5936 ]
+ 303.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER135': class PDFDictionary
-157 0 obj
+% 'Annot.NUMBER140': class PDFDictionary
+162 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com/svn/tags/r11/doc/ArgumentParser.html) >>
@@ -2572,14 +2647,14 @@ endobj 0
0 ]
/Rect [ 62.69291
- 258.5936
+ 216.5936
138.7898
- 270.5936 ]
+ 228.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER136': class PDFDictionary
-158 0 obj
+% 'Annot.NUMBER141': class PDFDictionary
+163 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
@@ -2587,14 +2662,14 @@ endobj 0
0 ]
/Rect [ 114.6649
- 246.5936
+ 204.5936
154.1249
- 258.5936 ]
+ 216.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER137': class PDFDictionary
-159 0 obj
+% 'Annot.NUMBER142': class PDFDictionary
+164 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
@@ -2602,14 +2677,14 @@ endobj 0
0 ]
/Rect [ 191.6329
- 234.5936
+ 192.5936
233.8729
- 246.5936 ]
+ 204.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER138': class PDFDictionary
-160 0 obj
+% 'Annot.NUMBER143': class PDFDictionary
+165 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/Clap/0.7) >>
@@ -2617,14 +2692,14 @@ endobj 0
0 ]
/Rect [ 263.3429
- 204.5936
+ 162.5936
286.6829
- 216.5936 ]
+ 174.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER139': class PDFDictionary
-161 0 obj
+% 'Annot.NUMBER144': class PDFDictionary
+166 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -2632,14 +2707,14 @@ endobj 0
0 ]
/Rect [ 258.5629
- 156.5936
+ 114.5936
276.9029
- 168.5936 ]
+ 126.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
% 'Page17': class PDFPage
-162 0 obj
+167 0 obj
% Page dictionary
<< /Annots [ 134 0 R
135 0 R
@@ -2668,13 +2743,18 @@ endobj 158 0 R
159 0 R
160 0 R
- 161 0 R ]
- /Contents 197 0 R
+ 161 0 R
+ 162 0 R
+ 163 0 R
+ 164 0 R
+ 165 0 R
+ 166 0 R ]
+ /Contents 202 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 180 0 R
+ /Parent 185 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -2685,199 +2765,199 @@ endobj /Trans << >>
/Type /Page >>
endobj
-% 'R163': class PDFCatalog
-163 0 obj
+% 'R168': class PDFCatalog
+168 0 obj
% Document Root
-<< /Outlines 165 0 R
- /PageLabels 198 0 R
+<< /Outlines 170 0 R
+ /PageLabels 203 0 R
/PageMode /UseNone
- /Pages 180 0 R
+ /Pages 185 0 R
/Type /Catalog >>
endobj
-% 'R164': class PDFInfo
-164 0 obj
+% 'R169': class PDFInfo
+169 0 obj
<< /Author (Michele Simionato)
- /CreationDate (D:20100703163715-01'00')
+ /CreationDate (D:20100712091726-01'00')
/Keywords ()
/Producer (ReportLab http://www.reportlab.com)
/Subject (\(unspecified\))
/Title (Plac: Parsing the Command Line the Easy Way) >>
endobj
-% 'R165': class PDFOutlines
-165 0 obj
+% 'R170': class PDFOutlines
+170 0 obj
<< /Count 14
- /First 166 0 R
- /Last 179 0 R
+ /First 171 0 R
+ /Last 184 0 R
/Type /Outlines >>
endobj
% 'Outline.0': class OutlineEntryObject
-166 0 obj
+171 0 obj
<< /Dest [ 48 0 R
/XYZ
62.69291
296.0236
0 ]
- /Next 167 0 R
- /Parent 165 0 R
+ /Next 172 0 R
+ /Parent 170 0 R
/Title (The importance of scaling down) >>
endobj
% 'Outline.1': class OutlineEntryObject
-167 0 obj
+172 0 obj
<< /Dest [ 56 0 R
/XYZ
62.69291
615.0236
0 ]
- /Next 168 0 R
- /Parent 165 0 R
- /Prev 166 0 R
+ /Next 173 0 R
+ /Parent 170 0 R
+ /Prev 171 0 R
/Title (Scripts with required arguments) >>
endobj
% 'Outline.2': class OutlineEntryObject
-168 0 obj
+173 0 obj
<< /Dest [ 63 0 R
/XYZ
62.69291
274.2236
0 ]
- /Next 169 0 R
- /Parent 165 0 R
- /Prev 167 0 R
+ /Next 174 0 R
+ /Parent 170 0 R
+ /Prev 172 0 R
/Title (Scripts with default arguments) >>
endobj
% 'Outline.3': class OutlineEntryObject
-169 0 obj
+174 0 obj
<< /Dest [ 75 0 R
/XYZ
62.69291
229.4236
0 ]
- /Next 170 0 R
- /Parent 165 0 R
- /Prev 168 0 R
+ /Next 175 0 R
+ /Parent 170 0 R
+ /Prev 173 0 R
/Title (Scripts with options \(and smart options\)) >>
endobj
% 'Outline.4': class OutlineEntryObject
-170 0 obj
+175 0 obj
<< /Dest [ 79 0 R
/XYZ
62.69291
231.0236
0 ]
- /Next 171 0 R
- /Parent 165 0 R
- /Prev 169 0 R
+ /Next 176 0 R
+ /Parent 170 0 R
+ /Prev 174 0 R
/Title (Scripts with flags) >>
endobj
% 'Outline.5': class OutlineEntryObject
-171 0 obj
+176 0 obj
<< /Dest [ 81 0 R
/XYZ
62.69291
377.4236
0 ]
- /Next 172 0 R
- /Parent 165 0 R
- /Prev 170 0 R
+ /Next 177 0 R
+ /Parent 170 0 R
+ /Prev 175 0 R
/Title (plac for Python 2.X users) >>
endobj
% 'Outline.6': class OutlineEntryObject
-172 0 obj
+177 0 obj
<< /Dest [ 89 0 R
/XYZ
62.69291
647.8236
0 ]
- /Next 173 0 R
- /Parent 165 0 R
- /Prev 171 0 R
+ /Next 178 0 R
+ /Parent 170 0 R
+ /Prev 176 0 R
/Title (More features) >>
endobj
% 'Outline.7': class OutlineEntryObject
-173 0 obj
+178 0 obj
<< /Dest [ 94 0 R
/XYZ
62.69291
683.8236
0 ]
- /Next 174 0 R
- /Parent 165 0 R
- /Prev 172 0 R
+ /Next 179 0 R
+ /Parent 170 0 R
+ /Prev 177 0 R
/Title (A realistic example) >>
endobj
% 'Outline.8': class OutlineEntryObject
-174 0 obj
+179 0 obj
<< /Dest [ 97 0 R
/XYZ
62.69291
623.8236
0 ]
- /Next 175 0 R
- /Parent 165 0 R
- /Prev 173 0 R
+ /Next 180 0 R
+ /Parent 170 0 R
+ /Prev 178 0 R
/Title (Keyword arguments) >>
endobj
% 'Outline.9': class OutlineEntryObject
-175 0 obj
+180 0 obj
<< /Dest [ 99 0 R
/XYZ
62.69291
594.6236
0 ]
- /Next 176 0 R
- /Parent 165 0 R
- /Prev 174 0 R
+ /Next 181 0 R
+ /Parent 170 0 R
+ /Prev 179 0 R
/Title (Final example: a shelve interface) >>
endobj
% 'Outline.10': class OutlineEntryObject
-176 0 obj
+181 0 obj
<< /Dest [ 124 0 R
/XYZ
62.69291
511.8236
0 ]
- /Next 177 0 R
- /Parent 165 0 R
- /Prev 175 0 R
+ /Next 182 0 R
+ /Parent 170 0 R
+ /Prev 180 0 R
/Title (plac vs argparse) >>
endobj
% 'Outline.11': class OutlineEntryObject
-177 0 obj
+182 0 obj
<< /Dest [ 133 0 R
/XYZ
62.69291
161.4236
0 ]
- /Next 178 0 R
- /Parent 165 0 R
- /Prev 176 0 R
+ /Next 183 0 R
+ /Parent 170 0 R
+ /Prev 181 0 R
/Title (plac vs the rest of the world) >>
endobj
% 'Outline.12': class OutlineEntryObject
-178 0 obj
-<< /Dest [ 162 0 R
+183 0 obj
+<< /Dest [ 167 0 R
/XYZ
62.69291
- 645.0236
+ 603.0236
0 ]
- /Next 179 0 R
- /Parent 165 0 R
- /Prev 177 0 R
+ /Next 184 0 R
+ /Parent 170 0 R
+ /Prev 182 0 R
/Title (The future) >>
endobj
% 'Outline.13': class OutlineEntryObject
-179 0 obj
-<< /Dest [ 162 0 R
+184 0 obj
+<< /Dest [ 167 0 R
/XYZ
62.69291
- 438.0236
+ 396.0236
0 ]
- /Parent 165 0 R
- /Prev 178 0 R
+ /Parent 170 0 R
+ /Prev 183 0 R
/Title (Trivia: the story behind the name) >>
endobj
-% 'R180': class PDFPages
-180 0 obj
+% 'R185': class PDFPages
+185 0 obj
% page tree
<< /Count 17
/Kids [ 48 0 R
@@ -2896,11 +2976,11 @@ endobj 102 0 R
124 0 R
133 0 R
- 162 0 R ]
+ 167 0 R ]
/Type /Pages >>
endobj
-% 'R181': class PDFStream
-181 0 obj
+% 'R186': class PDFStream
+186 0 obj
% page stream
<< /Length 9341 >>
stream
@@ -3326,8 +3406,8 @@ Q endstream
endobj
-% 'R182': class PDFStream
-182 0 obj
+% 'R187': class PDFStream
+187 0 obj
% page stream
<< /Length 4921 >>
stream
@@ -3415,8 +3495,8 @@ Q endstream
endobj
-% 'R183': class PDFStream
-183 0 obj
+% 'R188': class PDFStream
+188 0 obj
% page stream
<< /Length 4194 >>
stream
@@ -3574,8 +3654,8 @@ Q endstream
endobj
-% 'R184': class PDFStream
-184 0 obj
+% 'R189': class PDFStream
+189 0 obj
% page stream
<< /Length 3999 >>
stream
@@ -3721,8 +3801,8 @@ Q endstream
endobj
-% 'R185': class PDFStream
-185 0 obj
+% 'R190': class PDFStream
+190 0 obj
% page stream
<< /Length 4674 >>
stream
@@ -3843,8 +3923,8 @@ Q endstream
endobj
-% 'R186': class PDFStream
-186 0 obj
+% 'R191': class PDFStream
+191 0 obj
% page stream
<< /Length 4134 >>
stream
@@ -3984,8 +4064,8 @@ Q endstream
endobj
-% 'R187': class PDFStream
-187 0 obj
+% 'R192': class PDFStream
+192 0 obj
% page stream
<< /Length 4491 >>
stream
@@ -4171,8 +4251,8 @@ Q endstream
endobj
-% 'R188': class PDFStream
-188 0 obj
+% 'R193': class PDFStream
+193 0 obj
% page stream
<< /Length 5065 >>
stream
@@ -4336,8 +4416,8 @@ Q endstream
endobj
-% 'R189': class PDFStream
-189 0 obj
+% 'R194': class PDFStream
+194 0 obj
% page stream
<< /Length 5334 >>
stream
@@ -4471,8 +4551,8 @@ Q endstream
endobj
-% 'R190': class PDFStream
-190 0 obj
+% 'R195': class PDFStream
+195 0 obj
% page stream
<< /Length 4511 >>
stream
@@ -4634,8 +4714,8 @@ Q endstream
endobj
-% 'R191': class PDFStream
-191 0 obj
+% 'R196': class PDFStream
+196 0 obj
% page stream
<< /Length 4236 >>
stream
@@ -4745,8 +4825,8 @@ Q endstream
endobj
-% 'R192': class PDFStream
-192 0 obj
+% 'R197': class PDFStream
+197 0 obj
% page stream
<< /Length 3423 >>
stream
@@ -4879,10 +4959,10 @@ Q endstream
endobj
-% 'R193': class PDFStream
-193 0 obj
+% 'R198': class PDFStream
+198 0 obj
% page stream
-<< /Length 4047 >>
+<< /Length 4089 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
@@ -4966,7 +5046,7 @@ q n -6 -6 492 432 re B*
Q
q
-BT 1 0 0 1 0 413.71 Tm 12 TL /F4 10 Tf 0 0 0 rg (# ishelve.py) Tj T* (import os, shelve, plac) Tj T* T* (DEFAULT_SHELVE = os.path.expanduser\('~/conf.shelve'\)) Tj T* T* (@plac.annotations\() Tj T* ( help=\('show help', 'flag'\),) Tj T* ( showall=\('show all parameters in the shelve', 'flag'\),) Tj T* ( clear=\('clear the shelve', 'flag'\),) Tj T* ( delete=\('delete an element', 'option'\),) Tj T* ( filename=\('filename of the shelve', 'option'\),) Tj T* ( params='names of the parameters in the shelve',) Tj T* ( setters='setters param=value'\)) Tj T* (def main\(help, showall, clear, delete, filename=DEFAULT_SHELVE,) Tj T* ( *params, **setters\):) Tj T* ( "A simple interface to a shelve") Tj T* ( sh = shelve.open\(filename\)) Tj T* ( try:) Tj T* ( if not any\([help, showall, clear, delete, params, setters]\):) Tj T* ( yield 'no arguments passed, use .help to see the available commands') Tj T* ( elif help: # custom help) Tj T* ( yield 'Commands: .help, .showall, .clear, .delete') Tj T* ( yield ') Tj (<) Tj (param) Tj (>) Tj ( ...') Tj T* ( yield ') Tj (<) Tj (param=value) Tj (>) Tj ( ...') Tj T* ( elif showall:) Tj T* ( for param, name in sh.items\(\):) Tj T* ( yield '%s=%s' % \(param, name\)) Tj T* ( elif clear:) Tj T* ( sh.clear\(\)) Tj T* ( yield 'cleared the shelve') Tj T* ( elif delete:) Tj T* ( try:) Tj T* ( del sh[delete]) Tj T* ( except KeyError:) Tj T* ( yield '%s: not found' % delete) Tj T* ET
+BT 1 0 0 1 0 413.71 Tm 12 TL /F4 10 Tf 0 0 0 rg (# ishelve.py) Tj T* (import os, shelve, plac) Tj T* T* (DEFAULT_SHELVE = os.path.expanduser\('~/conf.shelve'\)) Tj T* T* (@plac.annotations\() Tj T* ( help=\('show help', 'flag'\),) Tj T* ( showall=\('show all parameters in the shelve', 'flag'\),) Tj T* ( clear=\('clear the shelve', 'flag'\),) Tj T* ( delete=\('delete an element', 'option'\),) Tj T* ( filename=\('filename of the shelve', 'option'\),) Tj T* ( params='names of the parameters in the shelve',) Tj T* ( setters='setters param=value'\)) Tj T* (def main\(help, showall, clear, delete, filename=DEFAULT_SHELVE,) Tj T* ( *params, **setters\):) Tj T* ( "A simple interface to a shelve. Use .help to see the available commands.") Tj T* ( sh = shelve.open\(filename\)) Tj T* ( try:) Tj T* ( if not any\([help, showall, clear, delete, params, setters]\):) Tj T* ( yield 'no arguments passed, use .help to see the available commands') Tj T* ( elif help: # custom help) Tj T* ( yield 'Commands: .help, .showall, .clear, .delete') Tj T* ( yield ') Tj (<) Tj (param) Tj (>) Tj ( ...') Tj T* ( yield ') Tj (<) Tj (param=value) Tj (>) Tj ( ...') Tj T* ( elif showall:) Tj T* ( for param, name in sh.items\(\):) Tj T* ( yield '%s=%s' % \(param, name\)) Tj T* ( elif clear:) Tj T* ( sh.clear\(\)) Tj T* ( yield 'cleared the shelve') Tj T* ( elif delete:) Tj T* ( try:) Tj T* ( del sh[delete]) Tj T* ( except KeyError:) Tj T* ( yield '%s: not found' % delete) Tj T* ET
Q
Q
Q
@@ -4983,8 +5063,8 @@ Q endstream
endobj
-% 'R194': class PDFStream
-194 0 obj
+% 'R199': class PDFStream
+199 0 obj
% page stream
<< /Length 6795 >>
stream
@@ -5302,8 +5382,8 @@ Q endstream
endobj
-% 'R195': class PDFStream
-195 0 obj
+% 'R200': class PDFStream
+200 0 obj
% page stream
<< /Length 7204 >>
stream
@@ -5520,8 +5600,8 @@ Q endstream
endobj
-% 'R196': class PDFStream
-196 0 obj
+% 'R201': class PDFStream
+201 0 obj
% page stream
<< /Length 6860 >>
stream
@@ -5678,10 +5758,10 @@ Q endstream
endobj
-% 'R197': class PDFStream
-197 0 obj
+% 'R202': class PDFStream
+202 0 obj
% page stream
-<< /Length 7645 >>
+<< /Length 8225 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
@@ -5749,49 +5829,55 @@ BT 1 0 0 1 0 28.82 Tm 1.551163 Tw 12 TL /F1 10 Tf 0 0 0 rg (Of course, there are Q
Q
q
-1 0 0 1 62.69291 624.0236 cm
+1 0 0 1 62.69291 615.0236 cm
+q
+BT 1 0 0 1 0 28.82 Tm .622488 Tw 12 TL /F1 10 Tf 0 0 .501961 rg (plac ) Tj 0 0 0 rg (can also be used as a replacement of the ) Tj 0 0 .501961 rg (cmd ) Tj 0 0 0 rg (module in the standard library and as such it shares) Tj T* 0 Tw .377126 Tw (many features with the module ) Tj 0 0 .501961 rg (cmd2 ) Tj 0 0 0 rg (by Catherine Devlin. However, this is completely coincidental, since) Tj T* 0 Tw (I became aware of the ) Tj 0 0 .501961 rg (cmd2 ) Tj 0 0 0 rg (module only after writing ) Tj 0 0 .501961 rg (plac) Tj 0 0 0 rg (.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 582.0236 cm
q
BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (The future) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 558.0236 cm
+1 0 0 1 62.69291 516.0236 cm
q
BT 1 0 0 1 0 52.82 Tm .135542 Tw 12 TL /F1 10 Tf 0 0 0 rg (Currently the core of ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (is around 200 lines of code, not counting blanks, comments and docstrings. I do) Tj T* 0 Tw .968626 Tw (not plan to extend the core much in the future. The idea is to keep the module short: it is and it should) Tj T* 0 Tw .11811 Tw (remain a little wrapper over ) Tj 0 0 .501961 rg (argparse) Tj 0 0 0 rg (. Actually I have thought about contributing the core back to ) Tj 0 0 .501961 rg (argparse) Tj T* 0 Tw 2.307485 Tw 0 0 0 rg (if ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (becomes successfull and gains a reasonable number of users. For the moment it should be) Tj T* 0 Tw (considered in alpha status.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 516.0236 cm
+1 0 0 1 62.69291 474.0236 cm
q
BT 1 0 0 1 0 28.82 Tm .927488 Tw 12 TL /F1 10 Tf 0 0 0 rg (Notice that even if ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (has been designed to be simple to use for simple stuff, its power should not be) Tj T* 0 Tw 1.02186 Tw (underestimated; it is actually a quite advanced tool with a domain of applicability which far exceeds the) Tj T* 0 Tw (realm of command-line arguments parsers.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 450.0236 cm
+1 0 0 1 62.69291 408.0236 cm
q
BT 1 0 0 1 0 52.82 Tm .285988 Tw 12 TL /F1 10 Tf 0 0 0 rg (Version 0.5 of ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (doubled the code base and the documentation: it is based on the idea of using ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (to) Tj T* 0 Tw .408555 Tw (implement command-line interpreters, i.e. something akin to the ) Tj /F4 10 Tf (cmd ) Tj /F1 10 Tf (module in the standard library, only) Tj T* 0 Tw .49936 Tw (better. The new features of ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (are described in the ) Tj 0 0 .501961 rg (advanced usage document ) Tj 0 0 0 rg (. They are implemented) Tj T* 0 Tw .313828 Tw (in a separated module \() Tj /F4 10 Tf (plac_ext.py) Tj /F1 10 Tf (\), since they require Python 2.5 to work, whereas ) Tj /F4 10 Tf (plac_core.py) Tj T* 0 Tw /F1 10 Tf (only requires Python 2.3.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 417.0236 cm
+1 0 0 1 62.69291 375.0236 cm
q
BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Trivia: the story behind the name) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 351.0236 cm
+1 0 0 1 62.69291 309.0236 cm
q
BT 1 0 0 1 0 52.82 Tm .942651 Tw 12 TL /F1 10 Tf 0 0 0 rg (The ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (project started very humble: I just wanted to make easy_installable my old ) Tj 0 0 .501961 rg (optionparse ) Tj 0 0 0 rg (recipe,) Tj T* 0 Tw .565988 Tw (and to publish it on PyPI. The original name of ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (was optionparser and the idea behind it was to build) Tj T* 0 Tw .603735 Tw (an ) Tj 0 0 .501961 rg (OptionParser ) Tj 0 0 0 rg (object from the docstring of the module. However, before doing that, I decided to check) Tj T* 0 Tw .244198 Tw (out the ) Tj 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (module, since I knew it was going into Python 2.7 and Python 2.7 was coming out. Soon) Tj T* 0 Tw (enough I realized two things:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 345.0236 cm
+1 0 0 1 62.69291 303.0236 cm
Q
q
-1 0 0 1 62.69291 345.0236 cm
+1 0 0 1 62.69291 303.0236 cm
Q
q
-1 0 0 1 62.69291 315.0236 cm
+1 0 0 1 62.69291 273.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -5811,13 +5897,13 @@ q Q
Q
q
-1 0 0 1 62.69291 315.0236 cm
+1 0 0 1 62.69291 273.0236 cm
Q
q
-1 0 0 1 62.69291 315.0236 cm
+1 0 0 1 62.69291 273.0236 cm
Q
q
-1 0 0 1 62.69291 285.0236 cm
+1 0 0 1 62.69291 243.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -5838,32 +5924,32 @@ q Q
Q
q
-1 0 0 1 62.69291 285.0236 cm
+1 0 0 1 62.69291 243.0236 cm
Q
q
-1 0 0 1 62.69291 285.0236 cm
+1 0 0 1 62.69291 243.0236 cm
Q
q
-1 0 0 1 62.69291 231.0236 cm
+1 0 0 1 62.69291 189.0236 cm
q
BT 1 0 0 1 0 40.82 Tm .600574 Tw 12 TL /F1 10 Tf 0 0 0 rg (Putting together these two observations with the original idea of inferring the parser I decided to build an) Tj T* 0 Tw .516905 Tw 0 0 .501961 rg (ArgumentParser ) Tj 0 0 0 rg (object from function annotations. The ) Tj /F4 10 Tf (optionparser ) Tj /F1 10 Tf (name was ruled out, since I was) Tj T* 0 Tw 2.085984 Tw (now using ) Tj 0 0 .501961 rg (argparse) Tj 0 0 0 rg (; a name like ) Tj /F4 10 Tf (argparse_plus ) Tj /F1 10 Tf (was also ruled out, since the typical usage was) Tj T* 0 Tw (completely different from the ) Tj 0 0 .501961 rg (argparse ) Tj 0 0 0 rg (usage.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 201.0236 cm
+1 0 0 1 62.69291 159.0236 cm
q
BT 1 0 0 1 0 16.82 Tm 1.093876 Tw 12 TL /F1 10 Tf 0 0 0 rg (I made a research on PyPI and the name ) Tj /F5 10 Tf (clap ) Tj /F1 10 Tf (\(Command Line Arguments Parser\) was not taken, so I) Tj T* 0 Tw (renamed everything to clap. After two days a ) Tj 0 0 .501961 rg (Clap ) Tj 0 0 0 rg (module appeared on PyPI <) Tj (expletives deleted) Tj (>) Tj (!) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 171.0236 cm
+1 0 0 1 62.69291 129.0236 cm
q
0 0 0 rg
BT 1 0 0 1 0 16.82 Tm /F1 10 Tf 12 TL .877209 Tw (Having little imagination, I decided to rename everything again to plac, an anagram of clap: since it is a) Tj T* 0 Tw (non-existing English name, I hope nobody will steal it from me!) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 153.0236 cm
+1 0 0 1 62.69291 111.0236 cm
q
BT 1 0 0 1 0 4.82 Tm 12 TL /F1 10 Tf 0 0 0 rg (That's all, I hope you will enjoy working with ) Tj 0 0 .501961 rg (plac) Tj 0 0 0 rg (!) Tj T* ET
Q
@@ -5879,148 +5965,148 @@ Q endstream
endobj
-% 'R198': class PDFPageLabels
-198 0 obj
+% 'R203': class PDFPageLabels
+203 0 obj
% Document Root
<< /Nums [ 0
- 199 0 R
+ 204 0 R
1
- 200 0 R
+ 205 0 R
2
- 201 0 R
+ 206 0 R
3
- 202 0 R
+ 207 0 R
4
- 203 0 R
+ 208 0 R
5
- 204 0 R
+ 209 0 R
6
- 205 0 R
+ 210 0 R
7
- 206 0 R
+ 211 0 R
8
- 207 0 R
+ 212 0 R
9
- 208 0 R
+ 213 0 R
10
- 209 0 R
+ 214 0 R
11
- 210 0 R
+ 215 0 R
12
- 211 0 R
+ 216 0 R
13
- 212 0 R
+ 217 0 R
14
- 213 0 R
+ 218 0 R
15
- 214 0 R
+ 219 0 R
16
- 215 0 R ] >>
+ 220 0 R ] >>
endobj
-% 'R199': class PDFPageLabel
-199 0 obj
+% 'R204': class PDFPageLabel
+204 0 obj
% None
<< /S /D
/St 1 >>
endobj
-% 'R200': class PDFPageLabel
-200 0 obj
+% 'R205': class PDFPageLabel
+205 0 obj
% None
<< /S /D
/St 2 >>
endobj
-% 'R201': class PDFPageLabel
-201 0 obj
+% 'R206': class PDFPageLabel
+206 0 obj
% None
<< /S /D
/St 3 >>
endobj
-% 'R202': class PDFPageLabel
-202 0 obj
+% 'R207': class PDFPageLabel
+207 0 obj
% None
<< /S /D
/St 4 >>
endobj
-% 'R203': class PDFPageLabel
-203 0 obj
+% 'R208': class PDFPageLabel
+208 0 obj
% None
<< /S /D
/St 5 >>
endobj
-% 'R204': class PDFPageLabel
-204 0 obj
+% 'R209': class PDFPageLabel
+209 0 obj
% None
<< /S /D
/St 6 >>
endobj
-% 'R205': class PDFPageLabel
-205 0 obj
+% 'R210': class PDFPageLabel
+210 0 obj
% None
<< /S /D
/St 7 >>
endobj
-% 'R206': class PDFPageLabel
-206 0 obj
+% 'R211': class PDFPageLabel
+211 0 obj
% None
<< /S /D
/St 8 >>
endobj
-% 'R207': class PDFPageLabel
-207 0 obj
+% 'R212': class PDFPageLabel
+212 0 obj
% None
<< /S /D
/St 9 >>
endobj
-% 'R208': class PDFPageLabel
-208 0 obj
+% 'R213': class PDFPageLabel
+213 0 obj
% None
<< /S /D
/St 10 >>
endobj
-% 'R209': class PDFPageLabel
-209 0 obj
+% 'R214': class PDFPageLabel
+214 0 obj
% None
<< /S /D
/St 11 >>
endobj
-% 'R210': class PDFPageLabel
-210 0 obj
+% 'R215': class PDFPageLabel
+215 0 obj
% None
<< /S /D
/St 12 >>
endobj
-% 'R211': class PDFPageLabel
-211 0 obj
+% 'R216': class PDFPageLabel
+216 0 obj
% None
<< /S /D
/St 13 >>
endobj
-% 'R212': class PDFPageLabel
-212 0 obj
+% 'R217': class PDFPageLabel
+217 0 obj
% None
<< /S /D
/St 14 >>
endobj
-% 'R213': class PDFPageLabel
-213 0 obj
+% 'R218': class PDFPageLabel
+218 0 obj
% None
<< /S /D
/St 15 >>
endobj
-% 'R214': class PDFPageLabel
-214 0 obj
+% 'R219': class PDFPageLabel
+219 0 obj
% None
<< /S /D
/St 16 >>
endobj
-% 'R215': class PDFPageLabel
-215 0 obj
+% 'R220': class PDFPageLabel
+220 0 obj
% None
<< /S /D
/St 17 >>
endobj
xref
-0 216
+0 221
0000000000 65535 f
0000000113 00000 n
0000000258 00000 n
@@ -6139,112 +6225,117 @@ xref 0000029570 00000 n
0000029822 00000 n
0000030075 00000 n
-0000030353 00000 n
-0000030606 00000 n
-0000030860 00000 n
-0000031138 00000 n
-0000031417 00000 n
-0000031671 00000 n
-0000031908 00000 n
-0000032429 00000 n
-0000032747 00000 n
-0000033001 00000 n
-0000033290 00000 n
-0000033542 00000 n
-0000033794 00000 n
-0000034048 00000 n
-0000034302 00000 n
-0000034541 00000 n
-0000034932 00000 n
-0000035191 00000 n
-0000035448 00000 n
-0000035700 00000 n
-0000035954 00000 n
-0000036212 00000 n
-0000036464 00000 n
-0000036722 00000 n
-0000036976 00000 n
-0000037230 00000 n
-0000037482 00000 n
-0000037734 00000 n
-0000037987 00000 n
-0000038241 00000 n
-0000038495 00000 n
-0000038749 00000 n
-0000039003 00000 n
-0000039282 00000 n
-0000039536 00000 n
-0000039823 00000 n
-0000040077 00000 n
-0000040388 00000 n
-0000040640 00000 n
-0000040892 00000 n
-0000041181 00000 n
-0000041433 00000 n
-0000041685 00000 n
-0000041943 00000 n
-0000042182 00000 n
-0000042759 00000 n
-0000042923 00000 n
-0000043197 00000 n
-0000043326 00000 n
-0000043520 00000 n
-0000043731 00000 n
-0000043941 00000 n
-0000044163 00000 n
-0000044361 00000 n
-0000044566 00000 n
-0000044759 00000 n
-0000044958 00000 n
-0000045155 00000 n
-0000045369 00000 n
-0000045567 00000 n
-0000045778 00000 n
-0000045970 00000 n
-0000046153 00000 n
-0000046412 00000 n
-0000055856 00000 n
-0000060880 00000 n
-0000065177 00000 n
-0000069279 00000 n
-0000074056 00000 n
-0000078293 00000 n
-0000082887 00000 n
-0000088055 00000 n
-0000093492 00000 n
-0000098106 00000 n
-0000102445 00000 n
-0000105971 00000 n
-0000110121 00000 n
-0000117019 00000 n
-0000124326 00000 n
-0000131289 00000 n
-0000139041 00000 n
-0000139368 00000 n
-0000139447 00000 n
-0000139526 00000 n
-0000139605 00000 n
-0000139684 00000 n
-0000139763 00000 n
-0000139842 00000 n
-0000139921 00000 n
-0000140000 00000 n
-0000140079 00000 n
-0000140159 00000 n
-0000140239 00000 n
-0000140319 00000 n
-0000140399 00000 n
-0000140479 00000 n
-0000140559 00000 n
-0000140639 00000 n
+0000030349 00000 n
+0000030602 00000 n
+0000030856 00000 n
+0000031130 00000 n
+0000031405 00000 n
+0000031659 00000 n
+0000031896 00000 n
+0000032417 00000 n
+0000032735 00000 n
+0000032989 00000 n
+0000033278 00000 n
+0000033530 00000 n
+0000033782 00000 n
+0000034036 00000 n
+0000034290 00000 n
+0000034529 00000 n
+0000034920 00000 n
+0000035179 00000 n
+0000035436 00000 n
+0000035688 00000 n
+0000035942 00000 n
+0000036200 00000 n
+0000036452 00000 n
+0000036710 00000 n
+0000036964 00000 n
+0000037217 00000 n
+0000037478 00000 n
+0000037732 00000 n
+0000037986 00000 n
+0000038240 00000 n
+0000038494 00000 n
+0000038746 00000 n
+0000038998 00000 n
+0000039251 00000 n
+0000039505 00000 n
+0000039759 00000 n
+0000040013 00000 n
+0000040267 00000 n
+0000040542 00000 n
+0000040796 00000 n
+0000041083 00000 n
+0000041337 00000 n
+0000041648 00000 n
+0000041900 00000 n
+0000042152 00000 n
+0000042441 00000 n
+0000042693 00000 n
+0000042945 00000 n
+0000043203 00000 n
+0000043442 00000 n
+0000044069 00000 n
+0000044233 00000 n
+0000044507 00000 n
+0000044636 00000 n
+0000044830 00000 n
+0000045041 00000 n
+0000045251 00000 n
+0000045473 00000 n
+0000045671 00000 n
+0000045876 00000 n
+0000046069 00000 n
+0000046268 00000 n
+0000046465 00000 n
+0000046679 00000 n
+0000046877 00000 n
+0000047088 00000 n
+0000047280 00000 n
+0000047463 00000 n
+0000047722 00000 n
+0000057166 00000 n
+0000062190 00000 n
+0000066487 00000 n
+0000070589 00000 n
+0000075366 00000 n
+0000079603 00000 n
+0000084197 00000 n
+0000089365 00000 n
+0000094802 00000 n
+0000099416 00000 n
+0000103755 00000 n
+0000107281 00000 n
+0000111473 00000 n
+0000118371 00000 n
+0000125678 00000 n
+0000132641 00000 n
+0000140973 00000 n
+0000141300 00000 n
+0000141379 00000 n
+0000141458 00000 n
+0000141537 00000 n
+0000141616 00000 n
+0000141695 00000 n
+0000141774 00000 n
+0000141853 00000 n
+0000141932 00000 n
+0000142011 00000 n
+0000142091 00000 n
+0000142171 00000 n
+0000142251 00000 n
+0000142331 00000 n
+0000142411 00000 n
+0000142491 00000 n
+0000142571 00000 n
trailer
<< /ID
% ReportLab generated PDF document -- digest (http://www.reportlab.com)
- [(\035U\351\206J$\3719\335\010i\224\201=?\204) (\035U\351\206J$\3719\335\010i\224\201=?\204)]
+ [(\272\236\026\327\302X\352+\277U\362\364\256\2152\272) (\272\236\026\327\302X\352+\277U\362\364\256\2152\272)]
- /Info 164 0 R
- /Root 163 0 R
- /Size 216 >>
+ /Info 169 0 R
+ /Root 168 0 R
+ /Size 221 >>
startxref
-140688
+142620
%%EOF
diff --git a/plac/doc/plac.txt b/plac/doc/plac.txt index f43d57c..7ae8e44 100644 --- a/plac/doc/plac.txt +++ b/plac/doc/plac.txt @@ -3,7 +3,7 @@ Plac: Parsing the Command Line the Easy Way :Author: Michele Simionato :E-mail: michele.simionato@gmail.com -:Date: June 2010 +:Date: July 2010 :Download page: http://pypi.python.org/pypi/plac :Project page: http://micheles.googlecode.com/hg/plac/doc/plac.html :Requires: Python 2.3+ @@ -697,7 +697,12 @@ Of course, there are tons of other libraries to parse the command line. For instance Clap_ by Matthew Frazier which appeared on PyPI just the day before plac_; Clap_ is fine but it is certainly not easier than plac_. - + +plac_ can also be used as a replacement of the cmd_ module in the standard +library and as such it shares many features with the module cmd2_ by +Catherine Devlin. However, this is completely coincidental, since I became +aware of the cmd2_ module only after writing plac_. + The future ------------------------------- @@ -769,3 +774,5 @@ That's all, I hope you will enjoy working with plac_! .. _CLIArgs: http://pypi.python.org/pypi/CLIArgs .. _opterator: http://pypi.python.org/pypi/opterator .. _advanced usage document: in-writing +.. _cmd2: http://packages.python.org/cmd2/ +.. _cmd: http://docs.python.org/library/cmd.html diff --git a/plac/doc/plac_adv.txt b/plac/doc/plac_adv.txt index 9ff1dab..3508464 100644 --- a/plac/doc/plac_adv.txt +++ b/plac/doc/plac_adv.txt @@ -215,7 +215,9 @@ languages as the ones you can implement with plac_. In particular, thanks to shlex_, plac_ is able to recognize comments (the default comment character is ``#``), escape sequences and more. Look at the shlex_ documentation if you need to customize how the language is -interpreted. +interpreted. For more flexibility, it is even possible to pass to the +interpreter a custom split function with signature ``split(line, +commentchar)``. In addition, I have implemented from scratch some support for line number recognition, so that if a test fail you get the line number of the diff --git a/plac/doc/sql_interface.py b/plac/doc/sql_interface.py index d045d03..ccedb97 100644 --- a/plac/doc/sql_interface.py +++ b/plac/doc/sql_interface.py @@ -11,8 +11,8 @@ class SqlInterface(object): commands = ['SELECT'] def __init__(self, dsn): self.soup = SqlSoup(dsn) - def SELECT(self, *args): - sql = 'SELECT ' + ' '.join(args) + def SELECT(self, argstring): + sql = 'SELECT ' + argstring for row in self.soup.bind.execute(sql): yield str(row) # the formatting can be much improved @@ -21,5 +21,10 @@ rl_input = plac.ReadlineInput( histfile=os.path.expanduser('~/.sql_interface.history'), case_sensitive=False) +def split_on_first_space(line, commentchar): + return line.strip().split(' ', 1) # ignoring comments + if __name__ == '__main__': - plac.Interpreter(plac.call(SqlInterface)).interact(rl_input) + si = plac.call(SqlInterface) + i = plac.Interpreter(si, split=split_on_first_space) + i.interact(rl_input) diff --git a/plac/plac_ext.py b/plac/plac_ext.py index 43adbbb..3cb858d 100644 --- a/plac/plac_ext.py +++ b/plac/plac_ext.py @@ -491,13 +491,14 @@ class Interpreter(object): A context manager with a .send method and a few utility methods: execute, test and doctest. """ - def __init__(self, obj, commentchar='#'): + def __init__(self, obj, commentchar='#', split=shlex.split): self.obj = obj try: self.name = obj.__module__ except AttributeError: self.name = 'plac' self.commentchar = commentchar + self.split = split self._set_commands(obj) self.tm = TaskManager(obj) self.parser = plac_core.parser_from(obj, prog='', add_help=False) @@ -544,7 +545,7 @@ class Interpreter(object): raise RuntimeError(_('%r not initialized: probably you forgot to ' 'use the with statement') % self) if isinstance(line, basestring): - arglist = shlex.split(line, self.commentchar) + arglist = self.split(line, self.commentchar) else: # expects a list of strings arglist = line return self._interpreter.send(arglist) @@ -653,10 +654,8 @@ class Interpreter(object): consolle. Using rlwrap is recommended. """ if stdin is sys.stdin and readline: # use readline - # print '.%s.history' % self.name - stdin = ReadlineInput( - self.commands, prompt, histfile='.%s.history' % self.name, - case_sensitive=True) + histfile = os.path.expanduser('~/.%s.history' % self.name) + stdin = ReadlineInput(self.commands, prompt, histfile=histfile) self.stdin = stdin self.prompt = getattr(stdin, 'prompt', prompt) self.verbose = verbose diff --git a/plac/plac_runner.py b/plac/plac_runner.py new file mode 100644 index 0000000..c9b7cef --- /dev/null +++ b/plac/plac_runner.py @@ -0,0 +1,58 @@ +#!python +from __future__ import with_statement +import os, sys, shlex, inspect +import plac + +def run(fnames, cmd, verbose): + "Run batch scripts and tests" + for fname in fnames: + with open(fname) as f: + lines = list(f) + if not lines[0].startswith('#!'): + sys.exit('Missing or incorrect shebang line!') + firstline = lines[0][2:] # strip the shebang + init_args = shlex.split(firstline) + tool = plac.import_main(*init_args) + command = getattr(plac.Interpreter(tool), cmd) # doctest or execute + if verbose: + sys.stdout.write('Running %s with %s' % (fname, firstline)) + command(lines[1:], verbose=verbose) + +@plac.annotations( + verbose=('verbose mode', 'flag', 'v'), + interactive=('run plac tool in interactive mode', 'flag', 'i'), + batch=('run plac batch files', 'flag', 'b'), + test=('run plac test files', 'flag', 't'), + fname='script to run (.py or .plac or .placet)', + extra='additional arguments', + ) +def main(verbose, interactive, batch, test, fname=None, *extra): + "Runner for plac tools, plac batch files and plac tests" + baseparser = plac.parser_from(main) + if fname is None: + baseparser.print_help() + elif sys.argv[1] == fname: # script mode + plactool = plac.import_main( + fname, prog=os.path.basename(sys.argv[0]) + ' ' + fname) + out = plac.call(plactool, sys.argv[2:], eager=False) + if plac.iterable(out): + for output in out: + print(output) + else: + print(out) + elif interactive: + plactool = plac.import_main(fname, *extra, **{'prog': ''}) + if inspect.isclass(plactool): # special case + plactool = plactool() + plac.Interpreter(plactool).interact(verbose=verbose) + elif batch: + run((fname,) + extra, 'execute', verbose) + elif test: + run((fname,) + extra, 'doctest', verbose) + print('run %s plac test(s)' % (len(extra) + 1)) + else: + baseparser.print_usage() +main.add_help = False + +if __name__ == '__main__': + plac.call(main) |