summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichele Simionato <michele.simionato@gmail.com>2010-08-01 07:44:22 +0200
committerMichele Simionato <michele.simionato@gmail.com>2010-08-01 07:44:22 +0200
commit7a3d16040e06af8ea5acdc180eea712b597b78df (patch)
treeabd3f2c6560053b491d714c0a6dd89acdb2e637e
parent5b08a4da7625622a072d78edc6254185be453b3d (diff)
downloadmicheles-7a3d16040e06af8ea5acdc180eea712b597b78df.tar.gz
A few minor fixes/improvements
-rw-r--r--plac/CHANGES.txt2
-rw-r--r--plac/doc/plac.el46
-rw-r--r--plac/doc/plac_adv.html106
-rw-r--r--plac/doc/plac_adv.pdf2806
-rw-r--r--plac/doc/plac_adv.txt95
-rw-r--r--plac/doc/server_ex.py9
-rw-r--r--plac/doc/test_server.py1
-rw-r--r--plac/plac_ext.py4
8 files changed, 1547 insertions, 1522 deletions
diff --git a/plac/CHANGES.txt b/plac/CHANGES.txt
index e8f8e92..9d1414a 100644
--- a/plac/CHANGES.txt
+++ b/plac/CHANGES.txt
@@ -7,7 +7,7 @@ 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
+0.6.0 Improved the interactive experience with full readline support and
custom help. Added support for long running command, via threads and
processes (2010-07-11)
0.5.0 Gigantic release. Introduced smart options, added an Interpreter class
diff --git a/plac/doc/plac.el b/plac/doc/plac.el
index c3b0de6..0eddcbb 100644
--- a/plac/doc/plac.el
+++ b/plac/doc/plac.el
@@ -4,13 +4,14 @@
'("#") ; comment chars
'(); highlighted commands
nil
- '(".plac"); file extensions
+ '(".plac\\'"); file extensions
nil)
(add-hook 'plac-mode-hook (lambda () (local-set-key [f4] 'plac-start)))
(add-hook 'plac-mode-hook (lambda () (local-set-key [f5] 'plac-send)))
(add-hook 'plac-mode-hook (lambda () (local-set-key [f6] 'plac-stop)))
+(defconst terminator 59); ASCII code for the semicolon
(defvar *plac-process* nil)
(defun plac-start ()
@@ -20,20 +21,57 @@
(let ((shebang-line
(save-excursion
(goto-line 1) (end-of-line)
- (buffer-substring 3 (point)))))
+ (buffer-substring-no-properties 3 (point)))))
(if *plac-process* (princ "plac already started")
(setq *plac-process*
(start-process
"plac" "*plac*" "plac_runner.py" "-m" shebang-line))))
(display-buffer "*plac*"))
+;(defun plac-send ()
+; "Send the current region to the inferior plac process"
+; (interactive)
+; (save-excursion (set-buffer "*plac*") (erase-buffer))
+; (process-send-region *plac-process* (region-beginning) (region-end)))
+
+(defun current-paragraph-beg-end ()
+ "Returns the extrema of the current paragraph, delimited by semicolons"
+ (interactive)
+ (save-excursion
+ (let ((beg (save-excursion (goto-line 2) (point))); skip the shebang
+ (end (point-max)))
+ ;; go backward
+ (while (> (point) beg)
+ (goto-char (1- (point)))
+ (if (= terminator (following-char))
+ (setq beg (point))))
+ (if (= terminator (following-char))
+ (setq beg (1+ beg)))
+ ;; go forward
+ (while (< (point) end)
+ (goto-char (1+ (point)))
+ (if (= 59 (following-char))
+ (setq end (point))))
+ (if (= 59 (following-char))
+ (setq end (1+ end)))
+ (list beg end))))
+
(defun plac-send ()
"Send the current region to the inferior plac process"
(interactive)
- (process-send-region *plac-process* (region-beginning) (region-end)))
+ (save-excursion (set-buffer "*plac*") (erase-buffer))
+ (let ((p (apply 'buffer-substring-no-properties (current-paragraph-beg-end))))
+ (message p)
+ (process-send-string *plac-process* (concat p "\n"))))
+ ;(switch-to-buffer-other-window "*plac*")))
+ ;(save-excursion (set-buffer "*plac*")
+ ; (set-window-start (selected-window) 1 nil))))
(defun plac-stop ()
"Stop the inferior plac process by sending to it an EOF"
(interactive)
(process-send-eof *plac-process*)
- (setq *plac-process* nil))
+ (setq *plac-process* nil)
+ "killed *plac-process*")
+
+(provide 'plac)
diff --git a/plac/doc/plac_adv.html b/plac/doc/plac_adv.html
index 5790048..b80d21c 100644
--- a/plac/doc/plac_adv.html
+++ b/plac/doc/plac_adv.html
@@ -6,7 +6,7 @@
<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
<title>Advanced usages of plac</title>
<meta name="author" content="Michele Simionato" />
-<meta name="date" content="July 2010" />
+<meta name="date" content="August 2010" />
<style type="text/css">
.first {
@@ -424,7 +424,7 @@ h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
<tr class="field"><th class="docinfo-name">E-mail:</th><td class="field-body"><a class="reference external" href="mailto:michele.simionato&#64;gmail.com">michele.simionato&#64;gmail.com</a></td>
</tr>
<tr><th class="docinfo-name">Date:</th>
-<td>July 2010</td></tr>
+<td>August 2010</td></tr>
<tr class="field"><th class="docinfo-name">Download page:</th><td class="field-body"><a class="reference external" href="http://pypi.python.org/pypi/plac">http://pypi.python.org/pypi/plac</a></td>
</tr>
<tr class="field"><th class="docinfo-name">Project page:</th><td class="field-body"><a class="reference external" href="http://micheles.googlecode.com/hg/plac/doc/plac.html">http://micheles.googlecode.com/hg/plac/doc/plac.html</a></td>
@@ -453,17 +453,16 @@ basic documentation.</em></p>
<li><a class="reference internal" href="#implementing-subcommands" id="id6">Implementing subcommands</a></li>
<li><a class="reference internal" href="#readline-support" id="id7">Readline support</a></li>
<li><a class="reference internal" href="#the-plac-runner" id="id8">The plac runner</a></li>
-<li><a class="reference internal" href="#multiline-support-and-emacs-integration" id="id9">Multiline support and Emacs integration</a></li>
-<li><a class="reference internal" href="#a-non-class-based-example" id="id10">A non class-based example</a></li>
-<li><a class="reference internal" href="#writing-your-own-plac-runner" id="id11">Writing your own plac runner</a></li>
-<li><a class="reference internal" href="#long-running-commands" id="id12">Long running commands</a></li>
-<li><a class="reference internal" href="#threaded-commands" id="id13">Threaded commands</a></li>
-<li><a class="reference internal" href="#running-commands-as-external-processes" id="id14">Running commands as external processes</a></li>
-<li><a class="reference internal" href="#managing-the-output-of-concurrent-commands" id="id15">Managing the output of concurrent commands</a></li>
-<li><a class="reference internal" href="#parallel-computing-with-plac" id="id16">Parallel computing with plac</a></li>
-<li><a class="reference internal" href="#the-plac-server" id="id17">The plac server</a></li>
-<li><a class="reference internal" href="#summary" id="id18">Summary</a></li>
-<li><a class="reference internal" href="#appendix-custom-annotation-objects" id="id19">Appendix: custom annotation objects</a></li>
+<li><a class="reference internal" href="#a-non-class-based-example" id="id9">A non class-based example</a></li>
+<li><a class="reference internal" href="#writing-your-own-plac-runner" id="id10">Writing your own plac runner</a></li>
+<li><a class="reference internal" href="#long-running-commands" id="id11">Long running commands</a></li>
+<li><a class="reference internal" href="#threaded-commands" id="id12">Threaded commands</a></li>
+<li><a class="reference internal" href="#running-commands-as-external-processes" id="id13">Running commands as external processes</a></li>
+<li><a class="reference internal" href="#managing-the-output-of-concurrent-commands" id="id14">Managing the output of concurrent commands</a></li>
+<li><a class="reference internal" href="#parallel-computing-with-plac" id="id15">Parallel computing with plac</a></li>
+<li><a class="reference internal" href="#the-plac-server" id="id16">The plac server</a></li>
+<li><a class="reference internal" href="#summary" id="id17">Summary</a></li>
+<li><a class="reference internal" href="#appendix-custom-annotation-objects" id="id18">Appendix: custom annotation objects</a></li>
</ul>
</div>
<div class="section" id="introduction">
@@ -991,7 +990,7 @@ and recorded and saved in the file <tt class="docutils literal"><span class="pre
exiting from the command-line interface.</p>
<p>If the readline library is not available, my suggestion is to use the
<a class="reference external" href="http://freshmeat.net/projects/rlwrap/">rlwrap</a> tool which provides similar features, at least on Unix-like
-platforms. <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> should also work fine on Windows with the <a href="#id20"><span class="problematic" id="id21">pyreadline_</span></a>
+platforms. <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> should also work fine on Windows with the <a href="#id19"><span class="problematic" id="id20">pyreadline_</span></a>
library (I do not use Windows, so this part is very little tested: I
tried it only once and it worked, but your mileage may vary).
For people worried about licenses, I will notice that <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> uses the
@@ -1148,11 +1147,11 @@ setting a=1
$ plac ishelve.py .show
a=1
</pre>
-<p>Notice that it non-interactive mode the runner just invokes <tt class="docutils literal">plac.call</tt>
+<p>Notice that in non-interactive mode the runner just invokes <tt class="docutils literal">plac.call</tt>
on the <tt class="docutils literal">main</tt> object of the Python module.</p>
-</div>
-<div class="section" id="multiline-support-and-emacs-integration">
-<h1><a class="toc-backref" href="#id9">Multiline support and Emacs integration</a></h1>
+<!-- -->
+<blockquote>
+<p>Multiline support and Emacs integration</p>
<p><a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> is optimized for the simplest use case and by default it provide
support for simple command-line languages where a command take
a single line. This is the simplest case: it is easy to keep
@@ -1203,6 +1202,7 @@ a = 1
(add-hook 'plac-mode-hook (lambda () (local-set-key [f5] 'plac-send)))
(add-hook 'plac-mode-hook (lambda () (local-set-key [f6] 'plac-stop)))
+(defconst terminator 59); ASCII code for the semicolon
(defvar *plac-process* nil)
(defun plac-start ()
@@ -1212,28 +1212,66 @@ a = 1
(let ((shebang-line
(save-excursion
(goto-line 1) (end-of-line)
- (buffer-substring 3 (point)))))
+ (buffer-substring-no-properties 3 (point)))))
(if *plac-process* (princ &quot;plac already started&quot;)
(setq *plac-process*
(start-process
&quot;plac&quot; &quot;*plac*&quot; &quot;plac_runner.py&quot; &quot;-m&quot; shebang-line))))
(display-buffer &quot;*plac*&quot;))
+;(defun plac-send ()
+; &quot;Send the current region to the inferior plac process&quot;
+; (interactive)
+; (save-excursion (set-buffer &quot;*plac*&quot;) (erase-buffer))
+; (process-send-region *plac-process* (region-beginning) (region-end)))
+
+(defun current-paragraph-beg-end ()
+ &quot;Returns the extrema of the current paragraph, delimited by semicolons&quot;
+ (interactive)
+ (save-excursion
+ (let ((beg (save-excursion (goto-line 2) (point))); skip the shebang
+ (end (point-max)))
+ ;; go backward
+ (while (&gt; (point) beg)
+ (goto-char (1- (point)))
+ (if (= terminator (following-char))
+ (setq beg (point))))
+ (if (= terminator (following-char))
+ (setq beg (1+ beg)))
+ ;; go forward
+ (while (&lt; (point) end)
+ (goto-char (1+ (point)))
+ (if (= 59 (following-char))
+ (setq end (point))))
+ (if (= 59 (following-char))
+ (setq end (1+ end)))
+ (list beg end))))
+
(defun plac-send ()
&quot;Send the current region to the inferior plac process&quot;
(interactive)
- (process-send-region *plac-process* (region-beginning) (region-end)))
+ (save-excursion (set-buffer &quot;*plac*&quot;) (erase-buffer))
+ (let ((p (apply 'buffer-substring-no-properties (current-paragraph-beg-end))))
+ (message p)
+ (process-send-string *plac-process* (concat p &quot;\n&quot;))))
+ ;(switch-to-buffer-other-window &quot;*plac*&quot;)))
+ ;(save-excursion (set-buffer &quot;*plac*&quot;)
+ ; (set-window-start (selected-window) 1 nil))))
(defun plac-stop ()
&quot;Stop the inferior plac process by sending to it an EOF&quot;
(interactive)
(process-send-eof *plac-process*)
- (setq *plac-process* nil))
+ (setq *plac-process* nil)
+ &quot;killed *plac-process*&quot;)
+
+(provide 'plac)
</pre>
+</blockquote>
</div>
<div class="section" id="a-non-class-based-example">
-<h1><a class="toc-backref" href="#id10">A non class-based example</a></h1>
+<h1><a class="toc-backref" href="#id9">A non class-based example</a></h1>
<p><a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> does not force you to use classes to define command containers.
Even a simple function can be a valid command container, it is
enough to add to it a <tt class="docutils literal">.commands</tt> attribute and possibly
@@ -1346,7 +1384,7 @@ a method container. In other situations, it is best to use a custom
class.</p>
</div>
<div class="section" id="writing-your-own-plac-runner">
-<h1><a class="toc-backref" href="#id11">Writing your own plac runner</a></h1>
+<h1><a class="toc-backref" href="#id10">Writing your own plac runner</a></h1>
<p>The runner included in the <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> distribution is intentionally kept
small (around 50 lines of code) so that you can study it and write
your own runner if want to. If you need to go to such level
@@ -1420,7 +1458,7 @@ loop in a separate process and send commands to it via the Queue
class provided by the <a class="reference external" href="http://docs.python.org/library/multiprocessing.html">multiprocessing</a> module.</p>
</div>
<div class="section" id="long-running-commands">
-<h1><a class="toc-backref" href="#id12">Long running commands</a></h1>
+<h1><a class="toc-backref" href="#id11">Long running commands</a></h1>
<p>As we saw, by default a <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> interpreter blocks until
the command terminates. This is an issue, in the sense that it makes
the interactive experience quite painful for long running commands. An
@@ -1468,7 +1506,7 @@ the interface responsive. <a class="reference external" href="http://pypi.python
and processes.</p>
</div>
<div class="section" id="threaded-commands">
-<h1><a class="toc-backref" href="#id13">Threaded commands</a></h1>
+<h1><a class="toc-backref" href="#id12">Threaded commands</a></h1>
<p>The most familiar way to execute a task in the background (even if not
necessarily the best way) is to run it into a separated thread. In our
example it is sufficient to replace the line</p>
@@ -1568,7 +1606,7 @@ if __name__ == '__main__':
</pre>
</div>
<div class="section" id="running-commands-as-external-processes">
-<h1><a class="toc-backref" href="#id14">Running commands as external processes</a></h1>
+<h1><a class="toc-backref" href="#id13">Running commands as external processes</a></h1>
<p>Threads are not loved much in the Python world and actually most people
prefer to use processes instead. For this reason <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> provides the
option to execute long running commands as external processes. Unfortunately
@@ -1611,7 +1649,7 @@ and it is safer than using threads, so it is the recommended approach
unless you are working on Windows.</p>
</div>
<div class="section" id="managing-the-output-of-concurrent-commands">
-<h1><a class="toc-backref" href="#id15">Managing the output of concurrent commands</a></h1>
+<h1><a class="toc-backref" href="#id14">Managing the output of concurrent commands</a></h1>
<p><a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> acts as a command-line task launcher and can be used as the base
to build a GUI-based task launcher and task monitor. To this aim the
interpreter class provides a <tt class="docutils literal">.submit</tt> method which returns a task
@@ -1663,7 +1701,7 @@ if __name__ == '__main__':
</pre>
</div>
<div class="section" id="parallel-computing-with-plac">
-<h1><a class="toc-backref" href="#id16">Parallel computing with plac</a></h1>
+<h1><a class="toc-backref" href="#id15">Parallel computing with plac</a></h1>
<p><a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> is certainly not intended as a tool for parallel computing, but
still you can use it to launch a set of commands and to collect the
results, similarly to the MapReduce pattern recently popularized by
@@ -1785,7 +1823,7 @@ $ python picalculator.py -mS 10000000
mode is some 20% slower than the sequential mode.</p>
</div>
<div class="section" id="the-plac-server">
-<h1><a class="toc-backref" href="#id17">The plac server</a></h1>
+<h1><a class="toc-backref" href="#id16">The plac server</a></h1>
<p>A command-line oriented interface can be easily converted into a
socket-based interface. Starting from release 0.7 plac features
a builtin server which is able to accept commands from multiple
@@ -1803,11 +1841,9 @@ For instance, here is how you could manage remote import on a database:</p>
<pre class="literal-block">
import plac
from importer2 import FakeImporter
-from ishelve2 import ShelveInterface
if __name__ == '__main__':
main = FakeImporter('dsn')
- #main = ShelveInterface()
plac.Interpreter(main).start_server() # default port 2199
</pre>
@@ -1829,7 +1865,7 @@ Connection closed by foreign host.
</pre>
</div>
<div class="section" id="summary">
-<h1><a class="toc-backref" href="#id18">Summary</a></h1>
+<h1><a class="toc-backref" href="#id17">Summary</a></h1>
<p>Once <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> claimed to be the easiest command-line arguments parser
in the world. Having read this document you may think that it is not
so easy after all. But it is a false impression. Actually the
@@ -1854,7 +1890,7 @@ given port number (default 2199)</li>
<p>Moreover, remember that <tt class="docutils literal">plac_runner.py</tt> is your friend.</p>
</div>
<div class="section" id="appendix-custom-annotation-objects">
-<h1><a class="toc-backref" href="#id19">Appendix: custom annotation objects</a></h1>
+<h1><a class="toc-backref" href="#id18">Appendix: custom annotation objects</a></h1>
<p>Internally <a class="reference external" href="http://pypi.python.org/pypi/plac">plac</a> uses an <tt class="docutils literal">Annotation</tt> class to convert the tuples
in the function signature into annotation objects, i.e. objects with
six attributes <tt class="docutils literal">help, kind, short, type, choices, metavar</tt>.</p>
@@ -1911,8 +1947,8 @@ pretty well for most users.</p>
</div>
<div class="system-messages section">
<h1>Docutils System Messages</h1>
-<div class="system-message" id="id20">
-<p class="system-message-title">System Message: ERROR/3 (<tt class="docutils">plac_adv.txt</tt>, line 438); <em><a href="#id21">backlink</a></em></p>
+<div class="system-message" id="id19">
+<p class="system-message-title">System Message: ERROR/3 (<tt class="docutils">plac_adv.txt</tt>, line 438); <em><a href="#id20">backlink</a></em></p>
Unknown target name: &quot;pyreadline&quot;.</div>
</div>
</div>
diff --git a/plac/doc/plac_adv.pdf b/plac/doc/plac_adv.pdf
index c8efff1..96d41dd 100644
--- a/plac/doc/plac_adv.pdf
+++ b/plac/doc/plac_adv.pdf
@@ -105,10 +105,10 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 50 0 R
+ /Dest [ 48 0 R
/XYZ
62.69291
- 164.0236
+ 182.0236
0 ]
/Rect [ 62.69291
506.5936
@@ -123,10 +123,10 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 50 0 R
+ /Dest [ 48 0 R
/XYZ
62.69291
- 164.0236
+ 182.0236
0 ]
/Rect [ 527.0227
506.5936
@@ -141,10 +141,10 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 60 0 R
+ /Dest [ 58 0 R
/XYZ
62.69291
- 609.0236
+ 633.0236
0 ]
/Rect [ 62.69291
488.5936
@@ -159,10 +159,10 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 60 0 R
+ /Dest [ 58 0 R
/XYZ
62.69291
- 609.0236
+ 633.0236
0 ]
/Rect [ 527.0227
488.5936
@@ -177,10 +177,10 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 62 0 R
+ /Dest [ 60 0 R
/XYZ
62.69291
- 151.4236
+ 175.4236
0 ]
/Rect [ 62.69291
470.5936
@@ -195,10 +195,10 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 62 0 R
+ /Dest [ 60 0 R
/XYZ
62.69291
- 151.4236
+ 175.4236
0 ]
/Rect [ 527.0227
470.5936
@@ -213,7 +213,7 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 74 0 R
+ /Dest [ 72 0 R
/XYZ
62.69291
765.0236
@@ -231,7 +231,7 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 74 0 R
+ /Dest [ 72 0 R
/XYZ
62.69291
765.0236
@@ -249,7 +249,7 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 77 0 R
+ /Dest [ 75 0 R
/XYZ
62.69291
461.8485
@@ -267,7 +267,7 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 77 0 R
+ /Dest [ 75 0 R
/XYZ
62.69291
461.8485
@@ -285,7 +285,7 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 82 0 R
+ /Dest [ 80 0 R
/XYZ
62.69291
539.8236
@@ -303,7 +303,7 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 82 0 R
+ /Dest [ 80 0 R
/XYZ
62.69291
539.8236
@@ -321,7 +321,7 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 88 0 R
+ /Dest [ 86 0 R
/XYZ
62.69291
460.0769
@@ -339,7 +339,7 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 88 0 R
+ /Dest [ 86 0 R
/XYZ
62.69291
460.0769
@@ -357,7 +357,7 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 104 0 R
+ /Dest [ 102 0 R
/XYZ
62.69291
554.6236
@@ -375,7 +375,7 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 104 0 R
+ /Dest [ 102 0 R
/XYZ
62.69291
554.6236
@@ -393,14 +393,14 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 115 0 R
+ /Dest [ 116 0 R
/XYZ
62.69291
- 729.0236
+ 765.0236
0 ]
/Rect [ 62.69291
362.5936
- 253.2829
+ 193.8529
374.5936 ]
/Subtype /Link
/Type /Annot >>
@@ -411,10 +411,10 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 115 0 R
+ /Dest [ 116 0 R
/XYZ
62.69291
- 729.0236
+ 765.0236
0 ]
/Rect [ 521.4627
362.5936
@@ -429,14 +429,14 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 117 0 R
+ /Dest [ 119 0 R
/XYZ
62.69291
- 523.8236
+ 765.0236
0 ]
/Rect [ 62.69291
344.5936
- 193.8529
+ 201.6029
356.5936 ]
/Subtype /Link
/Type /Annot >>
@@ -447,10 +447,10 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 117 0 R
+ /Dest [ 119 0 R
/XYZ
62.69291
- 523.8236
+ 765.0236
0 ]
/Rect [ 521.4627
344.5936
@@ -465,14 +465,14 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 120 0 R
+ /Dest [ 123 0 R
/XYZ
62.69291
- 533.8236
+ 615.8236
0 ]
/Rect [ 62.69291
326.5936
- 201.6029
+ 182.7029
338.5936 ]
/Subtype /Link
/Type /Annot >>
@@ -483,10 +483,10 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 120 0 R
+ /Dest [ 123 0 R
/XYZ
62.69291
- 533.8236
+ 615.8236
0 ]
/Rect [ 521.4627
326.5936
@@ -501,14 +501,14 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 123 0 R
+ /Dest [ 125 0 R
/XYZ
62.69291
- 384.6236
+ 741.0236
0 ]
/Rect [ 62.69291
308.5936
- 182.7029
+ 163.2729
320.5936 ]
/Subtype /Link
/Type /Annot >>
@@ -519,10 +519,10 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 123 0 R
+ /Dest [ 125 0 R
/XYZ
62.69291
- 384.6236
+ 741.0236
0 ]
/Rect [ 521.4627
308.5936
@@ -537,14 +537,14 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 126 0 R
+ /Dest [ 128 0 R
/XYZ
62.69291
- 498.6236
+ 237.4236
0 ]
/Rect [ 62.69291
290.5936
- 163.2729
+ 266.0929
302.5936 ]
/Subtype /Link
/Type /Annot >>
@@ -555,10 +555,10 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 126 0 R
+ /Dest [ 128 0 R
/XYZ
62.69291
- 498.6236
+ 237.4236
0 ]
/Rect [ 521.4627
290.5936
@@ -576,11 +576,11 @@ endobj
/Dest [ 130 0 R
/XYZ
62.69291
- 667.8236
+ 447.8236
0 ]
/Rect [ 62.69291
272.5936
- 266.0929
+ 283.8229
284.5936 ]
/Subtype /Link
/Type /Annot >>
@@ -594,7 +594,7 @@ endobj
/Dest [ 130 0 R
/XYZ
62.69291
- 667.8236
+ 447.8236
0 ]
/Rect [ 521.4627
272.5936
@@ -609,14 +609,14 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 133 0 R
+ /Dest [ 132 0 R
/XYZ
62.69291
- 765.0236
+ 571.8236
0 ]
/Rect [ 62.69291
254.5936
- 283.8229
+ 197.7329
266.5936 ]
/Subtype /Link
/Type /Annot >>
@@ -627,10 +627,10 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 133 0 R
+ /Dest [ 132 0 R
/XYZ
62.69291
- 765.0236
+ 571.8236
0 ]
/Rect [ 521.4627
254.5936
@@ -645,14 +645,14 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 133 0 R
+ /Dest [ 135 0 R
/XYZ
62.69291
- 230.8236
+ 537.8236
0 ]
/Rect [ 62.69291
236.5936
- 197.7329
+ 136.0629
248.5936 ]
/Subtype /Link
/Type /Annot >>
@@ -663,10 +663,10 @@ endobj
0
0 ]
/Contents ()
- /Dest [ 133 0 R
+ /Dest [ 135 0 R
/XYZ
62.69291
- 230.8236
+ 537.8236
0 ]
/Rect [ 521.4627
236.5936
@@ -688,7 +688,7 @@ endobj
0 ]
/Rect [ 62.69291
218.5936
- 136.0629
+ 108.2629
230.5936 ]
/Subtype /Link
/Type /Annot >>
@@ -720,11 +720,11 @@ endobj
/Dest [ 138 0 R
/XYZ
62.69291
- 303.6236
+ 468.0236
0 ]
/Rect [ 62.69291
200.5936
- 108.2629
+ 241.6029
212.5936 ]
/Subtype /Link
/Type /Annot >>
@@ -738,7 +738,7 @@ endobj
/Dest [ 138 0 R
/XYZ
62.69291
- 303.6236
+ 468.0236
0 ]
/Rect [ 521.4627
200.5936
@@ -747,44 +747,8 @@ endobj
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER40': class LinkAnnotation
+% 'Annot.NUMBER40': class PDFDictionary
46 0 obj
-<< /Border [ 0
- 0
- 0 ]
- /Contents ()
- /Dest [ 140 0 R
- /XYZ
- 62.69291
- 675.0236
- 0 ]
- /Rect [ 62.69291
- 182.5936
- 241.6029
- 194.5936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER41': class LinkAnnotation
-47 0 obj
-<< /Border [ 0
- 0
- 0 ]
- /Contents ()
- /Dest [ 140 0 R
- /XYZ
- 62.69291
- 675.0236
- 0 ]
- /Rect [ 521.4627
- 182.5936
- 532.5827
- 194.5936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER42': class PDFDictionary
-48 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -792,14 +756,14 @@ endobj
0
0 ]
/Rect [ 185.4471
- 128.5936
+ 146.5936
207.1062
- 140.5936 ]
+ 158.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER43': class PDFDictionary
-49 0 obj
+% 'Annot.NUMBER41': class PDFDictionary
+47 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -807,14 +771,14 @@ endobj
0
0 ]
/Rect [ 177.6784
- 116.5936
+ 134.5936
199.6123
- 128.5936 ]
+ 146.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
% 'Page1': class PDFPage
-50 0 obj
+48 0 obj
% Page dictionary
<< /Annots [ 5 0 R
6 0 R
@@ -856,15 +820,13 @@ endobj
44 0 R
45 0 R
46 0 R
- 47 0 R
- 48 0 R
- 49 0 R ]
- /Contents 165 0 R
+ 47 0 R ]
+ /Contents 162 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 164 0 R
+ /Parent 161 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -875,8 +837,8 @@ endobj
/Trans << >>
/Type /Page >>
endobj
-% 'Annot.NUMBER44': class PDFDictionary
-51 0 obj
+% 'Annot.NUMBER42': class PDFDictionary
+49 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -884,14 +846,14 @@ endobj
0
0 ]
/Rect [ 62.69291
- 732.5936
+ 756.5936
83.81291
- 744.5936 ]
+ 768.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER45': class PDFDictionary
-52 0 obj
+% 'Annot.NUMBER43': class PDFDictionary
+50 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -899,14 +861,14 @@ endobj
0
0 ]
/Rect [ 278.4678
- 714.5936
+ 738.5936
300.0328
- 726.5936 ]
+ 750.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER46': class PDFDictionary
-53 0 obj
+% 'Annot.NUMBER44': class PDFDictionary
+51 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -914,14 +876,14 @@ endobj
0
0 ]
/Rect [ 117.3573
- 702.5936
+ 726.5936
138.5845
- 714.5936 ]
+ 738.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER47': class PDFDictionary
-54 0 obj
+% 'Annot.NUMBER45': class PDFDictionary
+52 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://twill.idyll.org/) >>
@@ -929,14 +891,14 @@ endobj
0
0 ]
/Rect [ 82.74466
- 660.5936
+ 684.5936
104.4564
- 672.5936 ]
+ 696.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER48': class PDFDictionary
-55 0 obj
+% 'Annot.NUMBER46': class PDFDictionary
+53 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -944,14 +906,14 @@ endobj
0
0 ]
/Rect [ 127.2882
- 660.5936
+ 684.5936
145.6282
- 672.5936 ]
+ 696.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER49': class PDFDictionary
-56 0 obj
+% 'Annot.NUMBER47': class PDFDictionary
+54 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -959,14 +921,14 @@ endobj
0
0 ]
/Rect [ 410.1674
- 660.5936
+ 684.5936
433.5592
- 672.5936 ]
+ 696.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER50': class PDFDictionary
-57 0 obj
+% 'Annot.NUMBER48': class PDFDictionary
+55 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -974,14 +936,14 @@ endobj
0
0 ]
/Rect [ 265.9578
- 636.5936
+ 660.5936
284.2978
- 648.5936 ]
+ 672.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER51': class PDFDictionary
-58 0 obj
+% 'Annot.NUMBER49': class PDFDictionary
+56 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -989,14 +951,14 @@ endobj
0
0 ]
/Rect [ 487.7492
- 636.5936
+ 660.5936
506.0892
- 648.5936 ]
+ 672.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER52': class PDFDictionary
-59 0 obj
+% 'Annot.NUMBER50': class PDFDictionary
+57 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://micheles.googlecode.com/hg/plac/doc/plac.html) >>
@@ -1004,30 +966,30 @@ endobj
0
0 ]
/Rect [ 62.69291
- 477.5936
+ 501.5936
157.1829
- 489.5936 ]
+ 513.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
% 'Page2': class PDFPage
-60 0 obj
+58 0 obj
% Page dictionary
-<< /Annots [ 51 0 R
+<< /Annots [ 49 0 R
+ 50 0 R
+ 51 0 R
52 0 R
53 0 R
54 0 R
55 0 R
56 0 R
- 57 0 R
- 58 0 R
- 59 0 R ]
- /Contents 166 0 R
+ 57 0 R ]
+ /Contents 163 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 164 0 R
+ /Parent 161 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1038,8 +1000,8 @@ endobj
/Trans << >>
/Type /Page >>
endobj
-% 'Annot.NUMBER53': class PDFDictionary
-61 0 obj
+% 'Annot.NUMBER51': class PDFDictionary
+59 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1047,22 +1009,22 @@ endobj
0
0 ]
/Rect [ 383.9329
- 196.9936
+ 220.9936
405.0529
- 208.9936 ]
+ 232.9936 ]
/Subtype /Link
/Type /Annot >>
endobj
% 'Page3': class PDFPage
-62 0 obj
+60 0 obj
% Page dictionary
-<< /Annots [ 61 0 R ]
- /Contents 167 0 R
+<< /Annots [ 59 0 R ]
+ /Contents 164 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 164 0 R
+ /Parent 161 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1074,14 +1036,14 @@ endobj
/Type /Page >>
endobj
% 'Page4': class PDFPage
-63 0 obj
+61 0 obj
% Page dictionary
-<< /Contents 168 0 R
+<< /Contents 165 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 164 0 R
+ /Parent 161 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1092,8 +1054,8 @@ endobj
/Trans << >>
/Type /Page >>
endobj
-% 'Annot.NUMBER54': class PDFDictionary
-64 0 obj
+% 'Annot.NUMBER52': class PDFDictionary
+62 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1107,8 +1069,8 @@ endobj
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER55': class PDFDictionary
-65 0 obj
+% 'Annot.NUMBER53': class PDFDictionary
+63 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1122,8 +1084,8 @@ endobj
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER56': class PDFDictionary
-66 0 obj
+% 'Annot.NUMBER54': class PDFDictionary
+64 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1137,8 +1099,8 @@ endobj
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER57': class PDFDictionary
-67 0 obj
+% 'Annot.NUMBER55': class PDFDictionary
+65 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://docs.python.org/library/shlex.html) >>
@@ -1152,8 +1114,8 @@ endobj
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER58': class PDFDictionary
-68 0 obj
+% 'Annot.NUMBER56': class PDFDictionary
+66 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1167,8 +1129,8 @@ endobj
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER59': class PDFDictionary
-69 0 obj
+% 'Annot.NUMBER57': class PDFDictionary
+67 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://docs.python.org/library/shlex.html) >>
@@ -1182,8 +1144,8 @@ endobj
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER60': class PDFDictionary
-70 0 obj
+% 'Annot.NUMBER58': class PDFDictionary
+68 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1197,8 +1159,8 @@ endobj
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER61': class PDFDictionary
-71 0 obj
+% 'Annot.NUMBER59': class PDFDictionary
+69 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://docs.python.org/library/shlex.html) >>
@@ -1212,8 +1174,8 @@ endobj
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER62': class PDFDictionary
-72 0 obj
+% 'Annot.NUMBER60': class PDFDictionary
+70 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1227,8 +1189,8 @@ endobj
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER63': class PDFDictionary
-73 0 obj
+% 'Annot.NUMBER61': class PDFDictionary
+71 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1243,24 +1205,24 @@ endobj
/Type /Annot >>
endobj
% 'Page5': class PDFPage
-74 0 obj
+72 0 obj
% Page dictionary
-<< /Annots [ 64 0 R
+<< /Annots [ 62 0 R
+ 63 0 R
+ 64 0 R
65 0 R
66 0 R
67 0 R
68 0 R
69 0 R
70 0 R
- 71 0 R
- 72 0 R
- 73 0 R ]
- /Contents 169 0 R
+ 71 0 R ]
+ /Contents 166 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 164 0 R
+ /Parent 161 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1271,8 +1233,8 @@ endobj
/Trans << >>
/Type /Page >>
endobj
-% 'Annot.NUMBER64': class PDFDictionary
-75 0 obj
+% 'Annot.NUMBER62': class PDFDictionary
+73 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1286,8 +1248,8 @@ endobj
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER65': class PDFDictionary
-76 0 obj
+% 'Annot.NUMBER63': class PDFDictionary
+74 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1302,16 +1264,16 @@ endobj
/Type /Annot >>
endobj
% 'Page6': class PDFPage
-77 0 obj
+75 0 obj
% Page dictionary
-<< /Annots [ 75 0 R
- 76 0 R ]
- /Contents 170 0 R
+<< /Annots [ 73 0 R
+ 74 0 R ]
+ /Contents 167 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 164 0 R
+ /Parent 161 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1322,8 +1284,8 @@ endobj
/Trans << >>
/Type /Page >>
endobj
-% 'Annot.NUMBER66': class PDFDictionary
-78 0 obj
+% 'Annot.NUMBER64': class PDFDictionary
+76 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://micheles.googlecode.com/hg/plac/doc/plac.html) >>
@@ -1337,8 +1299,8 @@ endobj
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER67': class PDFDictionary
-79 0 obj
+% 'Annot.NUMBER65': class PDFDictionary
+77 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1352,8 +1314,8 @@ endobj
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER68': class PDFDictionary
-80 0 obj
+% 'Annot.NUMBER66': class PDFDictionary
+78 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1367,8 +1329,8 @@ endobj
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER69': class PDFDictionary
-81 0 obj
+% 'Annot.NUMBER67': class PDFDictionary
+79 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1383,18 +1345,18 @@ endobj
/Type /Annot >>
endobj
% 'Page7': class PDFPage
-82 0 obj
+80 0 obj
% Page dictionary
-<< /Annots [ 78 0 R
- 79 0 R
- 80 0 R
- 81 0 R ]
- /Contents 171 0 R
+<< /Annots [ 76 0 R
+ 77 0 R
+ 78 0 R
+ 79 0 R ]
+ /Contents 168 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 164 0 R
+ /Parent 161 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1405,8 +1367,8 @@ endobj
/Trans << >>
/Type /Page >>
endobj
-% 'Annot.NUMBER70': class PDFDictionary
-83 0 obj
+% 'Annot.NUMBER68': class PDFDictionary
+81 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1420,8 +1382,8 @@ endobj
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER71': class PDFDictionary
-84 0 obj
+% 'Annot.NUMBER69': class PDFDictionary
+82 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1435,8 +1397,8 @@ endobj
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER72': class PDFDictionary
-85 0 obj
+% 'Annot.NUMBER70': class PDFDictionary
+83 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://docs.python.org/library/cmd.html) >>
@@ -1451,17 +1413,17 @@ endobj
/Type /Annot >>
endobj
% 'Page8': class PDFPage
-86 0 obj
+84 0 obj
% Page dictionary
-<< /Annots [ 83 0 R
- 84 0 R
- 85 0 R ]
- /Contents 172 0 R
+<< /Annots [ 81 0 R
+ 82 0 R
+ 83 0 R ]
+ /Contents 169 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 164 0 R
+ /Parent 161 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1472,8 +1434,8 @@ endobj
/Trans << >>
/Type /Page >>
endobj
-% 'Annot.NUMBER73': class PDFDictionary
-87 0 obj
+% 'Annot.NUMBER71': class PDFDictionary
+85 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1488,15 +1450,15 @@ endobj
/Type /Annot >>
endobj
% 'Page9': class PDFPage
-88 0 obj
+86 0 obj
% Page dictionary
-<< /Annots [ 87 0 R ]
- /Contents 173 0 R
+<< /Annots [ 85 0 R ]
+ /Contents 170 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 164 0 R
+ /Parent 161 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1507,8 +1469,8 @@ endobj
/Trans << >>
/Type /Page >>
endobj
-% 'Annot.NUMBER74': class PDFDictionary
-89 0 obj
+% 'Annot.NUMBER72': class PDFDictionary
+87 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://freshmeat.net/projects/rlwrap/) >>
@@ -1522,8 +1484,8 @@ endobj
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER75': class PDFDictionary
-90 0 obj
+% 'Annot.NUMBER73': class PDFDictionary
+88 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1537,8 +1499,8 @@ endobj
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER76': class PDFDictionary
-91 0 obj
+% 'Annot.NUMBER74': class PDFDictionary
+89 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1552,8 +1514,8 @@ endobj
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER77': class PDFDictionary
-92 0 obj
+% 'Annot.NUMBER75': class PDFDictionary
+90 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1567,8 +1529,8 @@ endobj
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER78': class PDFDictionary
-93 0 obj
+% 'Annot.NUMBER76': class PDFDictionary
+91 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://docs.python.org/library/cmd.html) >>
@@ -1582,8 +1544,8 @@ endobj
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER79': class PDFDictionary
-94 0 obj
+% 'Annot.NUMBER77': class PDFDictionary
+92 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://docs.python.org/library/cmd.html) >>
@@ -1598,20 +1560,20 @@ endobj
/Type /Annot >>
endobj
% 'Page10': class PDFPage
-95 0 obj
+93 0 obj
% Page dictionary
-<< /Annots [ 89 0 R
+<< /Annots [ 87 0 R
+ 88 0 R
+ 89 0 R
90 0 R
91 0 R
- 92 0 R
- 93 0 R
- 94 0 R ]
- /Contents 174 0 R
+ 92 0 R ]
+ /Contents 171 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 164 0 R
+ /Parent 161 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1622,8 +1584,8 @@ endobj
/Trans << >>
/Type /Page >>
endobj
-% 'Annot.NUMBER80': class PDFDictionary
-96 0 obj
+% 'Annot.NUMBER78': class PDFDictionary
+94 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
@@ -1637,8 +1599,8 @@ endobj
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER81': class PDFDictionary
-97 0 obj
+% 'Annot.NUMBER79': class PDFDictionary
+95 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1652,8 +1614,8 @@ endobj
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER82': class PDFDictionary
-98 0 obj
+% 'Annot.NUMBER80': class PDFDictionary
+96 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
@@ -1667,8 +1629,8 @@ endobj
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER83': class PDFDictionary
-99 0 obj
+% 'Annot.NUMBER81': class PDFDictionary
+97 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1682,8 +1644,8 @@ endobj
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER84': class PDFDictionary
-100 0 obj
+% 'Annot.NUMBER82': class PDFDictionary
+98 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1697,8 +1659,8 @@ endobj
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER85': class PDFDictionary
-101 0 obj
+% 'Annot.NUMBER83': class PDFDictionary
+99 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1712,8 +1674,8 @@ endobj
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER86': class PDFDictionary
-102 0 obj
+% 'Annot.NUMBER84': class PDFDictionary
+100 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1727,8 +1689,8 @@ endobj
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER87': class PDFDictionary
-103 0 obj
+% 'Annot.NUMBER85': class PDFDictionary
+101 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://docs.python.org/distutils/) >>
@@ -1743,22 +1705,22 @@ endobj
/Type /Annot >>
endobj
% 'Page11': class PDFPage
-104 0 obj
+102 0 obj
% Page dictionary
-<< /Annots [ 96 0 R
+<< /Annots [ 94 0 R
+ 95 0 R
+ 96 0 R
97 0 R
98 0 R
99 0 R
100 0 R
- 101 0 R
- 102 0 R
- 103 0 R ]
- /Contents 175 0 R
+ 101 0 R ]
+ /Contents 172 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 164 0 R
+ /Parent 161 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1769,8 +1731,8 @@ endobj
/Trans << >>
/Type /Page >>
endobj
-% 'Annot.NUMBER88': class PDFDictionary
-105 0 obj
+% 'Annot.NUMBER86': class PDFDictionary
+103 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://argparse.googlecode.com) >>
@@ -1785,15 +1747,15 @@ endobj
/Type /Annot >>
endobj
% 'Page12': class PDFPage
-106 0 obj
+104 0 obj
% Page dictionary
-<< /Annots [ 105 0 R ]
- /Contents 176 0 R
+<< /Annots [ 103 0 R ]
+ /Contents 173 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 164 0 R
+ /Parent 161 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1804,143 +1766,143 @@ endobj
/Trans << >>
/Type /Page >>
endobj
-% 'Annot.NUMBER89': class PDFDictionary
-107 0 obj
+% 'Annot.NUMBER87': class PDFDictionary
+105 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
/Border [ 0
0
0 ]
- /Rect [ 62.69291
- 693.5936
- 85.42727
- 705.5936 ]
+ /Rect [ 82.69291
+ 692.7662
+ 104.1773
+ 704.7662 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER90': class PDFDictionary
-108 0 obj
+% 'Annot.NUMBER88': class PDFDictionary
+106 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
/Border [ 0
0
0 ]
- /Rect [ 389.1513
- 669.5936
- 410.2841
- 681.5936 ]
+ /Rect [ 445.3587
+ 668.7662
+ 467.5757
+ 680.7662 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER91': class PDFDictionary
-109 0 obj
+% 'Annot.NUMBER89': class PDFDictionary
+107 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
/Border [ 0
0
0 ]
- /Rect [ 80.0129
- 657.5936
- 101.7729
- 669.5936 ]
+ /Rect [ 157.9797
+ 656.7662
+ 179.1854
+ 668.7662 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER92': class PDFDictionary
-110 0 obj
+% 'Annot.NUMBER90': class PDFDictionary
+108 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
/Border [ 0
0
0 ]
- /Rect [ 140.4035
- 567.5936
- 162.977
- 579.5936 ]
+ /Rect [ 187.0217
+ 566.7662
+ 208.3864
+ 578.7662 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER93': class PDFDictionary
-111 0 obj
+% 'Annot.NUMBER91': class PDFDictionary
+109 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
/Border [ 0
0
0 ]
- /Rect [ 334.4378
- 543.5936
- 355.7761
- 555.5936 ]
+ /Rect [ 440.3127
+ 542.7662
+ 462.7327
+ 554.7662 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER94': class PDFDictionary
-112 0 obj
+% 'Annot.NUMBER92': class PDFDictionary
+110 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
/Border [ 0
0
0 ]
- /Rect [ 251.7193
- 531.5936
- 270.0593
- 543.5936 ]
+ /Rect [ 377.541
+ 530.7662
+ 395.881
+ 542.7662 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER95': class PDFDictionary
-113 0 obj
+% 'Annot.NUMBER93': class PDFDictionary
+111 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
/Border [ 0
0
0 ]
- /Rect [ 301.1816
- 501.5936
- 323.4792
- 513.5936 ]
+ /Rect [ 310.5934
+ 500.7662
+ 331.7145
+ 512.7662 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER96': class PDFDictionary
-114 0 obj
+% 'Annot.NUMBER94': class PDFDictionary
+112 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
/Border [ 0
0
0 ]
- /Rect [ 118.8329
- 376.3936
- 139.9529
- 388.3936 ]
+ /Rect [ 138.8329
+ 369.5662
+ 159.9529
+ 381.5662 ]
/Subtype /Link
/Type /Annot >>
endobj
% 'Page13': class PDFPage
-115 0 obj
+113 0 obj
% Page dictionary
-<< /Annots [ 107 0 R
+<< /Annots [ 105 0 R
+ 106 0 R
+ 107 0 R
108 0 R
109 0 R
110 0 R
111 0 R
- 112 0 R
- 113 0 R
- 114 0 R ]
- /Contents 177 0 R
+ 112 0 R ]
+ /Contents 174 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 164 0 R
+ /Parent 161 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1951,8 +1913,27 @@ endobj
/Trans << >>
/Type /Page >>
endobj
-% 'Annot.NUMBER97': class PDFDictionary
-116 0 obj
+% 'Page14': class PDFPage
+114 0 obj
+% Page dictionary
+<< /Contents 175 0 R
+ /MediaBox [ 0
+ 0
+ 595.2756
+ 841.8898 ]
+ /Parent 161 0 R
+ /Resources << /Font 1 0 R
+ /ProcSet [ /PDF
+ /Text
+ /ImageB
+ /ImageC
+ /ImageI ] >>
+ /Rotate 0
+ /Trans << >>
+ /Type /Page >>
+endobj
+% 'Annot.NUMBER95': class PDFDictionary
+115 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -1960,22 +1941,22 @@ endobj
0
0 ]
/Rect [ 62.69291
- 488.3936
+ 729.5936
84.72012
- 500.3936 ]
+ 741.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Page14': class PDFPage
-117 0 obj
+% 'Page15': class PDFPage
+116 0 obj
% Page dictionary
-<< /Annots [ 116 0 R ]
- /Contents 178 0 R
+<< /Annots [ 115 0 R ]
+ /Contents 176 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 164 0 R
+ /Parent 161 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -1986,15 +1967,15 @@ endobj
/Trans << >>
/Type /Page >>
endobj
-% 'Page15': class PDFPage
-118 0 obj
+% 'Page16': class PDFPage
+117 0 obj
% Page dictionary
-<< /Contents 179 0 R
+<< /Contents 177 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 164 0 R
+ /Parent 161 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -2005,8 +1986,8 @@ endobj
/Trans << >>
/Type /Page >>
endobj
-% 'Annot.NUMBER98': class PDFDictionary
-119 0 obj
+% 'Annot.NUMBER96': class PDFDictionary
+118 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -2014,22 +1995,22 @@ endobj
0
0 ]
/Rect [ 182.479
- 498.3936
+ 729.5936
203.7662
- 510.3936 ]
+ 741.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Page16': class PDFPage
-120 0 obj
+% 'Page17': class PDFPage
+119 0 obj
% Page dictionary
-<< /Annots [ 119 0 R ]
- /Contents 180 0 R
+<< /Annots [ 118 0 R ]
+ /Contents 178 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 164 0 R
+ /Parent 161 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -2040,8 +2021,8 @@ endobj
/Trans << >>
/Type /Page >>
endobj
-% 'Annot.NUMBER99': class PDFDictionary
-121 0 obj
+% 'Annot.NUMBER97': class PDFDictionary
+120 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://docs.python.org/library/multiprocessing.html) >>
@@ -2049,14 +2030,14 @@ endobj
0
0 ]
/Rect [ 295.0229
- 400.1936
+ 631.3936
367.2629
- 412.1936 ]
+ 643.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER100': class PDFDictionary
-122 0 obj
+% 'Annot.NUMBER98': class PDFDictionary
+121 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -2064,23 +2045,39 @@ endobj
0
0 ]
/Rect [ 179.1295
- 349.1936
+ 580.3936
201.6839
- 361.1936 ]
+ 592.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Page17': class PDFPage
+% 'Annot.NUMBER99': class PDFDictionary
+122 0 obj
+<< /A << /S /URI
+ /Type /Action
+ /URI (http://pypi.python.org/pypi/plac) >>
+ /Border [ 0
+ 0
+ 0 ]
+ /Rect [ 414.8874
+ 101.9936
+ 436.9487
+ 113.9936 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Page18': class PDFPage
123 0 obj
% Page dictionary
-<< /Annots [ 121 0 R
+<< /Annots [ 120 0 R
+ 121 0 R
122 0 R ]
- /Contents 181 0 R
+ /Contents 179 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 164 0 R
+ /Parent 161 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -2091,7 +2088,7 @@ endobj
/Trans << >>
/Type /Page >>
endobj
-% 'Annot.NUMBER101': class PDFDictionary
+% 'Annot.NUMBER100': class PDFDictionary
124 0 obj
<< /A << /S /URI
/Type /Action
@@ -2099,58 +2096,23 @@ endobj
/Border [ 0
0
0 ]
- /Rect [ 414.8874
- 526.1936
- 436.9487
- 538.1936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER102': class PDFDictionary
-125 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://pypi.python.org/pypi/plac) >>
- /Border [ 0
- 0
- 0 ]
/Rect [ 122.7054
- 379.1936
+ 621.5936
145.2085
- 391.1936 ]
+ 633.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Page18': class PDFPage
-126 0 obj
-% Page dictionary
-<< /Annots [ 124 0 R
- 125 0 R ]
- /Contents 182 0 R
- /MediaBox [ 0
- 0
- 595.2756
- 841.8898 ]
- /Parent 164 0 R
- /Resources << /Font 1 0 R
- /ProcSet [ /PDF
- /Text
- /ImageB
- /ImageC
- /ImageI ] >>
- /Rotate 0
- /Trans << >>
- /Type /Page >>
-endobj
% 'Page19': class PDFPage
-127 0 obj
+125 0 obj
% Page dictionary
-<< /Contents 183 0 R
+<< /Annots [ 124 0 R ]
+ /Contents 180 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 164 0 R
+ /Parent 161 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -2161,8 +2123,8 @@ endobj
/Trans << >>
/Type /Page >>
endobj
-% 'Annot.NUMBER103': class PDFDictionary
-128 0 obj
+% 'Annot.NUMBER101': class PDFDictionary
+126 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -2170,14 +2132,14 @@ endobj
0
0 ]
/Rect [ 183.3657
- 620.3936
+ 189.9936
207.8364
- 632.3936 ]
+ 201.9936 ]
/Subtype /Link
/Type /Annot >>
endobj
-% 'Annot.NUMBER104': class PDFDictionary
-129 0 obj
+% 'Annot.NUMBER102': class PDFDictionary
+127 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://docs.python.org/library/multiprocessing.html) >>
@@ -2185,23 +2147,23 @@ endobj
0
0 ]
/Rect [ 254.9929
- 596.3936
+ 165.9936
327.2329
- 608.3936 ]
+ 177.9936 ]
/Subtype /Link
/Type /Annot >>
endobj
% 'Page20': class PDFPage
-130 0 obj
+128 0 obj
% Page dictionary
-<< /Annots [ 128 0 R
- 129 0 R ]
- /Contents 184 0 R
+<< /Annots [ 126 0 R
+ 127 0 R ]
+ /Contents 181 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 164 0 R
+ /Parent 161 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -2212,8 +2174,8 @@ endobj
/Trans << >>
/Type /Page >>
endobj
-% 'Annot.NUMBER105': class PDFDictionary
-131 0 obj
+% 'Annot.NUMBER103': class PDFDictionary
+129 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -2221,38 +2183,22 @@ endobj
0
0 ]
/Rect [ 62.69291
- 729.5936
+ 412.3936
85.70846
- 741.5936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER106': class PDFDictionary
-132 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://pypi.python.org/pypi/plac) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 62.69291
- 195.3936
- 84.98766
- 207.3936 ]
+ 424.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
% 'Page21': class PDFPage
-133 0 obj
+130 0 obj
% Page dictionary
-<< /Annots [ 131 0 R
- 132 0 R ]
- /Contents 185 0 R
+<< /Annots [ 129 0 R ]
+ /Contents 182 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 164 0 R
+ /Parent 161 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -2263,15 +2209,31 @@ endobj
/Trans << >>
/Type /Page >>
endobj
+% 'Annot.NUMBER104': class PDFDictionary
+131 0 obj
+<< /A << /S /URI
+ /Type /Action
+ /URI (http://pypi.python.org/pypi/plac) >>
+ /Border [ 0
+ 0
+ 0 ]
+ /Rect [ 62.69291
+ 536.3936
+ 84.98766
+ 548.3936 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
% 'Page22': class PDFPage
-134 0 obj
+132 0 obj
% Page dictionary
-<< /Contents 186 0 R
+<< /Annots [ 131 0 R ]
+ /Contents 183 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 164 0 R
+ /Parent 161 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -2283,14 +2245,14 @@ endobj
/Type /Page >>
endobj
% 'Page23': class PDFPage
-135 0 obj
+133 0 obj
% Page dictionary
-<< /Contents 187 0 R
+<< /Contents 184 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 164 0 R
+ /Parent 161 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -2301,8 +2263,8 @@ endobj
/Trans << >>
/Type /Page >>
endobj
-% 'Annot.NUMBER107': class PDFDictionary
-136 0 obj
+% 'Annot.NUMBER105': class PDFDictionary
+134 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -2310,38 +2272,22 @@ endobj
0
0 ]
/Rect [ 172.4311
- 645.5936
+ 418.3936
194.7087
- 657.5936 ]
- /Subtype /Link
- /Type /Annot >>
-endobj
-% 'Annot.NUMBER108': class PDFDictionary
-137 0 obj
-<< /A << /S /URI
- /Type /Action
- /URI (http://pypi.python.org/pypi/plac) >>
- /Border [ 0
- 0
- 0 ]
- /Rect [ 91.57623
- 268.1936
- 114.8995
- 280.1936 ]
+ 430.3936 ]
/Subtype /Link
/Type /Annot >>
endobj
% 'Page24': class PDFPage
-138 0 obj
+135 0 obj
% Page dictionary
-<< /Annots [ 136 0 R
- 137 0 R ]
- /Contents 188 0 R
+<< /Annots [ 134 0 R ]
+ /Contents 185 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 164 0 R
+ /Parent 161 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -2352,8 +2298,23 @@ endobj
/Trans << >>
/Type /Page >>
endobj
-% 'Annot.NUMBER109': class PDFDictionary
-139 0 obj
+% 'Annot.NUMBER106': class PDFDictionary
+136 0 obj
+<< /A << /S /URI
+ /Type /Action
+ /URI (http://pypi.python.org/pypi/plac) >>
+ /Border [ 0
+ 0
+ 0 ]
+ /Rect [ 91.57623
+ 729.5936
+ 114.8995
+ 741.5936 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER107': class PDFDictionary
+137 0 obj
<< /A << /S /URI
/Type /Action
/URI (http://pypi.python.org/pypi/plac) >>
@@ -2361,22 +2322,23 @@ endobj
0
0 ]
/Rect [ 106.6216
- 639.5936
+ 432.5936
128.3202
- 651.5936 ]
+ 444.5936 ]
/Subtype /Link
/Type /Annot >>
endobj
% 'Page25': class PDFPage
-140 0 obj
+138 0 obj
% Page dictionary
-<< /Annots [ 139 0 R ]
- /Contents 189 0 R
+<< /Annots [ 136 0 R
+ 137 0 R ]
+ /Contents 186 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 164 0 R
+ /Parent 161 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -2388,14 +2350,14 @@ endobj
/Type /Page >>
endobj
% 'Page26': class PDFPage
-141 0 obj
+139 0 obj
% Page dictionary
-<< /Contents 190 0 R
+<< /Contents 187 0 R
/MediaBox [ 0
0
595.2756
841.8898 ]
- /Parent 164 0 R
+ /Parent 161 0 R
/Resources << /Font 1 0 R
/ProcSet [ /PDF
/Text
@@ -2406,293 +2368,281 @@ endobj
/Trans << >>
/Type /Page >>
endobj
-% 'R142': class PDFCatalog
-142 0 obj
+% 'R140': class PDFCatalog
+140 0 obj
% Document Root
-<< /Outlines 144 0 R
- /PageLabels 191 0 R
+<< /Outlines 142 0 R
+ /PageLabels 188 0 R
/PageMode /UseNone
- /Pages 164 0 R
+ /Pages 161 0 R
/Type /Catalog >>
endobj
-% 'R143': class PDFInfo
-143 0 obj
+% 'R141': class PDFInfo
+141 0 obj
<< /Author (Michele Simionato)
- /CreationDate (D:20100730155707-01'00')
+ /CreationDate (D:20100801071315-01'00')
/Keywords ()
/Producer (ReportLab http://www.reportlab.com)
/Subject (\(unspecified\))
/Title (Advanced usages of plac) >>
endobj
-% 'R144': class PDFOutlines
-144 0 obj
-<< /Count 19
- /First 145 0 R
- /Last 163 0 R
+% 'R142': class PDFOutlines
+142 0 obj
+<< /Count 18
+ /First 143 0 R
+ /Last 160 0 R
/Type /Outlines >>
endobj
% 'Outline.0': class OutlineEntryObject
-145 0 obj
-<< /Dest [ 50 0 R
+143 0 obj
+<< /Dest [ 48 0 R
/XYZ
62.69291
- 164.0236
+ 182.0236
0 ]
- /Next 146 0 R
- /Parent 144 0 R
+ /Next 144 0 R
+ /Parent 142 0 R
/Title (Introduction) >>
endobj
% 'Outline.1': class OutlineEntryObject
-146 0 obj
+144 0 obj
+<< /Dest [ 58 0 R
+ /XYZ
+ 62.69291
+ 633.0236
+ 0 ]
+ /Next 145 0 R
+ /Parent 142 0 R
+ /Prev 143 0 R
+ /Title (From scripts to interactive applications) >>
+endobj
+% 'Outline.2': class OutlineEntryObject
+145 0 obj
<< /Dest [ 60 0 R
/XYZ
62.69291
- 609.0236
+ 175.4236
+ 0 ]
+ /Next 146 0 R
+ /Parent 142 0 R
+ /Prev 144 0 R
+ /Title (Testing a plac application) >>
+endobj
+% 'Outline.3': class OutlineEntryObject
+146 0 obj
+<< /Dest [ 72 0 R
+ /XYZ
+ 62.69291
+ 765.0236
0 ]
/Next 147 0 R
- /Parent 144 0 R
+ /Parent 142 0 R
/Prev 145 0 R
- /Title (From scripts to interactive applications) >>
+ /Title (Plac easy tests) >>
endobj
-% 'Outline.2': class OutlineEntryObject
+% 'Outline.4': class OutlineEntryObject
147 0 obj
-<< /Dest [ 62 0 R
+<< /Dest [ 75 0 R
/XYZ
62.69291
- 151.4236
+ 461.8485
0 ]
/Next 148 0 R
- /Parent 144 0 R
+ /Parent 142 0 R
/Prev 146 0 R
- /Title (Testing a plac application) >>
+ /Title (Plac batch scripts) >>
endobj
-% 'Outline.3': class OutlineEntryObject
+% 'Outline.5': class OutlineEntryObject
148 0 obj
-<< /Dest [ 74 0 R
+<< /Dest [ 80 0 R
/XYZ
62.69291
- 765.0236
+ 539.8236
0 ]
/Next 149 0 R
- /Parent 144 0 R
+ /Parent 142 0 R
/Prev 147 0 R
- /Title (Plac easy tests) >>
+ /Title (Implementing subcommands) >>
endobj
-% 'Outline.4': class OutlineEntryObject
+% 'Outline.6': class OutlineEntryObject
149 0 obj
-<< /Dest [ 77 0 R
+<< /Dest [ 86 0 R
/XYZ
62.69291
- 461.8485
+ 460.0769
0 ]
/Next 150 0 R
- /Parent 144 0 R
+ /Parent 142 0 R
/Prev 148 0 R
- /Title (Plac batch scripts) >>
+ /Title (Readline support) >>
endobj
-% 'Outline.5': class OutlineEntryObject
+% 'Outline.7': class OutlineEntryObject
150 0 obj
-<< /Dest [ 82 0 R
+<< /Dest [ 102 0 R
/XYZ
62.69291
- 539.8236
+ 554.6236
0 ]
/Next 151 0 R
- /Parent 144 0 R
+ /Parent 142 0 R
/Prev 149 0 R
- /Title (Implementing subcommands) >>
+ /Title (The plac runner) >>
endobj
-% 'Outline.6': class OutlineEntryObject
+% 'Outline.8': class OutlineEntryObject
151 0 obj
-<< /Dest [ 88 0 R
+<< /Dest [ 116 0 R
/XYZ
62.69291
- 460.0769
+ 765.0236
0 ]
/Next 152 0 R
- /Parent 144 0 R
+ /Parent 142 0 R
/Prev 150 0 R
- /Title (Readline support) >>
+ /Title (A non class-based example) >>
endobj
-% 'Outline.7': class OutlineEntryObject
+% 'Outline.9': class OutlineEntryObject
152 0 obj
-<< /Dest [ 104 0 R
+<< /Dest [ 119 0 R
/XYZ
62.69291
- 554.6236
+ 765.0236
0 ]
/Next 153 0 R
- /Parent 144 0 R
+ /Parent 142 0 R
/Prev 151 0 R
- /Title (The plac runner) >>
+ /Title (Writing your own plac runner) >>
endobj
-% 'Outline.8': class OutlineEntryObject
+% 'Outline.10': class OutlineEntryObject
153 0 obj
-<< /Dest [ 115 0 R
+<< /Dest [ 123 0 R
/XYZ
62.69291
- 729.0236
+ 615.8236
0 ]
/Next 154 0 R
- /Parent 144 0 R
+ /Parent 142 0 R
/Prev 152 0 R
- /Title (Multiline support and Emacs integration) >>
+ /Title (Long running commands) >>
endobj
-% 'Outline.9': class OutlineEntryObject
+% 'Outline.11': class OutlineEntryObject
154 0 obj
-<< /Dest [ 117 0 R
+<< /Dest [ 125 0 R
/XYZ
62.69291
- 523.8236
+ 741.0236
0 ]
/Next 155 0 R
- /Parent 144 0 R
+ /Parent 142 0 R
/Prev 153 0 R
- /Title (A non class-based example) >>
+ /Title (Threaded commands) >>
endobj
-% 'Outline.10': class OutlineEntryObject
+% 'Outline.12': class OutlineEntryObject
155 0 obj
-<< /Dest [ 120 0 R
+<< /Dest [ 128 0 R
/XYZ
62.69291
- 533.8236
+ 237.4236
0 ]
/Next 156 0 R
- /Parent 144 0 R
+ /Parent 142 0 R
/Prev 154 0 R
- /Title (Writing your own plac runner) >>
+ /Title (Running commands as external processes) >>
endobj
-% 'Outline.11': class OutlineEntryObject
+% 'Outline.13': class OutlineEntryObject
156 0 obj
-<< /Dest [ 123 0 R
+<< /Dest [ 130 0 R
/XYZ
62.69291
- 384.6236
+ 447.8236
0 ]
/Next 157 0 R
- /Parent 144 0 R
+ /Parent 142 0 R
/Prev 155 0 R
- /Title (Long running commands) >>
+ /Title (Managing the output of concurrent commands) >>
endobj
-% 'Outline.12': class OutlineEntryObject
+% 'Outline.14': class OutlineEntryObject
157 0 obj
-<< /Dest [ 126 0 R
+<< /Dest [ 132 0 R
/XYZ
62.69291
- 498.6236
+ 571.8236
0 ]
/Next 158 0 R
- /Parent 144 0 R
+ /Parent 142 0 R
/Prev 156 0 R
- /Title (Threaded commands) >>
+ /Title (Parallel computing with plac) >>
endobj
-% 'Outline.13': class OutlineEntryObject
+% 'Outline.15': class OutlineEntryObject
158 0 obj
-<< /Dest [ 130 0 R
+<< /Dest [ 135 0 R
/XYZ
62.69291
- 667.8236
+ 537.8236
0 ]
/Next 159 0 R
- /Parent 144 0 R
+ /Parent 142 0 R
/Prev 157 0 R
- /Title (Running commands as external processes) >>
+ /Title (The plac server) >>
endobj
-% 'Outline.14': class OutlineEntryObject
+% 'Outline.16': class OutlineEntryObject
159 0 obj
-<< /Dest [ 133 0 R
+<< /Dest [ 138 0 R
/XYZ
62.69291
765.0236
0 ]
/Next 160 0 R
- /Parent 144 0 R
+ /Parent 142 0 R
/Prev 158 0 R
- /Title (Managing the output of concurrent commands) >>
-endobj
-% 'Outline.15': class OutlineEntryObject
-160 0 obj
-<< /Dest [ 133 0 R
- /XYZ
- 62.69291
- 230.8236
- 0 ]
- /Next 161 0 R
- /Parent 144 0 R
- /Prev 159 0 R
- /Title (Parallel computing with plac) >>
-endobj
-% 'Outline.16': class OutlineEntryObject
-161 0 obj
-<< /Dest [ 138 0 R
- /XYZ
- 62.69291
- 765.0236
- 0 ]
- /Next 162 0 R
- /Parent 144 0 R
- /Prev 160 0 R
- /Title (The plac server) >>
+ /Title (Summary) >>
endobj
% 'Outline.17': class OutlineEntryObject
-162 0 obj
+160 0 obj
<< /Dest [ 138 0 R
/XYZ
62.69291
- 303.6236
- 0 ]
- /Next 163 0 R
- /Parent 144 0 R
- /Prev 161 0 R
- /Title (Summary) >>
-endobj
-% 'Outline.18': class OutlineEntryObject
-163 0 obj
-<< /Dest [ 140 0 R
- /XYZ
- 62.69291
- 675.0236
+ 468.0236
0 ]
- /Parent 144 0 R
- /Prev 162 0 R
+ /Parent 142 0 R
+ /Prev 159 0 R
/Title (Appendix: custom annotation objects) >>
endobj
-% 'R164': class PDFPages
-164 0 obj
+% 'R161': class PDFPages
+161 0 obj
% page tree
<< /Count 26
- /Kids [ 50 0 R
+ /Kids [ 48 0 R
+ 58 0 R
60 0 R
- 62 0 R
- 63 0 R
- 74 0 R
- 77 0 R
- 82 0 R
+ 61 0 R
+ 72 0 R
+ 75 0 R
+ 80 0 R
+ 84 0 R
86 0 R
- 88 0 R
- 95 0 R
+ 93 0 R
+ 102 0 R
104 0 R
- 106 0 R
- 115 0 R
+ 113 0 R
+ 114 0 R
+ 116 0 R
117 0 R
- 118 0 R
- 120 0 R
+ 119 0 R
123 0 R
- 126 0 R
- 127 0 R
+ 125 0 R
+ 128 0 R
130 0 R
+ 132 0 R
133 0 R
- 134 0 R
135 0 R
138 0 R
- 140 0 R
- 141 0 R ]
+ 139 0 R ]
/Type /Pages >>
endobj
-% 'R165': class PDFStream
-165 0 obj
+% 'R162': class PDFStream
+162 0 obj
% page stream
-<< /Length 9202 >>
+<< /Length 9279 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
@@ -2759,7 +2709,7 @@ q
1 0 0 1 91.03937 3 cm
q
0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (July 2010) Tj T* ET
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (August 2010) Tj T* ET
Q
Q
q
@@ -2886,27 +2836,13 @@ BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Contents) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 176.0236 cm
+1 0 0 1 62.69291 194.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
-1 0 0 1 0 327 cm
-q
-BT 1 0 0 1 0 4.82 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Introduction) Tj T* ET
-Q
-Q
-q
-1 0 0 1 397.8898 327 cm
-q
-0 0 .501961 rg
-0 0 .501961 RG
-BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 66.44 0 Td (1) Tj T* -66.44 0 Td ET
-Q
-Q
-q
1 0 0 1 0 309 cm
q
-BT 1 0 0 1 0 4.82 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (From scripts to interactive applications) Tj T* ET
+BT 1 0 0 1 0 4.82 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Introduction) Tj T* ET
Q
Q
q
@@ -2914,13 +2850,13 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 66.44 0 Td (2) Tj T* -66.44 0 Td ET
+BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 66.44 0 Td (1) Tj T* -66.44 0 Td ET
Q
Q
q
1 0 0 1 0 291 cm
q
-BT 1 0 0 1 0 4.82 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Testing a plac application) Tj T* ET
+BT 1 0 0 1 0 4.82 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (From scripts to interactive applications) Tj T* ET
Q
Q
q
@@ -2928,13 +2864,13 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 66.44 0 Td (3) Tj T* -66.44 0 Td ET
+BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 66.44 0 Td (2) Tj T* -66.44 0 Td ET
Q
Q
q
1 0 0 1 0 273 cm
q
-BT 1 0 0 1 0 4.82 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Plac easy tests) Tj T* ET
+BT 1 0 0 1 0 4.82 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Testing a plac application) Tj T* ET
Q
Q
q
@@ -2942,13 +2878,13 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 66.44 0 Td (5) Tj T* -66.44 0 Td ET
+BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 66.44 0 Td (3) Tj T* -66.44 0 Td ET
Q
Q
q
1 0 0 1 0 255 cm
q
-BT 1 0 0 1 0 4.82 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Plac batch scripts) Tj T* ET
+BT 1 0 0 1 0 4.82 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Plac easy tests) Tj T* ET
Q
Q
q
@@ -2956,13 +2892,13 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 66.44 0 Td (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 (5) Tj T* -66.44 0 Td ET
Q
Q
q
1 0 0 1 0 237 cm
q
-BT 1 0 0 1 0 4.82 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Implementing subcommands) Tj T* ET
+BT 1 0 0 1 0 4.82 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Plac batch scripts) Tj T* ET
Q
Q
q
@@ -2970,13 +2906,13 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 66.44 0 Td (7) Tj T* -66.44 0 Td ET
+BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 66.44 0 Td (6) Tj T* -66.44 0 Td ET
Q
Q
q
1 0 0 1 0 219 cm
q
-BT 1 0 0 1 0 4.82 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Readline support) Tj T* ET
+BT 1 0 0 1 0 4.82 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Implementing subcommands) Tj T* ET
Q
Q
q
@@ -2984,13 +2920,13 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 66.44 0 Td (9) 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
1 0 0 1 0 201 cm
q
-BT 1 0 0 1 0 4.82 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (The plac runner) Tj T* ET
+BT 1 0 0 1 0 4.82 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Readline support) Tj T* ET
Q
Q
q
@@ -2998,13 +2934,13 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 60.88 0 Td (11) Tj T* -60.88 0 Td ET
+BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 66.44 0 Td (9) Tj T* -66.44 0 Td ET
Q
Q
q
1 0 0 1 0 183 cm
q
-BT 1 0 0 1 0 4.82 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Multiline support and Emacs integration) Tj T* ET
+BT 1 0 0 1 0 4.82 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (The plac runner) Tj T* ET
Q
Q
q
@@ -3012,7 +2948,7 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 60.88 0 Td (13) Tj T* -60.88 0 Td ET
+BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 60.88 0 Td (11) Tj T* -60.88 0 Td ET
Q
Q
q
@@ -3026,7 +2962,7 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 60.88 0 Td (14) Tj T* -60.88 0 Td ET
+BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 60.88 0 Td (15) Tj T* -60.88 0 Td ET
Q
Q
q
@@ -3040,7 +2976,7 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 60.88 0 Td (16) Tj T* -60.88 0 Td ET
+BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 60.88 0 Td (17) Tj T* -60.88 0 Td ET
Q
Q
q
@@ -3054,7 +2990,7 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 60.88 0 Td (17) Tj T* -60.88 0 Td ET
+BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 60.88 0 Td (18) Tj T* -60.88 0 Td ET
Q
Q
q
@@ -3068,7 +3004,7 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 60.88 0 Td (18) Tj T* -60.88 0 Td ET
+BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 60.88 0 Td (19) Tj T* -60.88 0 Td ET
Q
Q
q
@@ -3110,7 +3046,7 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 60.88 0 Td (21) Tj T* -60.88 0 Td ET
+BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 60.88 0 Td (22) Tj T* -60.88 0 Td ET
Q
Q
q
@@ -3138,7 +3074,7 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 60.88 0 Td (24) Tj T* -60.88 0 Td ET
+BT 1 0 0 1 0 4.82 Tm /F2 10 Tf 12 TL 60.88 0 Td (25) Tj T* -60.88 0 Td ET
Q
Q
q
@@ -3159,18 +3095,24 @@ q
Q
Q
q
-1 0 0 1 62.69291 143.0236 cm
+1 0 0 1 62.69291 161.0236 cm
q
BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Introduction) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 101.0236 cm
+1 0 0 1 62.69291 119.0236 cm
q
BT 1 0 0 1 0 28.82 Tm .539036 Tw 12 TL /F1 10 Tf 0 0 0 rg (One of the design goals of ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (is to make it dead easy to write a scriptable and testable interface for an) Tj T* 0 Tw .813876 Tw (application. You can use ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (whenever you have an API with strings in input and strings in output, and) Tj T* 0 Tw (that includes a ) Tj /F5 10 Tf (huge ) Tj /F1 10 Tf (domain of applications.) Tj T* ET
Q
Q
q
+1 0 0 1 62.69291 89.02362 cm
+q
+BT 1 0 0 1 0 16.82 Tm 1.756651 Tw 12 TL /F1 10 Tf 0 0 0 rg (A string-oriented interface is a scriptable interface by construction. That means that you can define a ) Tj T* 0 Tw .918735 Tw (command language for your application and that it is possible to write scripts which are interpretable by) Tj T* 0 Tw ET
+Q
+Q
+q
1 0 0 1 56.69291 56.69291 cm
q
0 0 0 rg
@@ -3181,56 +3123,56 @@ Q
endstream
endobj
-% 'R166': class PDFStream
-166 0 obj
+% 'R163': class PDFStream
+163 0 obj
% page stream
-<< /Length 5450 >>
+<< /Length 5305 >>
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 753.0236 cm
q
-BT 1 0 0 1 0 28.82 Tm 1.756651 Tw 12 TL /F1 10 Tf 0 0 0 rg (A string-oriented interface is a scriptable interface by construction. That means that you can define a) Tj T* 0 Tw .918735 Tw (command language for your application and that it is possible to write scripts which are interpretable by) Tj T* 0 Tw 0 0 .501961 rg (plac ) Tj 0 0 0 rg (and can be run as batch scripts.) Tj T* ET
+BT 1 0 0 1 0 4.82 Tm 12 TL /F1 10 Tf 0 0 .501961 rg (plac ) Tj 0 0 0 rg (and can be run as batch scripts.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 687.0236 cm
+1 0 0 1 62.69291 711.0236 cm
q
BT 1 0 0 1 0 28.82 Tm .444987 Tw 12 TL /F1 10 Tf 0 0 0 rg (Actually, at the most general level, you can see ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (as a generic tool to write domain specific languages) Tj T* 0 Tw .107209 Tw (\(DSL\). With ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (you can test your application interactively as well as with batch scripts, and even with the) Tj T* 0 Tw (analogous of Python doctests for your defined language.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 621.0236 cm
+1 0 0 1 62.69291 645.0236 cm
q
BT 1 0 0 1 0 52.82 Tm .694104 Tw 12 TL /F1 10 Tf 0 0 0 rg (You can easily replace the ) Tj /F4 10 Tf (cmd ) Tj /F1 10 Tf (module of the standard library and you could easily write an application) Tj T* 0 Tw 2.271751 Tw (like ) Tj 0 0 .501961 rg (twill ) Tj 0 0 0 rg (with ) Tj 0 0 .501961 rg (plac) Tj 0 0 0 rg (. Or you could use it to script your building procedure. ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (also supports parallel) Tj T* 0 Tw .907765 Tw (execution of multiple commands and can be used as task manager and monitor. It is also quite easy to) Tj T* 0 Tw 1.483488 Tw (build a GUI or a Web application on top of ) Tj 0 0 .501961 rg (plac) Tj 0 0 0 rg (. When speaking of things you can do with ) Tj 0 0 .501961 rg (plac) Tj 0 0 0 rg (, your) Tj T* 0 Tw (imagination is the only limit!) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 588.0236 cm
+1 0 0 1 62.69291 612.0236 cm
q
BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (From scripts to interactive applications) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 534.0236 cm
+1 0 0 1 62.69291 558.0236 cm
q
BT 1 0 0 1 0 40.82 Tm 1.300751 Tw 12 TL /F1 10 Tf 0 0 0 rg (Command-line scripts have many advantages, but they are no substitute for interactive applications. In) Tj T* 0 Tw .088171 Tw (particular, if you have a script with a large startup time which must be run multiple times, it is best to turn it) Tj T* 0 Tw 4.582126 Tw (into an interactive application, so that the startup is performed only once. ) Tj /F4 10 Tf (plac ) Tj /F1 10 Tf (provides an) Tj T* 0 Tw /F4 10 Tf (Interpreter ) Tj /F1 10 Tf (class just for this purpose.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 504.0236 cm
+1 0 0 1 62.69291 528.0236 cm
q
BT 1 0 0 1 0 16.82 Tm 1.293984 Tw 12 TL /F1 10 Tf 0 0 0 rg (The ) Tj /F4 10 Tf (Interpreter ) Tj /F1 10 Tf (class wraps the main function of a script and provides an ) Tj /F4 10 Tf (.interact ) Tj /F1 10 Tf (method to) Tj T* 0 Tw (start an interactive interpreter reading commands from the console.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 474.0236 cm
+1 0 0 1 62.69291 498.0236 cm
q
BT 1 0 0 1 0 16.82 Tm 1.49436 Tw 12 TL /F1 10 Tf 0 0 0 rg (For instance, you can define an interactive interpreter on top of the ) Tj /F4 10 Tf (ishelve ) Tj /F1 10 Tf (script introduced in the) Tj T* 0 Tw 0 0 .501961 rg (basic documentation ) Tj 0 0 0 rg (as follows:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 224.8236 cm
+1 0 0 1 62.69291 248.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -3251,13 +3193,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 180.8236 cm
+1 0 0 1 62.69291 204.8236 cm
q
BT 1 0 0 1 0 28.82 Tm 2.200651 Tw 12 TL /F1 10 Tf 0 0 0 rg (A trick has been used here: the ishelve command-line interface has been hidden inside an external) Tj T* 0 Tw .917674 Tw (interface. They are distinct: for instance the external interface recognizes the ) Tj /F4 10 Tf (-h/--help ) Tj /F1 10 Tf (flag whereas) Tj T* 0 Tw (the internal interface only recognizes the ) Tj /F4 10 Tf (.help ) Tj /F1 10 Tf (command:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 147.6236 cm
+1 0 0 1 62.69291 171.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -3288,11 +3230,11 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 48 re B*
+n -6 -6 468.6898 72 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 29.71 Tm /F4 10 Tf 12 TL (usage: shelve_interpreter.py [-h] [-interactive]) Tj T* ( [subcommands [subcommands ...]]) Tj T* T* ET
+BT 1 0 0 1 0 53.71 Tm /F4 10 Tf 12 TL (usage: shelve_interpreter.py [-h] [-interactive]) Tj T* ( [subcommands [subcommands ...]]) Tj T* T* ( This script works both interactively and non-interactively.) Tj T* ( Use .help to see the internal commands.) Tj T* ET
Q
Q
Q
@@ -3309,14 +3251,14 @@ Q
endstream
endobj
-% 'R167': class PDFStream
-167 0 obj
+% 'R164': class PDFStream
+164 0 obj
% page stream
-<< /Length 4041 >>
+<< /Length 4183 >>
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 655.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -3326,25 +3268,25 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 132 re B*
+n -6 -6 468.6898 108 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 113.71 Tm /F4 10 Tf 12 TL ( This script works both interactively and non-interactively.) Tj T* ( Use .help to see the internal commands.) Tj T* ( ) Tj T* T* (positional arguments:) Tj T* ( subcommands the commands of the underlying ishelve interpreter) Tj T* T* (optional arguments:) Tj T* ( -h, --help show this help message and exit) Tj T* ( -interactive start interactive interface) Tj T* ET
+BT 1 0 0 1 0 89.71 Tm /F4 10 Tf 12 TL ( ) Tj T* T* (positional arguments:) Tj T* ( subcommands the commands of the underlying ishelve interpreter) Tj T* T* (optional arguments:) Tj T* ( -h, --help show this help message and exit) Tj T* ( -interactive start interactive interface) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 611.8236 cm
+1 0 0 1 62.69291 635.8236 cm
q
0 0 0 rg
BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (Thanks to this ingenuous trick, the script can be run both interactively and non-interactively:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 566.6236 cm
+1 0 0 1 62.69291 590.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -3365,14 +3307,14 @@ Q
Q
Q
q
-1 0 0 1 62.69291 546.6236 cm
+1 0 0 1 62.69291 570.6236 cm
q
0 0 0 rg
BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (Here is an usage session:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 261.4236 cm
+1 0 0 1 62.69291 285.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -3392,31 +3334,37 @@ Q
Q
Q
q
-1 0 0 1 62.69291 193.4236 cm
+1 0 0 1 62.69291 217.4236 cm
q
BT 1 0 0 1 0 52.82 Tm .256412 Tw 12 TL /F1 10 Tf 0 0 0 rg (The ) Tj /F4 10 Tf (.interact ) Tj /F1 10 Tf (method reads commands from the console and send them to the underlying interpreter,) Tj T* 0 Tw .065984 Tw (until the user send a CTRL-D command \(CTRL-Z in Windows\). There is a default argument ) Tj /F4 10 Tf (prompt='i) Tj (>) Tj T* 0 Tw .41832 Tw (' ) Tj /F1 10 Tf (which can be used to change the prompt. The text displayed at the beginning of the interactive session) Tj T* 0 Tw 1.407126 Tw (is the docstring of the main function. ) Tj /F4 10 Tf (plac ) Tj /F1 10 Tf (also understands command abbreviations: in this example) Tj T* 0 Tw /F4 10 Tf (del ) Tj /F1 10 Tf (is an abbreviation for ) Tj /F4 10 Tf (delete) Tj /F1 10 Tf (. In case of ambiguous abbreviations ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (raises a ) Tj /F4 10 Tf (NameError) Tj /F1 10 Tf (.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 163.4236 cm
+1 0 0 1 62.69291 187.4236 cm
q
BT 1 0 0 1 0 16.82 Tm .847045 Tw 12 TL /F1 10 Tf 0 0 0 rg (Finally I must notice that the ) Tj /F4 10 Tf (plac.Interpreter ) Tj /F1 10 Tf (is available only if you are using a recent version of) Tj T* 0 Tw (Python \() Tj (>) Tj (= 2.5\), because it is a context manager object which uses extended generators internally.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 130.4236 cm
+1 0 0 1 62.69291 154.4236 cm
q
BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Testing a plac application) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 100.4236 cm
+1 0 0 1 62.69291 124.4236 cm
q
0 0 0 rg
BT 1 0 0 1 0 16.82 Tm /F1 10 Tf 12 TL 3.034269 Tw (You can conveniently test your application in interactive mode. However manual testing is a poor) Tj T* 0 Tw (substitute for automatic testing.) Tj T* ET
Q
Q
q
+1 0 0 1 62.69291 106.4236 cm
+q
+BT 1 0 0 1 0 4.82 Tm 12 TL /F1 10 Tf 0 0 0 rg (In principle, one could write automatic tests for the ) Tj /F4 10 Tf (ishelve ) Tj /F1 10 Tf (application by using ) Tj /F4 10 Tf (plac.call ) Tj /F1 10 Tf (directly:) Tj T* ET
+Q
+Q
+q
1 0 0 1 56.69291 56.69291 cm
q
0 0 0 rg
@@ -3427,20 +3375,14 @@ Q
endstream
endobj
-% 'R168': class PDFStream
-168 0 obj
+% 'R165': class PDFStream
+165 0 obj
% page stream
-<< /Length 5561 >>
+<< /Length 5294 >>
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
-BT 1 0 0 1 0 4.82 Tm 12 TL /F1 10 Tf 0 0 0 rg (In principle, one could write automatic tests for the ) Tj /F4 10 Tf (ishelve ) Tj /F1 10 Tf (application by using ) Tj /F4 10 Tf (plac.call ) Tj /F1 10 Tf (directly:) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 587.8236 cm
+1 0 0 1 62.69291 607.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -3461,19 +3403,19 @@ Q
Q
Q
q
-1 0 0 1 62.69291 543.8236 cm
+1 0 0 1 62.69291 563.8236 cm
q
BT 1 0 0 1 0 28.82 Tm .390651 Tw 12 TL /F1 10 Tf 0 0 0 rg (However, using ) Tj /F4 10 Tf (plac.call ) Tj /F1 10 Tf (is not especially nice. The big issue is that ) Tj /F4 10 Tf (plac.call ) Tj /F1 10 Tf (responds to invalid) Tj T* 0 Tw 1.249987 Tw (input by printing an error message on stderr and by raising a ) Tj /F4 10 Tf (SystemExit) Tj /F1 10 Tf (: this is certainly not a nice) Tj T* 0 Tw (thing to do in a test.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 501.8236 cm
+1 0 0 1 62.69291 521.8236 cm
q
BT 1 0 0 1 0 28.82 Tm 1.616457 Tw 12 TL /F1 10 Tf 0 0 0 rg (As a consequence of this behavior it is impossible to test for invalid commands, unless you wrap the) Tj T* 0 Tw .259985 Tw /F4 10 Tf (SystemExit ) Tj /F1 10 Tf (exception by hand each time \(a possibly you do something with the error message in stderr) Tj T* 0 Tw (too\). Luckily, ) Tj /F4 10 Tf (plac ) Tj /F1 10 Tf (offers a better testing support through the ) Tj /F4 10 Tf (check ) Tj /F1 10 Tf (method of ) Tj /F4 10 Tf (Interpreter ) Tj /F1 10 Tf (objects:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 348.6236 cm
+1 0 0 1 62.69291 368.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -3494,28 +3436,28 @@ Q
Q
Q
q
-1 0 0 1 62.69291 292.6236 cm
+1 0 0 1 62.69291 312.6236 cm
q
BT 1 0 0 1 0 40.82 Tm 6.299974 Tw 12 TL /F1 10 Tf 0 0 0 rg (The method ) Tj /F4 10 Tf (.check\(given_input, expected_output\) ) Tj /F1 10 Tf (works on strings and raises an) Tj T* 0 Tw .971318 Tw /F4 10 Tf (AssertionError ) Tj /F1 10 Tf (if the output produced by the interpreter is different from the expected output for the) Tj T* 0 Tw 2.186905 Tw (given input. Notice that ) Tj /F4 10 Tf (AssertionError ) Tj /F1 10 Tf (is catched by tools like ) Tj /F4 10 Tf (py.test ) Tj /F1 10 Tf (and ) Tj /F4 10 Tf (nosetests ) Tj /F1 10 Tf (and) Tj T* 0 Tw (actually ) Tj /F4 10 Tf (plac ) Tj /F1 10 Tf (tests are intended to be run with such tools.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 238.6236 cm
+1 0 0 1 62.69291 258.6236 cm
q
BT 1 0 0 1 0 40.82 Tm .239984 Tw 12 TL /F1 10 Tf 0 0 0 rg (Interpreters offer a minor syntactic advantage with respect to calling ) Tj /F4 10 Tf (plac.call ) Tj /F1 10 Tf (directly, but they offer a) Tj T* 0 Tw .96748 Tw /F5 10 Tf (major ) Tj /F1 10 Tf (semantic advantage when things go wrong \(read exceptions\): an ) Tj /F4 10 Tf (Interpreter ) Tj /F1 10 Tf (object internally) Tj T* 0 Tw 1.181318 Tw (invokes something like ) Tj /F4 10 Tf (plac.call) Tj /F1 10 Tf (, but it wraps all exceptions, so that ) Tj /F4 10 Tf (i.check ) Tj /F1 10 Tf (is guaranteed not to) Tj T* 0 Tw (raise any exception except ) Tj /F4 10 Tf (AssertionError) Tj /F1 10 Tf (.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 220.6236 cm
+1 0 0 1 62.69291 240.6236 cm
q
BT 1 0 0 1 0 4.82 Tm 12 TL /F1 10 Tf 0 0 0 rg (Even the ) Tj /F4 10 Tf (SystemExit ) Tj /F1 10 Tf (exception is captured and you can write your test as) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 214.6236 cm
+1 0 0 1 62.69291 234.6236 cm
Q
q
-1 0 0 1 62.69291 202.6236 cm
+1 0 0 1 62.69291 222.6236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
BT 1 0 0 1 0 2 Tm T* ET
@@ -3530,17 +3472,17 @@ q
Q
Q
q
-1 0 0 1 62.69291 202.6236 cm
+1 0 0 1 62.69291 222.6236 cm
Q
q
-1 0 0 1 62.69291 184.6236 cm
+1 0 0 1 62.69291 204.6236 cm
q
0 0 0 rg
BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (without risk of exiting from the Python interpreter.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 142.6236 cm
+1 0 0 1 62.69291 162.6236 cm
q
BT 1 0 0 1 0 28.82 Tm 1.422651 Tw 12 TL /F1 10 Tf 0 0 0 rg (There is a second advantage of interpreters: if the main function contains some initialization code and) Tj T* 0 Tw .454651 Tw (finalization code \() Tj /F4 10 Tf (__enter__ ) Tj /F1 10 Tf (and ) Tj /F4 10 Tf (__exit__ ) Tj /F1 10 Tf (functions\) they will be run only once at the beginning and) Tj T* 0 Tw (at the end of the interpreter loop. ) Tj /F4 10 Tf (plac.call ) Tj /F1 10 Tf (instead ignores the initialization/finalization code.) Tj T* ET
Q
@@ -3556,8 +3498,8 @@ Q
endstream
endobj
-% 'R169': class PDFStream
-169 0 obj
+% 'R166': class PDFStream
+166 0 obj
% page stream
<< /Length 6149 >>
stream
@@ -3674,8 +3616,8 @@ Q
endstream
endobj
-% 'R170': class PDFStream
-170 0 obj
+% 'R167': class PDFStream
+167 0 obj
% page stream
<< /Length 5253 >>
stream
@@ -3795,8 +3737,8 @@ Q
endstream
endobj
-% 'R171': class PDFStream
-171 0 obj
+% 'R168': class PDFStream
+168 0 obj
% page stream
<< /Length 4319 >>
stream
@@ -3890,8 +3832,8 @@ Q
endstream
endobj
-% 'R172': class PDFStream
-172 0 obj
+% 'R169': class PDFStream
+169 0 obj
% page stream
<< /Length 4289 >>
stream
@@ -3967,8 +3909,8 @@ Q
endstream
endobj
-% 'R173': class PDFStream
-173 0 obj
+% 'R170': class PDFStream
+170 0 obj
% page stream
<< /Length 3743 >>
stream
@@ -4042,8 +3984,8 @@ Q
endstream
endobj
-% 'R174': class PDFStream
-174 0 obj
+% 'R171': class PDFStream
+171 0 obj
% page stream
<< /Length 4535 >>
stream
@@ -4144,8 +4086,8 @@ Q
endstream
endobj
-% 'R175': class PDFStream
-175 0 obj
+% 'R172': class PDFStream
+172 0 obj
% page stream
<< /Length 5760 >>
stream
@@ -4326,8 +4268,8 @@ Q
endstream
endobj
-% 'R176': class PDFStream
-176 0 obj
+% 'R173': class PDFStream
+173 0 obj
% page stream
<< /Length 4832 >>
stream
@@ -4518,44 +4460,53 @@ Q
endstream
endobj
-% 'R177': class PDFStream
-177 0 obj
+% 'R174': class PDFStream
+174 0 obj
% page stream
-<< /Length 4876 >>
+<< /Length 5036 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
1 0 0 1 62.69291 741.0236 cm
q
-BT 1 0 0 1 0 16.82 Tm .18936 Tw 12 TL /F1 10 Tf 0 0 0 rg (Notice that it non-interactive mode the runner just invokes ) Tj /F4 10 Tf (plac.call ) Tj /F1 10 Tf (on the ) Tj /F4 10 Tf (main ) Tj /F1 10 Tf (object of the Python) Tj T* 0 Tw (module.) Tj T* ET
+BT 1 0 0 1 0 16.82 Tm .01561 Tw 12 TL /F1 10 Tf 0 0 0 rg (Notice that in non-interactive mode the runner just invokes ) Tj /F4 10 Tf (plac.call ) Tj /F1 10 Tf (on the ) Tj /F4 10 Tf (main ) Tj /F1 10 Tf (object of the Python) Tj T* 0 Tw (module.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 708.0236 cm
+1 0 0 1 62.69291 735.0236 cm
+Q
q
-BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Multiline support and Emacs integration) Tj T* ET
+1 0 0 1 62.69291 88.86614 cm
+0 0 0 rg
+BT /F3 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 618.33 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (Multiline support and Emacs integration) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 594.0236 cm
+1 0 0 1 20 504.33 cm
q
-BT 1 0 0 1 0 100.82 Tm 1.61436 Tw 12 TL /F1 10 Tf 0 0 .501961 rg (plac ) Tj 0 0 0 rg (is optimized for the simplest use case and by default it provide support for simple command-line) Tj T* 0 Tw .734488 Tw (languages where a command take a single line. This is the simplest case: it is easy to keep track of the) Tj T* 0 Tw .012846 Tw (line number and to print it in the error message, if there is some error in a ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (script. Starting from release) Tj T* 0 Tw .639985 Tw (0.7 ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (is beginning to support multiline input: it is now possible to define command-line languages with) Tj T* 0 Tw .504692 Tw (commands spanning multiple lines. The topical use case is the implementation of a tool to interact with a) Tj T* 0 Tw 1.33311 Tw (relational database: the tool must be able to send complex SQL queries spanning multiple lines to the) Tj T* 0 Tw 11.55398 Tw (backend. To support multiline input the ) Tj /F4 10 Tf (Interpreter ) Tj /F1 10 Tf (class provides a method) Tj T* 0 Tw 4.086627 Tw /F4 10 Tf (multiline\(stdin=sys.stdin, terminator=';', verbose=False\) ) Tj /F1 10 Tf (which reads input from) Tj T* 0 Tw /F4 10 Tf (stdin ) Tj /F1 10 Tf (until the terminator character \(by default a semicolon\) is reached.) Tj T* ET
+BT 1 0 0 1 0 100.82 Tm .36436 Tw 12 TL /F1 10 Tf 0 0 .501961 rg (plac ) Tj 0 0 0 rg (is optimized for the simplest use case and by default it provide support for simple command-line) Tj T* 0 Tw .598409 Tw (languages where a command take a single line. This is the simplest case: it is easy to keep track of) Tj T* 0 Tw 1.096988 Tw (the line number and to print it in the error message, if there is some error in a ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (script. Starting) Tj T* 0 Tw .08561 Tw (from release 0.7 ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (is beginning to support multiline input: it is now possible to define command-line) Tj T* 0 Tw .970697 Tw (languages with commands spanning multiple lines. The topical use case is the implementation of a) Tj T* 0 Tw 2.41061 Tw (tool to interact with a relational database: the tool must be able to send complex SQL queries) Tj T* 0 Tw .636905 Tw (spanning multiple lines to the backend. To support multiline input the ) Tj /F4 10 Tf (Interpreter ) Tj /F1 10 Tf (class provides) Tj T* 0 Tw .678294 Tw (a method ) Tj /F4 10 Tf (multiline\(stdin=sys.stdin, terminator=';', verbose=False\) ) Tj /F1 10 Tf (which reads) Tj T* 0 Tw (input from ) Tj /F4 10 Tf (stdin ) Tj /F1 10 Tf (until the terminator character \(by default a semicolon\) is reached.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 516.0236 cm
+1 0 0 1 20 426.33 cm
q
-BT 1 0 0 1 0 64.82 Tm 1.052651 Tw 12 TL /F1 10 Tf 0 0 0 rg (Since the Python readline module does not expose the multiline functionality of the underlying C library) Tj T* 0 Tw 1.453516 Tw (\(which is there\), ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (multiline mode does not have readline functionality. This is not a big deal really,) Tj T* 0 Tw .09881 Tw (because if you are writing multiple line commands you don't really want to type them at the command-line.) Tj T* 0 Tw .218323 Tw (It is much better to use a real editor to type them, and to call ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (from the editor. Since I use Emacs I will) Tj T* 0 Tw 2.072339 Tw (give the recipe to integrate Emacs with ) Tj 0 0 .501961 rg (plac) Tj 0 0 0 rg (: something equivalent can be done for vi and for other) Tj T* 0 Tw (editors/IDEs.) Tj T* ET
+BT 1 0 0 1 0 64.82 Tm 1.842126 Tw 12 TL /F1 10 Tf 0 0 0 rg (Since the Python readline module does not expose the multiline functionality of the underlying C) Tj T* 0 Tw .244692 Tw (library \(which is there\), ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (multiline mode does not have readline functionality. This is not a big deal) Tj T* 0 Tw 1.210574 Tw (really, because if you are writing multiple line commands you don't really want to type them at the) Tj T* 0 Tw 1.299988 Tw (command-line. It is much better to use a real editor to type them, and to call ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (from the editor.) Tj T* 0 Tw .962927 Tw (Since I use Emacs I will give the recipe to integrate Emacs with ) Tj 0 0 .501961 rg (plac) Tj 0 0 0 rg (: something equivalent can be) Tj T* 0 Tw (done for vi and for other editors/IDEs.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 474.0236 cm
+1 0 0 1 20 384.33 cm
q
-BT 1 0 0 1 0 28.82 Tm 1.177633 Tw 12 TL /F1 10 Tf 0 0 0 rg (The multiline mode can be enabled by invoking the ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (runner with the ) Tj /F4 10 Tf (-m ) Tj /F1 10 Tf (option. Since the multiline) Tj T* 0 Tw .262488 Tw (mode is intended for use with Emacs in inferior mode, it does not print any prompt. Here is an example of) Tj T* 0 Tw (usage:) Tj T* ET
+BT 1 0 0 1 0 28.82 Tm .001163 Tw 12 TL /F1 10 Tf 0 0 0 rg (The multiline mode can be enabled by invoking the ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (runner with the ) Tj /F4 10 Tf (-m ) Tj /F1 10 Tf (option. Since the multiline) Tj T* 0 Tw 2.052209 Tw (mode is intended for use with Emacs in inferior mode, it does not print any prompt. Here is an) Tj T* 0 Tw (example of usage:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 392.8236 cm
+1 0 0 1 20 303.13 cm
q
q
1 0 0 1 0 0 cm
@@ -4565,7 +4516,7 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 72 re B*
+n -6 -6 442.6898 72 re B*
Q
q
0 0 0 rg
@@ -4576,31 +4527,33 @@ Q
Q
Q
q
-1 0 0 1 62.69291 372.8236 cm
+1 0 0 1 20 277.13 cm
q
BT 1 0 0 1 0 4.82 Tm 12 TL /F1 10 Tf 0 0 0 rg (To integrate ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (with Emacs, enters the following lines in your .emacs:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 99.62362 cm
+1 0 0 1 20 0 cm
q
q
-1 0 0 1 0 0 cm
+.970887 0 0 .970887 0 0 cm
q
-1 0 0 1 6.6 6.6 cm
+1 0 0 1 6.6 6.797904 cm
q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 264 re B*
+n -6 -6 456 276 re B*
Q
q
-0 0 0 rg
-BT 1 0 0 1 0 245.71 Tm /F4 10 Tf 12 TL (;;; Emacs-plac integration: add the following to your .emacs) Tj T* T* (\(define-generic-mode 'plac-mode) Tj T* ( '\("#"\) ; comment chars) Tj T* ( '\(\); highlighted commands) Tj T* ( nil) Tj T* ( '\(".plac"\); file extensions) Tj T* ( nil\)) Tj T* ( ) Tj T* (\(add-hook 'plac-mode-hook \(lambda \(\) \(local-set-key [f4] 'plac-start\)\)\)) Tj T* (\(add-hook 'plac-mode-hook \(lambda \(\) \(local-set-key [f5] 'plac-send\)\)\)) Tj T* (\(add-hook 'plac-mode-hook \(lambda \(\) \(local-set-key [f6] 'plac-stop\)\)\)) Tj T* T* (\(defvar *plac-process* nil\)) Tj T* T* (\(defun plac-start \(\)) Tj T* ( "Start an inferior plac process by inferring the script to use from the ) Tj T* ( shebang line") Tj T* ( \(interactive\)) Tj T* ( \(let \(\(shebang-line ) Tj T* ( \(save-excursion) Tj T* ET
+BT 1 0 0 1 0 257.71 Tm 12 TL /F4 10 Tf 0 0 0 rg (;;; Emacs-plac integration: add the following to your .emacs) Tj T* T* (\(define-generic-mode 'plac-mode) Tj T* ( '\("#"\) ; comment chars) Tj T* ( '\(\); highlighted commands) Tj T* ( nil) Tj T* ( '\(".plac"\); file extensions) Tj T* ( nil\)) Tj T* ( ) Tj T* (\(add-hook 'plac-mode-hook \(lambda \(\) \(local-set-key [f4] 'plac-start\)\)\)) Tj T* (\(add-hook 'plac-mode-hook \(lambda \(\) \(local-set-key [f5] 'plac-send\)\)\)) Tj T* (\(add-hook 'plac-mode-hook \(lambda \(\) \(local-set-key [f6] 'plac-stop\)\)\)) Tj T* T* (\(defconst terminator 59\); ASCII code for the semicolon) Tj T* (\(defvar *plac-process* nil\)) Tj T* T* (\(defun plac-start \(\)) Tj T* ( "Start an inferior plac process by inferring the script to use from the ) Tj T* ( shebang line") Tj T* ( \(interactive\)) Tj T* ( \(let \(\(shebang-line ) Tj T* ( \(save-excursion) Tj T* ET
+Q
Q
Q
Q
Q
+q
+Q
Q
q
1 0 0 1 56.69291 56.69291 cm
@@ -4613,54 +4566,81 @@ Q
endstream
endobj
-% 'R178': class PDFStream
-178 0 obj
+% 'R175': class PDFStream
+175 0 obj
% page stream
-<< /Length 3216 >>
+<< /Length 3087 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 535.8236 cm
+1 0 0 1 47.6378 159.1303 cm
+0 0 0 rg
+BT /F3 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
q
+1 0 0 1 20 0 cm
q
-1 0 0 1 0 0 cm
q
-1 0 0 1 6.6 6.6 cm
+.90002 0 0 .90002 0 0 cm
+q
+1 0 0 1 6.6 7.333172 cm
q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 228 re B*
+n -6 -6 492 672 re B*
Q
q
-0 0 0 rg
-BT 1 0 0 1 0 209.71 Tm /F4 10 Tf 12 TL ( \(goto-line 1\) \(end-of-line\)) Tj T* ( \(buffer-substring 3 \(point\)\)\)\)\)) Tj T* ( \(if *plac-process* \(princ "plac already started"\)) Tj T* ( \(setq *plac-process*) Tj T* ( \(start-process) Tj T* ( "plac" "*plac*" "plac_runner.py" "-m" shebang-line\)\)\)\)) Tj T* ( \(display-buffer "*plac*"\)\)) Tj T* T* (\(defun plac-send \(\)) Tj T* ( "Send the current region to the inferior plac process") Tj T* ( \(interactive\)) Tj T* ( \(process-send-region *plac-process* \(region-beginning\) \(region-end\)\)\)) Tj T* T* (\(defun plac-stop \(\)) Tj T* ( "Stop the inferior plac process by sending to it an EOF") Tj T* ( \(interactive\)) Tj T* ( \(process-send-eof *plac-process*\)) Tj T* ( \(setq *plac-process* nil\)\)) Tj T* ET
+BT 1 0 0 1 0 653.71 Tm 12 TL /F4 10 Tf 0 0 0 rg ( \(goto-line 1\) \(end-of-line\)) Tj T* ( \(buffer-substring-no-properties 3 \(point\)\)\)\)\)) Tj T* ( \(if *plac-process* \(princ "plac already started"\)) Tj T* ( \(setq *plac-process*) Tj T* ( \(start-process) Tj T* ( "plac" "*plac*" "plac_runner.py" "-m" shebang-line\)\)\)\)) Tj T* ( \(display-buffer "*plac*"\)\)) Tj T* T* (;\(defun plac-send \(\)) Tj T* (; "Send the current region to the inferior plac process") Tj T* (; \(interactive\)) Tj T* (; \(save-excursion \(set-buffer "*plac*"\) \(erase-buffer\)\)) Tj T* (; \(process-send-region *plac-process* \(region-beginning\) \(region-end\)\)\)) Tj T* T* (\(defun current-paragraph-beg-end \(\)) Tj T* ( "Returns the extrema of the current paragraph, delimited by semicolons") Tj T* ( \(interactive\)) Tj T* ( \(save-excursion) Tj T* ( \(let \(\(beg \(save-excursion \(goto-line 2\) \(point\)\)\); skip the shebang) Tj T* ( \(end \(point-max\)\)\)) Tj T* ( ;; go backward) Tj T* ( \(while \() Tj (>) Tj ( \(point\) beg\)) Tj T* ( \(goto-char \(1- \(point\)\)\)) Tj T* ( \(if \(= terminator \(following-char\)\)) Tj T* ( \(setq beg \(point\)\)\)\)) Tj T* ( \(if \(= terminator \(following-char\)\)) Tj T* ( \(setq beg \(1+ beg\)\)\)) Tj T* ( ;; go forward) Tj T* ( \(while \() Tj (<) Tj ( \(point\) end\)) Tj T* ( \(goto-char \(1+ \(point\)\)\)) Tj T* ( \(if \(= 59 \(following-char\)\)) Tj T* ( \(setq end \(point\)\)\)\)) Tj T* ( \(if \(= 59 \(following-char\)\)) Tj T* ( \(setq end \(1+ end\)\)\)) Tj T* ( \(list beg end\)\)\)\)) Tj T* ( ) Tj T* (\(defun plac-send \(\)) Tj T* ( "Send the current region to the inferior plac process") Tj T* ( \(interactive\)) Tj T* ( \(save-excursion \(set-buffer "*plac*"\) \(erase-buffer\)\)) Tj T* ( \(let \(\(p \(apply 'buffer-substring-no-properties \(current-paragraph-beg-end\)\)\)\)) Tj T* ( \(message p\)) Tj T* ( \(process-send-string *plac-process* \(concat p "\\n"\)\)\)\)) Tj T* ( ;\(switch-to-buffer-other-window "*plac*"\)\)\)) Tj T* ( ;\(save-excursion \(set-buffer "*plac*"\) ) Tj T* ( ; \(set-window-start \(selected-window\) 1 nil\)\)\)\)) Tj T* T* (\(defun plac-stop \(\)) Tj T* ( "Stop the inferior plac process by sending to it an EOF") Tj T* ( \(interactive\)) Tj T* ( \(process-send-eof *plac-process*\)) Tj T* ( \(setq *plac-process* nil\)) Tj T* ( "killed *plac-process*"\)) Tj T* T* (\(provide 'plac\)) Tj T* ET
+Q
+Q
Q
Q
Q
+q
+Q
Q
+q
+1 0 0 1 62.69291 159.1303 cm
Q
q
-1 0 0 1 62.69291 502.8236 cm
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 235.3849 0 Td (14) Tj T* -235.3849 0 Td ET
+Q
+Q
+
+endstream
+
+endobj
+% 'R176': class PDFStream
+176 0 obj
+% page stream
+<< /Length 3684 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 744.0236 cm
q
BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (A non class-based example) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 460.8236 cm
+1 0 0 1 62.69291 702.0236 cm
q
BT 1 0 0 1 0 28.82 Tm .907209 Tw 12 TL /F1 10 Tf 0 0 .501961 rg (plac ) Tj 0 0 0 rg (does not force you to use classes to define command containers. Even a simple function can be a) Tj T* 0 Tw 1.796651 Tw (valid command container, it is enough to add to it a ) Tj /F4 10 Tf (.commands ) Tj /F1 10 Tf (attribute and possibly ) Tj /F4 10 Tf (__enter__) Tj T* 0 Tw /F1 10 Tf (and/or ) Tj /F4 10 Tf (__exit__ ) Tj /F1 10 Tf (attributes.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 430.8236 cm
+1 0 0 1 62.69291 672.0236 cm
q
0 0 0 rg
BT 1 0 0 1 0 16.82 Tm /F1 10 Tf 12 TL .327485 Tw (In particular, a Python module is a perfect container of commands. As an example, consider the following) Tj T* 0 Tw (module implementing a fake Version Control System:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 97.62362 cm
+1 0 0 1 62.69291 290.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -4670,35 +4650,30 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 324 re B*
+n -6 -6 468.6898 372 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 305.71 Tm /F4 10 Tf 12 TL ("A Fake Version Control System") Tj T* T* (import plac) Tj T* T* (commands = 'checkout', 'commit', 'status') Tj T* T* (@plac.annotations\(url='url of the source code'\)) Tj T* (def checkout\(url\):) Tj T* ( "A fake checkout command") Tj T* ( return \('checkout ', url\)) Tj T* T* (@plac.annotations\(message=\('commit message', 'option'\)\)) Tj T* (def commit\(message\):) Tj T* ( "A fake commit command") Tj T* ( return \('commit ', message\)) Tj T* T* (@plac.annotations\(quiet=\('summary information', 'flag', 'q'\)\)) Tj T* (def status\(quiet\):) Tj T* ( "A fake status command") Tj T* ( return \('status ', quiet\)) Tj T* T* (def __missing__\(name\):) Tj T* ( return 'Command %r does not exist' % name) Tj T* T* (def __exit__\(etype, exc, tb\):) Tj T* ( "Will be called automatically at the end of the call/cmdloop") Tj T* ET
+BT 1 0 0 1 0 353.71 Tm /F4 10 Tf 12 TL ("A Fake Version Control System") Tj T* T* (import plac) Tj T* T* (commands = 'checkout', 'commit', 'status') Tj T* T* (@plac.annotations\(url='url of the source code'\)) Tj T* (def checkout\(url\):) Tj T* ( "A fake checkout command") Tj T* ( return \('checkout ', url\)) Tj T* T* (@plac.annotations\(message=\('commit message', 'option'\)\)) Tj T* (def commit\(message\):) Tj T* ( "A fake commit command") Tj T* ( return \('commit ', message\)) Tj T* T* (@plac.annotations\(quiet=\('summary information', 'flag', 'q'\)\)) Tj T* (def status\(quiet\):) Tj T* ( "A fake status command") Tj T* ( return \('status ', quiet\)) Tj T* T* (def __missing__\(name\):) Tj T* ( return 'Command %r does not exist' % name) Tj T* T* (def __exit__\(etype, exc, tb\):) Tj T* ( "Will be called automatically at the end of the call/cmdloop") Tj T* ( if etype in \(None, GeneratorExit\): # success) Tj T* ( print\('ok'\)) Tj T* T* (main = __import__\(__name__\) # the module imports itself!) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 56.69291 56.69291 cm
+1 0 0 1 62.69291 246.8236 cm
q
-0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 235.3849 0 Td (14) Tj T* -235.3849 0 Td ET
+BT 1 0 0 1 0 28.82 Tm .431318 Tw 12 TL /F1 10 Tf 0 0 0 rg (Notice that I have defined both an ) Tj /F4 10 Tf (__exit__ ) Tj /F1 10 Tf (hook and a ) Tj /F4 10 Tf (__missing__ ) Tj /F1 10 Tf (hook, invoked for non-existing) Tj T* 0 Tw .592651 Tw (commands. The real trick here is the line ) Tj /F4 10 Tf (main = __import__\(__name__\)) Tj /F1 10 Tf (, which define ) Tj /F4 10 Tf (main ) Tj /F1 10 Tf (to be) Tj T* 0 Tw (an alias for the current module.) Tj T* ET
Q
Q
-
-endstream
-
-endobj
-% 'R179': class PDFStream
-179 0 obj
-% page stream
-<< /Length 4077 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 703.8236 cm
+1 0 0 1 62.69291 216.8236 cm
+q
+BT 1 0 0 1 0 16.82 Tm 1.259986 Tw 12 TL /F1 10 Tf 0 0 0 rg (The ) Tj /F4 10 Tf (vcs ) Tj /F1 10 Tf (module does not contain an ) Tj /F4 10 Tf (if __name__ == '__main__' ) Tj /F1 10 Tf (block, but you can still run it) Tj T* 0 Tw (through the plac runner \(try ) Tj /F4 10 Tf (plac vcs.py -h) Tj /F1 10 Tf (\):) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 99.62362 cm
q
q
1 0 0 1 0 0 cm
@@ -4708,30 +4683,35 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 60 re B*
+n -6 -6 468.6898 108 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 41.71 Tm /F4 10 Tf 12 TL ( if etype in \(None, GeneratorExit\): # success) Tj T* ( print\('ok'\)) Tj T* T* (main = __import__\(__name__\) # the module imports itself!) Tj T* ET
-Q
-Q
+BT 1 0 0 1 0 89.71 Tm /F4 10 Tf 12 TL (usage: plac_runner.py vcs.py [-h] {status,commit,checkout} ...) Tj T* T* (A Fake Version Control System) Tj T* T* (optional arguments:) Tj T* ( -h, --help show this help message and exit) Tj T* T* (subcommands:) Tj T* ET
Q
Q
Q
-q
-1 0 0 1 62.69291 659.8236 cm
-q
-BT 1 0 0 1 0 28.82 Tm .431318 Tw 12 TL /F1 10 Tf 0 0 0 rg (Notice that I have defined both an ) Tj /F4 10 Tf (__exit__ ) Tj /F1 10 Tf (hook and a ) Tj /F4 10 Tf (__missing__ ) Tj /F1 10 Tf (hook, invoked for non-existing) Tj T* 0 Tw .592651 Tw (commands. The real trick here is the line ) Tj /F4 10 Tf (main = __import__\(__name__\)) Tj /F1 10 Tf (, which define ) Tj /F4 10 Tf (main ) Tj /F1 10 Tf (to be) Tj T* 0 Tw (an alias for the current module.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 629.8236 cm
+1 0 0 1 56.69291 56.69291 cm
q
-BT 1 0 0 1 0 16.82 Tm 1.259986 Tw 12 TL /F1 10 Tf 0 0 0 rg (The ) Tj /F4 10 Tf (vcs ) Tj /F1 10 Tf (module does not contain an ) Tj /F4 10 Tf (if __name__ == '__main__' ) Tj /F1 10 Tf (block, but you can still run it) Tj T* 0 Tw (through the plac runner \(try ) Tj /F4 10 Tf (plac vcs.py -h) Tj /F1 10 Tf (\):) Tj T* ET
+0 0 0 rg
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 235.3849 0 Td (15) Tj T* -235.3849 0 Td ET
Q
Q
+
+endstream
+
+endobj
+% 'R177': class PDFStream
+177 0 obj
+% page stream
+<< /Length 3422 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 488.6236 cm
+1 0 0 1 62.69291 727.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -4741,24 +4721,24 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 132 re B*
+n -6 -6 468.6898 36 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 113.71 Tm /F4 10 Tf 12 TL (usage: plac_runner.py vcs.py [-h] {status,commit,checkout} ...) Tj T* T* (A Fake Version Control System) Tj T* T* (optional arguments:) Tj T* ( -h, --help show this help message and exit) Tj T* T* (subcommands:) Tj T* ( {status,commit,checkout}) Tj T* ( -h to get additional help) Tj T* ET
+BT 1 0 0 1 0 17.71 Tm /F4 10 Tf 12 TL ( {status,commit,checkout}) Tj T* ( -h to get additional help) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 468.6236 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 (You can get help for the subcommands by postponing ) Tj /F4 10 Tf (-h ) Tj /F1 10 Tf (after the name of the command:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 351.4236 cm
+1 0 0 1 62.69291 590.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -4779,20 +4759,20 @@ Q
Q
Q
q
-1 0 0 1 62.69291 319.4236 cm
+1 0 0 1 62.69291 558.6236 cm
q
BT 1 0 0 1 0 16.82 Tm 2.064985 Tw 12 TL /F1 10 Tf 0 0 0 rg (Notice how the docstring of the command is automatically shown in usage message, as well as the) Tj T* 0 Tw (documentation for the sub flag ) Tj /F4 10 Tf (-q) Tj /F1 10 Tf (.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 301.4236 cm
+1 0 0 1 62.69291 540.6236 cm
q
0 0 0 rg
BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (Here is an example of a non-interactive session:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 172.2236 cm
+1 0 0 1 62.69291 411.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -4813,14 +4793,14 @@ Q
Q
Q
q
-1 0 0 1 62.69291 152.2236 cm
+1 0 0 1 62.69291 391.4236 cm
q
0 0 0 rg
BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (and here is an interactive session:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 95.02362 cm
+1 0 0 1 62.69291 190.2236 cm
q
q
1 0 0 1 0 0 cm
@@ -4830,85 +4810,65 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 48 re B*
+n -6 -6 468.6898 192 re B*
Q
q
-BT 1 0 0 1 0 29.71 Tm 12 TL /F4 10 Tf 0 0 0 rg ($ plac -i vcs.py) Tj T* (usage: plac_runner.py vcs.py [-h] {status,commit,checkout} ...) Tj T* (i) Tj (>) Tj ( check url) Tj T* ET
+BT 1 0 0 1 0 173.71 Tm 12 TL /F4 10 Tf 0 0 0 rg ($ plac -i vcs.py) Tj T* (usage: plac_runner.py vcs.py [-h] {status,commit,checkout} ...) Tj T* (i) Tj (>) Tj ( check url) Tj T* (checkout) Tj T* (url) Tj T* (i) Tj (>) Tj ( st -q) Tj T* (status) Tj T* (True) Tj T* (i) Tj (>) Tj ( co) Tj T* (commit) Tj T* (None) Tj T* (i) Tj (>) Tj ( sto) Tj T* (Command 'sto' does not exist) Tj T* (i) Tj (>) Tj ( [CTRL-D]) Tj T* (ok) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 56.69291 56.69291 cm
-q
-0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 235.3849 0 Td (15) Tj T* -235.3849 0 Td ET
-Q
-Q
-
-endstream
-
-endobj
-% 'R180': class PDFStream
-180 0 obj
-% page stream
-<< /Length 6171 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
-q
-1 0 0 1 62.69291 607.8236 cm
-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 156 re B*
-Q
+1 0 0 1 62.69291 158.2236 cm
q
-BT 1 0 0 1 0 137.71 Tm 12 TL /F4 10 Tf 0 0 0 rg (checkout) Tj T* (url) Tj T* (i) Tj (>) Tj ( st -q) Tj T* (status) Tj T* (True) Tj T* (i) Tj (>) Tj ( co) Tj T* (commit) Tj T* (None) Tj T* (i) Tj (>) Tj ( sto) Tj T* (Command 'sto' does not exist) Tj T* (i) Tj (>) Tj ( [CTRL-D]) Tj T* (ok) Tj T* ET
-Q
-Q
-Q
+BT 1 0 0 1 0 16.82 Tm 2.986905 Tw 12 TL /F1 10 Tf 0 0 0 rg (Notice the invocation of the ) Tj /F4 10 Tf (__missing__ ) Tj /F1 10 Tf (hook for non-existing commands. Notice also that the) Tj T* 0 Tw /F4 10 Tf (__exit__ ) Tj /F1 10 Tf (hook gets called only in interactive mode.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 575.8236 cm
+1 0 0 1 62.69291 128.2236 cm
q
-BT 1 0 0 1 0 16.82 Tm 2.986905 Tw 12 TL /F1 10 Tf 0 0 0 rg (Notice the invocation of the ) Tj /F4 10 Tf (__missing__ ) Tj /F1 10 Tf (hook for non-existing commands. Notice also that the) Tj T* 0 Tw /F4 10 Tf (__exit__ ) Tj /F1 10 Tf (hook gets called only in interactive mode.) Tj T* ET
+0 0 0 rg
+BT 1 0 0 1 0 16.82 Tm /F1 10 Tf 12 TL 1.614104 Tw (If the commands are completely independent, a module is a good fit for a method container. In other) Tj T* 0 Tw (situations, it is best to use a custom class.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 545.8236 cm
+1 0 0 1 56.69291 56.69291 cm
q
0 0 0 rg
-BT 1 0 0 1 0 16.82 Tm /F1 10 Tf 12 TL 1.614104 Tw (If the commands are completely independent, a module is a good fit for a method container. In other) Tj T* 0 Tw (situations, it is best to use a custom class.) Tj T* ET
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 235.3849 0 Td (16) Tj T* -235.3849 0 Td ET
Q
Q
+
+endstream
+
+endobj
+% 'R178': class PDFStream
+178 0 obj
+% page stream
+<< /Length 5984 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 512.8236 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 (Writing your own plac runner) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 458.8236 cm
+1 0 0 1 62.69291 690.0236 cm
q
BT 1 0 0 1 0 40.82 Tm .167209 Tw 12 TL /F1 10 Tf 0 0 0 rg (The runner included in the ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (distribution is intentionally kept small \(around 50 lines of code\) so that you) Tj T* 0 Tw .081294 Tw (can study it and write your own runner if want to. If you need to go to such level of detail, you should know) Tj T* 0 Tw .42061 Tw (that the most important method of the ) Tj /F4 10 Tf (Interpreter ) Tj /F1 10 Tf (class is the ) Tj /F4 10 Tf (.send ) Tj /F1 10 Tf (method, which takes strings in) Tj T* 0 Tw (input and returns a four-tuple with attributes ) Tj /F4 10 Tf (.str) Tj /F1 10 Tf (, ) Tj /F4 10 Tf (.etype) Tj /F1 10 Tf (, ) Tj /F4 10 Tf (.exc ) Tj /F1 10 Tf (and ) Tj /F4 10 Tf (.tb) Tj /F1 10 Tf (:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 452.8236 cm
+1 0 0 1 62.69291 684.0236 cm
Q
q
-1 0 0 1 62.69291 452.8236 cm
+1 0 0 1 62.69291 684.0236 cm
Q
q
-1 0 0 1 62.69291 434.8236 cm
+1 0 0 1 62.69291 666.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -4928,13 +4888,13 @@ q
Q
Q
q
-1 0 0 1 62.69291 434.8236 cm
+1 0 0 1 62.69291 666.0236 cm
Q
q
-1 0 0 1 62.69291 434.8236 cm
+1 0 0 1 62.69291 666.0236 cm
Q
q
-1 0 0 1 62.69291 416.8236 cm
+1 0 0 1 62.69291 648.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -4954,13 +4914,13 @@ q
Q
Q
q
-1 0 0 1 62.69291 416.8236 cm
+1 0 0 1 62.69291 648.0236 cm
Q
q
-1 0 0 1 62.69291 416.8236 cm
+1 0 0 1 62.69291 648.0236 cm
Q
q
-1 0 0 1 62.69291 398.8236 cm
+1 0 0 1 62.69291 630.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -4980,13 +4940,13 @@ q
Q
Q
q
-1 0 0 1 62.69291 398.8236 cm
+1 0 0 1 62.69291 630.0236 cm
Q
q
-1 0 0 1 62.69291 398.8236 cm
+1 0 0 1 62.69291 630.0236 cm
Q
q
-1 0 0 1 62.69291 380.8236 cm
+1 0 0 1 62.69291 612.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -5006,25 +4966,25 @@ q
Q
Q
q
-1 0 0 1 62.69291 380.8236 cm
+1 0 0 1 62.69291 612.0236 cm
Q
q
-1 0 0 1 62.69291 380.8236 cm
+1 0 0 1 62.69291 612.0236 cm
Q
q
-1 0 0 1 62.69291 338.8236 cm
+1 0 0 1 62.69291 570.0236 cm
q
BT 1 0 0 1 0 28.82 Tm .937485 Tw 12 TL /F1 10 Tf 0 0 0 rg (Moreover the ) Tj /F4 10 Tf (__str__ ) Tj /F1 10 Tf (representation of the output object is redefined to return the output string if the) Tj T* 0 Tw 2.686651 Tw (command was successful or the error message if the command failed \(actually it returns the error) Tj T* 0 Tw (message preceded by the name of the exception class\).) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 320.8236 cm
+1 0 0 1 62.69291 552.0236 cm
q
BT 1 0 0 1 0 4.82 Tm 12 TL /F1 10 Tf 0 0 0 rg (For instance, if you send a mispelled option to the interpreter a ) Tj /F4 10 Tf (SystemExit ) Tj /F1 10 Tf (will be trapped:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 227.6236 cm
+1 0 0 1 62.69291 458.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -5044,20 +5004,20 @@ Q
Q
Q
q
-1 0 0 1 62.69291 195.6236 cm
+1 0 0 1 62.69291 426.8236 cm
q
BT 1 0 0 1 0 16.82 Tm 2.90561 Tw 12 TL /F1 10 Tf 0 0 0 rg (It is important to invoke the ) Tj /F4 10 Tf (.send ) Tj /F1 10 Tf (method inside the context manager, otherwise you will get a) Tj T* 0 Tw /F4 10 Tf (RuntimeError) Tj /F1 10 Tf (.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 153.6236 cm
+1 0 0 1 62.69291 384.8236 cm
q
0 0 0 rg
BT 1 0 0 1 0 28.82 Tm /F1 10 Tf 12 TL .29311 Tw (For instance, suppose you want to implement a graphical runner for a plac-based interpreter with two text) Tj T* 0 Tw 1.548221 Tw (widgets: one to enter the commands and one to display the results. Suppose you want to display the) Tj T* 0 Tw (errors with tracebacks in red. You will need to code something like that \(pseudocode follows\):) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 96.42362 cm
+1 0 0 1 62.69291 147.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -5067,69 +5027,48 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 48 re B*
+n -6 -6 468.6898 228 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 29.71 Tm /F4 10 Tf 12 TL (input_widget = WidgetReadingInput\(\)) Tj T* (output_widget = WidgetDisplayingOutput\(\)) Tj T* T* ET
+BT 1 0 0 1 0 209.71 Tm /F4 10 Tf 12 TL (input_widget = WidgetReadingInput\(\)) Tj T* (output_widget = WidgetDisplayingOutput\(\)) Tj T* T* (def send\(interpreter, line\):) Tj T* ( out = interpreter.send\(line\)) Tj T* ( if out.tb: # there was an error) Tj T* ( output_widget.display\(out.tb, color='red'\)) Tj T* ( else:) Tj T* ( output_widget.display\(out.str\)) Tj T* T* (main = plac.import_main\(tool_path\) # get the main object) Tj T* T* (with plac.Interpreter\(main\) as i:) Tj T* ( def callback\(event\):) Tj T* ( if event.user_pressed_ENTER\(\):) Tj T* ( send\(i, input_widget.last_line\)) Tj T* ( input_widget.addcallback\(callback\)) Tj T* ( gui_mainloop.start\(\)) Tj T* ET
Q
Q
Q
Q
Q
q
+1 0 0 1 62.69291 115.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 16.82 Tm /F1 10 Tf 12 TL .102765 Tw (You can adapt the pseudocode to your GUI toolkit of choice and you can also change the file associations) Tj T* 0 Tw (in such a way that clicking on a plac tool file the graphical user interface starts.) Tj T* ET
+Q
+Q
+q
1 0 0 1 56.69291 56.69291 cm
q
0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 235.3849 0 Td (16) Tj T* -235.3849 0 Td ET
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 235.3849 0 Td (17) Tj T* -235.3849 0 Td ET
Q
Q
endstream
endobj
-% 'R181': class PDFStream
-181 0 obj
+% 'R179': class PDFStream
+179 0 obj
% page stream
-<< /Length 4124 >>
+<< /Length 4283 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 571.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 192 re B*
-Q
-q
-0 0 0 rg
-BT 1 0 0 1 0 173.71 Tm /F4 10 Tf 12 TL (def send\(interpreter, line\):) Tj T* ( out = interpreter.send\(line\)) Tj T* ( if out.tb: # there was an error) Tj T* ( output_widget.display\(out.tb, color='red'\)) Tj T* ( else:) Tj T* ( output_widget.display\(out.str\)) Tj T* T* (main = plac.import_main\(tool_path\) # get the main object) Tj T* T* (with plac.Interpreter\(main\) as i:) Tj T* ( def callback\(event\):) Tj T* ( if event.user_pressed_ENTER\(\):) Tj T* ( send\(i, input_widget.last_line\)) Tj T* ( input_widget.addcallback\(callback\)) Tj T* ( gui_mainloop.start\(\)) Tj T* ET
-Q
-Q
-Q
-Q
-Q
-q
-1 0 0 1 62.69291 539.8236 cm
-q
-0 0 0 rg
-BT 1 0 0 1 0 16.82 Tm /F1 10 Tf 12 TL .102765 Tw (You can adapt the pseudocode to your GUI toolkit of choice and you can also change the file associations) Tj T* 0 Tw (in such a way that clicking on a plac tool file the graphical user interface starts.) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 485.8236 cm
+1 0 0 1 62.69291 717.0236 cm
q
BT 1 0 0 1 0 40.82 Tm 2.090651 Tw 12 TL /F1 10 Tf 0 0 0 rg (There is a final ) Tj /F5 10 Tf (caveat) Tj /F1 10 Tf (: since the plac interpreter loop is implemented via extended generators, plac) Tj T* 0 Tw .988651 Tw (interpreters are single threaded: you will get an error if you ) Tj /F4 10 Tf (.send ) Tj /F1 10 Tf (commands from separated threads.) Tj T* 0 Tw .947882 Tw (You can circumvent the problem by using a queue. If EXIT is a sentinel value to signal exiting from the) Tj T* 0 Tw (interpreter look, you can write code like this:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 428.6236 cm
+1 0 0 1 62.69291 659.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -5150,25 +5089,25 @@ Q
Q
Q
q
-1 0 0 1 62.69291 396.6236 cm
+1 0 0 1 62.69291 627.8236 cm
q
BT 1 0 0 1 0 16.82 Tm .106098 Tw 12 TL /F1 10 Tf 0 0 0 rg (The same trick also work for processes; you could run the interpreter loop in a separate process and send) Tj T* 0 Tw (commands to it via the Queue class provided by the ) Tj 0 0 .501961 rg (multiprocessing ) Tj 0 0 0 rg (module.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 363.6236 cm
+1 0 0 1 62.69291 594.8236 cm
q
BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Long running commands) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 321.6236 cm
+1 0 0 1 62.69291 552.8236 cm
q
BT 1 0 0 1 0 28.82 Tm 1.434431 Tw 12 TL /F1 10 Tf 0 0 0 rg (As we saw, by default a ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (interpreter blocks until the command terminates. This is an issue, in the) Tj T* 0 Tw 1.201318 Tw (sense that it makes the interactive experience quite painful for long running commands. An example is) Tj T* 0 Tw (better than a thousand words, so consider the following fake importer:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 96.42362 cm
+1 0 0 1 62.69291 291.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -5178,35 +5117,24 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 216 re B*
+n -6 -6 468.6898 252 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 197.71 Tm /F4 10 Tf 12 TL (import time) Tj T* (import plac) Tj T* T* (class FakeImporter\(object\):) Tj T* ( "A fake importer with an import_file command") Tj T* ( commands = ['import_file']) Tj T* ( def __init__\(self, dsn\):) Tj T* ( self.dsn = dsn) Tj T* ( def import_file\(self, fname\):) Tj T* ( "Import a file into the database") Tj T* ( try:) Tj T* ( for n in range\(10000\):) Tj T* ( time.sleep\(.01\)) Tj T* ( if n % 100 == 99:) Tj T* ( yield 'Imported %d lines' % \(n+1\)) Tj T* ( finally:) Tj T* ( print\('closing the file'\)) Tj T* ET
+BT 1 0 0 1 0 233.71 Tm /F4 10 Tf 12 TL (import time) Tj T* (import plac) Tj T* T* (class FakeImporter\(object\):) Tj T* ( "A fake importer with an import_file command") Tj T* ( commands = ['import_file']) Tj T* ( def __init__\(self, dsn\):) Tj T* ( self.dsn = dsn) Tj T* ( def import_file\(self, fname\):) Tj T* ( "Import a file into the database") Tj T* ( try:) Tj T* ( for n in range\(10000\):) Tj T* ( time.sleep\(.01\)) Tj T* ( if n % 100 == 99:) Tj T* ( yield 'Imported %d lines' % \(n+1\)) Tj T* ( finally:) Tj T* ( print\('closing the file'\)) Tj T* T* (if __name__ == '__main__':) Tj T* ( plac.Interpreter\(plac.call\(FakeImporter\)\).interact\(\)) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 56.69291 56.69291 cm
+1 0 0 1 62.69291 259.6236 cm
q
-0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 235.3849 0 Td (17) Tj T* -235.3849 0 Td ET
+BT 1 0 0 1 0 16.82 Tm 1.466457 Tw 12 TL /F1 10 Tf 0 0 0 rg (If you run the ) Tj /F4 10 Tf (import_file ) Tj /F1 10 Tf (command, you will have to wait for 200 seconds before entering a new) Tj T* 0 Tw (command:) Tj T* ET
Q
Q
-
-endstream
-
-endobj
-% 'R182': class PDFStream
-182 0 obj
-% page stream
-<< /Length 4850 >>
-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 130.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -5216,66 +5144,63 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 48 re B*
+n -6 -6 468.6898 120 re B*
Q
q
-0 0 0 rg
-BT 1 0 0 1 0 29.71 Tm /F4 10 Tf 12 TL T* (if __name__ == '__main__':) Tj T* ( plac.Interpreter\(plac.call\(FakeImporter\)\).interact\(\)) Tj T* ET
+BT 1 0 0 1 0 101.71 Tm 12 TL /F4 10 Tf 0 0 0 rg ($ python importer1.py dsn) Tj T* (A fake importer with an import_file command) Tj T* (i) Tj (>) Tj ( import_file file1) Tj T* (Imported 100 lines) Tj T* (Imported 200 lines) Tj T* (Imported 300 lines) Tj T* (... ) Tj (<) Tj (wait 3+ minutes) Tj (>) Tj T* (Imported 10000 lines) Tj T* (closing the file) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 683.8236 cm
+1 0 0 1 62.69291 98.42362 cm
q
-BT 1 0 0 1 0 16.82 Tm 1.466457 Tw 12 TL /F1 10 Tf 0 0 0 rg (If you run the ) Tj /F4 10 Tf (import_file ) Tj /F1 10 Tf (command, you will have to wait for 200 seconds before entering a new) Tj T* 0 Tw (command:) Tj T* ET
+BT 1 0 0 1 0 16.82 Tm .96832 Tw 12 TL /F1 10 Tf 0 0 0 rg (Being unable to enter any other command is quite annoying: in such situation one would like to run the ) Tj T* 0 Tw .941318 Tw (long running commands in the background, to keep the interface responsive. ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (provides two ways to) Tj T* 0 Tw ET
Q
Q
q
-1 0 0 1 62.69291 554.6236 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 468.6898 120 re B*
-Q
+1 0 0 1 56.69291 56.69291 cm
q
-BT 1 0 0 1 0 101.71 Tm 12 TL /F4 10 Tf 0 0 0 rg ($ python importer1.py dsn) Tj T* (A fake importer with an import_file command) Tj T* (i) Tj (>) Tj ( import_file file1) Tj T* (Imported 100 lines) Tj T* (Imported 200 lines) Tj T* (Imported 300 lines) Tj T* (... ) Tj (<) Tj (wait 3+ minutes) Tj (>) Tj T* (Imported 10000 lines) Tj T* (closing the file) Tj T* ET
-Q
-Q
-Q
+0 0 0 rg
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 235.3849 0 Td (18) Tj T* -235.3849 0 Td ET
Q
Q
+
+endstream
+
+endobj
+% 'R180': class PDFStream
+180 0 obj
+% page stream
+<< /Length 5339 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 510.6236 cm
+1 0 0 1 62.69291 753.0236 cm
q
-BT 1 0 0 1 0 28.82 Tm .96832 Tw 12 TL /F1 10 Tf 0 0 0 rg (Being unable to enter any other command is quite annoying: in such situation one would like to run the) Tj T* 0 Tw .941318 Tw (long running commands in the background, to keep the interface responsive. ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (provides two ways to) Tj T* 0 Tw (reach this goal: threads and processes.) Tj T* ET
+0 0 0 rg
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (reach this goal: threads and processes.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 477.6236 cm
+1 0 0 1 62.69291 720.0236 cm
q
BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Threaded commands) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 447.6236 cm
+1 0 0 1 62.69291 690.0236 cm
q
0 0 0 rg
BT 1 0 0 1 0 16.82 Tm /F1 10 Tf 12 TL .317988 Tw (The most familiar way to execute a task in the background \(even if not necessarily the best way\) is to run) Tj T* 0 Tw (it into a separated thread. In our example it is sufficient to replace the line) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 441.6236 cm
+1 0 0 1 62.69291 684.0236 cm
Q
q
-1 0 0 1 62.69291 429.6236 cm
+1 0 0 1 62.69291 672.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
BT 1 0 0 1 0 2 Tm T* ET
@@ -5290,20 +5215,20 @@ q
Q
Q
q
-1 0 0 1 62.69291 429.6236 cm
+1 0 0 1 62.69291 672.0236 cm
Q
q
-1 0 0 1 62.69291 411.6236 cm
+1 0 0 1 62.69291 654.0236 cm
q
0 0 0 rg
BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (with) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 405.6236 cm
+1 0 0 1 62.69291 648.0236 cm
Q
q
-1 0 0 1 62.69291 393.6236 cm
+1 0 0 1 62.69291 636.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
BT 1 0 0 1 0 2 Tm T* ET
@@ -5318,16 +5243,16 @@ q
Q
Q
q
-1 0 0 1 62.69291 393.6236 cm
+1 0 0 1 62.69291 636.0236 cm
Q
q
-1 0 0 1 62.69291 363.6236 cm
+1 0 0 1 62.69291 606.0236 cm
q
BT 1 0 0 1 0 16.82 Tm 1.38311 Tw 12 TL /F1 10 Tf 0 0 0 rg (to tell to the ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (interpreter that the command ) Tj /F4 10 Tf (import_file ) Tj /F1 10 Tf (should be run into a separated thread.) Tj T* 0 Tw (Here is an example session:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 318.4236 cm
+1 0 0 1 62.69291 560.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -5347,13 +5272,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 286.4236 cm
+1 0 0 1 62.69291 528.8236 cm
q
BT 1 0 0 1 0 16.82 Tm .595777 Tw 12 TL /F1 10 Tf 0 0 0 rg (The import task started in a separated thread. You can see the progress of the task by using the special) Tj T* 0 Tw (command ) Tj /F4 10 Tf (.output) Tj /F1 10 Tf (:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 217.2236 cm
+1 0 0 1 62.69291 459.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -5373,14 +5298,14 @@ Q
Q
Q
q
-1 0 0 1 62.69291 197.2236 cm
+1 0 0 1 62.69291 439.6236 cm
q
0 0 0 rg
BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (If you look after a while, you will get more lines of output:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 104.0236 cm
+1 0 0 1 62.69291 346.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -5400,31 +5325,14 @@ Q
Q
Q
q
-1 0 0 1 56.69291 56.69291 cm
-q
-0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 235.3849 0 Td (18) Tj T* -235.3849 0 Td ET
-Q
-Q
-
-endstream
-
-endobj
-% 'R183': class PDFStream
-183 0 obj
-% page stream
-<< /Length 4810 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
-q
-1 0 0 1 62.69291 753.0236 cm
+1 0 0 1 62.69291 326.4236 cm
q
0 0 0 rg
BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (If you look after a time long enough, the task will be finished:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 707.8236 cm
+1 0 0 1 62.69291 281.2236 cm
q
q
1 0 0 1 0 0 cm
@@ -5444,20 +5352,20 @@ Q
Q
Q
q
-1 0 0 1 62.69291 675.8236 cm
+1 0 0 1 62.69291 249.2236 cm
q
BT 1 0 0 1 0 16.82 Tm 1.045868 Tw 12 TL /F1 10 Tf 0 0 0 rg (You can even skip the number argument: then ) Tj /F4 10 Tf (.output ) Tj /F1 10 Tf (will the return the output of the last launched) Tj T* 0 Tw (command \(the special commands like .output do not count\).) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 657.8236 cm
+1 0 0 1 62.69291 231.2236 cm
q
0 0 0 rg
BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (You can launch many tasks one after the other:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 588.6236 cm
+1 0 0 1 62.69291 162.0236 cm
q
q
1 0 0 1 0 0 cm
@@ -5477,13 +5385,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 568.6236 cm
+1 0 0 1 62.69291 142.0236 cm
q
BT 1 0 0 1 0 4.82 Tm 12 TL /F1 10 Tf 0 0 0 rg (The ) Tj /F4 10 Tf (.list ) Tj /F1 10 Tf (command displays all the running tasks:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 511.4236 cm
+1 0 0 1 62.69291 96.82362 cm
q
q
1 0 0 1 0 0 cm
@@ -5493,24 +5401,34 @@ 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 (i) Tj (>) Tj ( .list) Tj T* (<) Tj (ThreadedTask 5 [import_file file2] RUNNING) Tj (>) Tj T* (<) Tj (ThreadedTask 6 [import_file file3] RUNNING) Tj (>) Tj T* ET
+BT 1 0 0 1 0 17.71 Tm 12 TL /F4 10 Tf 0 0 0 rg (i) Tj (>) Tj ( .list) Tj T* (<) Tj (ThreadedTask 5 [import_file file2] RUNNING) Tj (>) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 491.4236 cm
+1 0 0 1 56.69291 56.69291 cm
q
0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (It is even possible to kill a task:) Tj T* ET
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 235.3849 0 Td (19) Tj T* -235.3849 0 Td ET
Q
Q
+
+endstream
+
+endobj
+% 'R181': class PDFStream
+181 0 obj
+% page stream
+<< /Length 4995 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 398.2236 cm
+1 0 0 1 62.69291 739.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -5520,23 +5438,24 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 84 re B*
+n -6 -6 468.6898 24 re B*
Q
q
-BT 1 0 0 1 0 65.71 Tm 12 TL /F4 10 Tf 0 0 0 rg (i) Tj (>) Tj ( .kill 5) Tj T* (<) Tj (ThreadedTask 5 [import_file file2] TOBEKILLED) Tj (>) Tj T* (# wait a bit ...) Tj T* (closing the file) Tj T* (i) Tj (>) Tj ( .output 5) Tj T* (<) Tj (ThreadedTask 5 [import_file file2] KILLED) Tj (>) Tj T* ET
+BT 1 0 0 1 0 5.71 Tm 12 TL /F4 10 Tf 0 0 0 rg (<) Tj (ThreadedTask 6 [import_file file3] RUNNING) Tj (>) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 306.2236 cm
+1 0 0 1 62.69291 719.8236 cm
q
-BT 1 0 0 1 0 76.82 Tm 1.100542 Tw 12 TL /F1 10 Tf 0 0 0 rg (You should notice that since at the Python level it is impossible to kill a thread, the ) Tj /F4 10 Tf (.kill ) Tj /F1 10 Tf (commands) Tj T* 0 Tw 1.793984 Tw (works by setting the status of the task to ) Tj /F4 10 Tf (TOBEKILLED) Tj /F1 10 Tf (. Internally the generator corresponding to the) Tj T* 0 Tw .632927 Tw (command is executed in the thread and the status is checked at each iteration: when the status become) Tj T* 0 Tw 2.578443 Tw /F4 10 Tf (TOBEKILLED ) Tj /F1 10 Tf (a ) Tj /F4 10 Tf (GeneratorExit ) Tj /F1 10 Tf (exception is raised and the thread terminates \(softly, so that the) Tj T* 0 Tw 2.328651 Tw /F4 10 Tf (finally ) Tj /F1 10 Tf (clause is honored\). In our example the generator is yielding back control once every 100) Tj T* 0 Tw 1.152619 Tw (iterations, i.e. every two seconds \(not much\). In order to get a responsive interface it is a good idea to) Tj T* 0 Tw (yield more often, for instance every 10 iterations \(i.e. 5 times per second\), as in the following code:) Tj T* ET
+0 0 0 rg
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (It is even possible to kill a task:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 93.02362 cm
+1 0 0 1 62.69291 626.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -5546,35 +5465,23 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 204 re B*
+n -6 -6 468.6898 84 re B*
Q
q
-0 0 0 rg
-BT 1 0 0 1 0 185.71 Tm /F4 10 Tf 12 TL (import time) Tj T* (import plac) Tj T* T* (class FakeImporter\(object\):) Tj T* ( "A fake importer with an import_file command") Tj T* ( thcommands = ['import_file']) Tj T* ( def __init__\(self, dsn\):) Tj T* ( self.dsn = dsn) Tj T* ( def import_file\(self, fname\):) Tj T* ( "Import a file into the database") Tj T* ( try:) Tj T* ( for n in range\(10000\):) Tj T* ( time.sleep\(.02\)) Tj T* ( if n % 100 == 99: # every two seconds) Tj T* ( yield 'Imported %d lines' % \(n+1\)) Tj T* ( if n % 10 == 9: # every 0.2 seconds) Tj T* ET
+BT 1 0 0 1 0 65.71 Tm 12 TL /F4 10 Tf 0 0 0 rg (i) Tj (>) Tj ( .kill 5) Tj T* (<) Tj (ThreadedTask 5 [import_file file2] TOBEKILLED) Tj (>) Tj T* (# wait a bit ...) Tj T* (closing the file) Tj T* (i) Tj (>) Tj ( .output 5) Tj T* (<) Tj (ThreadedTask 5 [import_file file2] KILLED) Tj (>) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 56.69291 56.69291 cm
+1 0 0 1 62.69291 534.6236 cm
q
-0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 235.3849 0 Td (19) Tj T* -235.3849 0 Td ET
+BT 1 0 0 1 0 76.82 Tm 1.100542 Tw 12 TL /F1 10 Tf 0 0 0 rg (You should notice that since at the Python level it is impossible to kill a thread, the ) Tj /F4 10 Tf (.kill ) Tj /F1 10 Tf (commands) Tj T* 0 Tw 1.793984 Tw (works by setting the status of the task to ) Tj /F4 10 Tf (TOBEKILLED) Tj /F1 10 Tf (. Internally the generator corresponding to the) Tj T* 0 Tw .632927 Tw (command is executed in the thread and the status is checked at each iteration: when the status become) Tj T* 0 Tw 2.578443 Tw /F4 10 Tf (TOBEKILLED ) Tj /F1 10 Tf (a ) Tj /F4 10 Tf (GeneratorExit ) Tj /F1 10 Tf (exception is raised and the thread terminates \(softly, so that the) Tj T* 0 Tw 2.328651 Tw /F4 10 Tf (finally ) Tj /F1 10 Tf (clause is honored\). In our example the generator is yielding back control once every 100) Tj T* 0 Tw 1.152619 Tw (iterations, i.e. every two seconds \(not much\). In order to get a responsive interface it is a good idea to) Tj T* 0 Tw (yield more often, for instance every 10 iterations \(i.e. 5 times per second\), as in the following code:) Tj T* ET
Q
Q
-
-endstream
-
-endobj
-% 'R184': class PDFStream
-184 0 obj
-% page stream
-<< /Length 4592 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 679.8236 cm
+1 0 0 1 62.69291 249.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -5584,40 +5491,40 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 84 re B*
+n -6 -6 468.6898 276 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 65.71 Tm /F4 10 Tf 12 TL ( yield # go back and check the TOBEKILLED status) Tj T* ( finally:) Tj T* ( print\('closing the file'\)) Tj T* T* (if __name__ == '__main__':) Tj T* ( plac.Interpreter\(plac.call\(FakeImporter\)\).interact\(\)) Tj T* ET
+BT 1 0 0 1 0 257.71 Tm /F4 10 Tf 12 TL (import time) Tj T* (import plac) Tj T* T* (class FakeImporter\(object\):) Tj T* ( "A fake importer with an import_file command") Tj T* ( thcommands = ['import_file']) Tj T* ( def __init__\(self, dsn\):) Tj T* ( self.dsn = dsn) Tj T* ( def import_file\(self, fname\):) Tj T* ( "Import a file into the database") Tj T* ( try:) Tj T* ( for n in range\(10000\):) Tj T* ( time.sleep\(.02\)) Tj T* ( if n % 100 == 99: # every two seconds) Tj T* ( yield 'Imported %d lines' % \(n+1\)) Tj T* ( if n % 10 == 9: # every 0.2 seconds) Tj T* ( yield # go back and check the TOBEKILLED status) Tj T* ( finally:) Tj T* ( print\('closing the file'\)) Tj T* T* (if __name__ == '__main__':) Tj T* ( plac.Interpreter\(plac.call\(FakeImporter\)\).interact\(\)) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 646.8236 cm
+1 0 0 1 62.69291 216.4236 cm
q
BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Running commands as external processes) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 592.8236 cm
+1 0 0 1 62.69291 162.4236 cm
q
BT 1 0 0 1 0 40.82 Tm 2.30686 Tw 12 TL /F1 10 Tf 0 0 0 rg (Threads are not loved much in the Python world and actually most people prefer to use processes) Tj T* 0 Tw 3.350697 Tw (instead. For this reason ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (provides the option to execute long running commands as external) Tj T* 0 Tw .632706 Tw (processes. Unfortunately the current implementation only works in Unix-like operating systems \(including) Tj T* 0 Tw (Mac OS X\) because it relies on fork via the ) Tj 0 0 .501961 rg (multiprocessing ) Tj 0 0 0 rg (module.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 574.8236 cm
+1 0 0 1 62.69291 144.4236 cm
q
0 0 0 rg
BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (In our example, to enable the feature it is sufficient to replace the line) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 568.8236 cm
+1 0 0 1 62.69291 138.4236 cm
Q
q
-1 0 0 1 62.69291 556.8236 cm
+1 0 0 1 62.69291 126.4236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
BT 1 0 0 1 0 2 Tm T* ET
@@ -5632,20 +5539,20 @@ q
Q
Q
q
-1 0 0 1 62.69291 556.8236 cm
+1 0 0 1 62.69291 126.4236 cm
Q
q
-1 0 0 1 62.69291 538.8236 cm
+1 0 0 1 62.69291 108.4236 cm
q
0 0 0 rg
BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (with) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 532.8236 cm
+1 0 0 1 62.69291 102.4236 cm
Q
q
-1 0 0 1 62.69291 520.8236 cm
+1 0 0 1 62.69291 90.42362 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
BT 1 0 0 1 0 2 Tm T* ET
@@ -5659,17 +5566,34 @@ q
Q
Q
q
-1 0 0 1 62.69291 520.8236 cm
+1 0 0 1 62.69291 90.42362 cm
Q
q
-1 0 0 1 62.69291 490.8236 cm
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 235.3849 0 Td (20) Tj T* -235.3849 0 Td ET
+Q
+Q
+
+endstream
+
+endobj
+% 'R182': class PDFStream
+182 0 obj
+% page stream
+<< /Length 5075 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 741.0236 cm
q
0 0 0 rg
BT 1 0 0 1 0 16.82 Tm /F1 10 Tf 12 TL .772619 Tw (The user experience is exactly the same as with threads and you will not see any difference at the user) Tj T* 0 Tw (interface level:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 349.6236 cm
+1 0 0 1 62.69291 599.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -5689,63 +5613,46 @@ Q
Q
Q
q
-1 0 0 1 62.69291 293.6236 cm
+1 0 0 1 62.69291 543.8236 cm
q
0 0 0 rg
BT 1 0 0 1 0 40.82 Tm /F1 10 Tf 12 TL 1.201318 Tw (Still, using processes is quite different than using threads: in particular, when using processes you can) Tj T* 0 Tw 2.313318 Tw (only yield pickleable values and you cannot re-raise an exception first raised in a different process,) Tj T* 0 Tw 1.445697 Tw (because traceback objects are not pickleable. Moreover, you cannot rely on automatic sharing of your) Tj T* 0 Tw (objects.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 239.6236 cm
+1 0 0 1 62.69291 489.8236 cm
q
BT 1 0 0 1 0 40.82 Tm .128935 Tw 12 TL /F1 10 Tf 0 0 0 rg (On the plus side, when using processes you do not need to worry about killing a command: they are killed) Tj T* 0 Tw .466412 Tw (immediately using a SIGTERM signal, and there is not a ) Tj /F4 10 Tf (TOBEKILLED ) Tj /F1 10 Tf (mechanism. Moreover, the killing) Tj T* 0 Tw 1.50229 Tw (is guaranteed to be soft: internally a command receiving a SIGTERM raises a ) Tj /F4 10 Tf (TerminatedProcess) Tj T* 0 Tw /F1 10 Tf (exception which is trapped in the generator loop, so that the command is closed properly.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 209.6236 cm
+1 0 0 1 62.69291 459.8236 cm
q
0 0 0 rg
BT 1 0 0 1 0 16.82 Tm /F1 10 Tf 12 TL .242927 Tw (Using processes allows to take full advantage of multicore machines and it is safer than using threads, so) Tj T* 0 Tw (it is the recommended approach unless you are working on Windows.) Tj T* ET
Q
Q
q
-1 0 0 1 56.69291 56.69291 cm
-q
-0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 235.3849 0 Td (20) Tj T* -235.3849 0 Td ET
-Q
-Q
-
-endstream
-
-endobj
-% 'R185': class PDFStream
-185 0 obj
-% page stream
-<< /Length 4964 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
-q
-1 0 0 1 62.69291 744.0236 cm
+1 0 0 1 62.69291 426.8236 cm
q
BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Managing the output of concurrent commands) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 642.0236 cm
+1 0 0 1 62.69291 324.8236 cm
q
BT 1 0 0 1 0 88.82 Tm 1.895542 Tw 12 TL /F1 10 Tf 0 0 .501961 rg (plac ) Tj 0 0 0 rg (acts as a command-line task launcher and can be used as the base to build a GUI-based task) Tj T* 0 Tw .38561 Tw (launcher and task monitor. To this aim the interpreter class provides a ) Tj /F4 10 Tf (.submit ) Tj /F1 10 Tf (method which returns a) Tj T* 0 Tw 1.792339 Tw (task object and a ) Tj /F4 10 Tf (.tasks ) Tj /F1 10 Tf (method returning the list of all the tasks submitted to the interpreter. The) Tj T* 0 Tw .373516 Tw /F4 10 Tf (submit ) Tj /F1 10 Tf (method does not start the task and thus it is nonblocking. Each task has an ) Tj /F4 10 Tf (.outlist ) Tj /F1 10 Tf (attribute) Tj T* 0 Tw .106098 Tw (which is a list storing the value yielded by the generator underlying the task \(the ) Tj /F4 10 Tf (None ) Tj /F1 10 Tf (values are skipped) Tj T* 0 Tw .633318 Tw (though\): the ) Tj /F4 10 Tf (.outlist ) Tj /F1 10 Tf (grows as the task runs and more values are yielded. Accessing the ) Tj /F4 10 Tf (.outlist) Tj T* 0 Tw 1.051654 Tw /F1 10 Tf (is nonblocking and can be done freely. Finally there is a ) Tj /F4 10 Tf (.result ) Tj /F1 10 Tf (property which waits for the task to) Tj T* 0 Tw (finish and returns the last yielded value or raises an exception.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 612.0236 cm
+1 0 0 1 62.69291 294.8236 cm
q
0 0 0 rg
BT 1 0 0 1 0 16.82 Tm /F1 10 Tf 12 TL .014692 Tw (Here is some example code to visualize the output of the FakeImporter in Tkinter \(I chose Tkinter because) Tj T* 0 Tw (it is easy to use and it is in the standard library, but you can use any GUI\):) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 242.8236 cm
+1 0 0 1 62.69291 93.62362 cm
q
q
1 0 0 1 0 0 cm
@@ -5755,27 +5662,15 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 360 re B*
+n -6 -6 468.6898 192 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 341.71 Tm /F4 10 Tf 12 TL (from Tkinter import *) Tj T* (from importer3 import FakeImporter) Tj T* T* (def taskwidget\(root, task, tick=500\):) Tj T* ( "A Label widget showing the output of a task every 500 ms") Tj T* ( sv = StringVar\(root\)) Tj T* ( lb = Label\(root, textvariable=sv\)) Tj T* ( def show_outlist\(\):) Tj T* ( try:) Tj T* ( out = task.outlist[-1]) Tj T* ( except IndexError: # no output yet) Tj T* ( out = '') Tj T* ( sv.set\('%s %s' % \(task, out\)\)) Tj T* ( root.after\(tick, show_outlist\)) Tj T* ( root.after\(0, show_outlist\)) Tj T* ( return lb) Tj T* T* (def monitor\(tasks\):) Tj T* ( root = Tk\(\)) Tj T* ( for task in tasks:) Tj T* ( task.run\(\)) Tj T* ( taskwidget\(root, task\).pack\(\)) Tj T* ( root.mainloop\(\)) Tj T* T* (if __name__ == '__main__':) Tj T* ( import plac) Tj T* ( with plac.Interpreter\(plac.call\(FakeImporter\)\) as i:) Tj T* ( tasks = [i.submit\('import_file f1'\), i.submit\('import_file f2'\)]) Tj T* ( monitor\(tasks\)) Tj T* ET
-Q
+BT 1 0 0 1 0 173.71 Tm /F4 10 Tf 12 TL (from Tkinter import *) Tj T* (from importer3 import FakeImporter) Tj T* T* (def taskwidget\(root, task, tick=500\):) Tj T* ( "A Label widget showing the output of a task every 500 ms") Tj T* ( sv = StringVar\(root\)) Tj T* ( lb = Label\(root, textvariable=sv\)) Tj T* ( def show_outlist\(\):) Tj T* ( try:) Tj T* ( out = task.outlist[-1]) Tj T* ( except IndexError: # no output yet) Tj T* ( out = '') Tj T* ( sv.set\('%s %s' % \(task, out\)\)) Tj T* ( root.after\(tick, show_outlist\)) Tj T* ( root.after\(0, show_outlist\)) Tj T* ET
Q
Q
Q
Q
-q
-1 0 0 1 62.69291 209.8236 cm
-q
-BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Parallel computing with plac) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 95.82362 cm
-q
-BT 1 0 0 1 0 100.82 Tm 1.174751 Tw 12 TL /F1 10 Tf 0 0 .501961 rg (plac ) Tj 0 0 0 rg (is certainly not intended as a tool for parallel computing, but still you can use it to launch a set of) Tj T* 0 Tw .494269 Tw (commands and to collect the results, similarly to the MapReduce pattern recently popularized by Google.) Tj T* 0 Tw .329431 Tw (In order to give an example, I will consider the "Hello World" of parallel computing, i.e. the computation of) Tj T* 0 Tw .229431 Tw (pi with independent processes. There is a huge number of algorithms to compute pi; here I will describe a) Tj T* 0 Tw .30683 Tw (trivial one chosen for simplicity, not per efficienty. The trick is to consider the first quadrant of a circle with) Tj T* 0 Tw .102488 Tw (radius 1 and to extract a number of points ) Tj /F4 10 Tf (\(x, y\) ) Tj /F1 10 Tf (with ) Tj /F4 10 Tf (x ) Tj /F1 10 Tf (and ) Tj /F4 10 Tf (y ) Tj /F1 10 Tf (random variables in the interval ) Tj /F4 10 Tf ([0,1]) Tj /F1 10 Tf (.) Tj T* 0 Tw .743876 Tw (The probability of extracting a number inside the quadrant \(i.e. with ) Tj /F4 10 Tf (x^2 + y^2 < 1) Tj /F1 10 Tf (\) is proportional to) Tj T* 0 Tw .725251 Tw (the area of the quadrant \(i.e. ) Tj /F4 10 Tf (pi/4) Tj /F1 10 Tf (\). The value of ) Tj /F4 10 Tf (pi ) Tj /F1 10 Tf (therefore can be extracted by multiplying by 4 the) Tj T* 0 Tw (ratio between the number of points in the quadrant versus the total number of points ) Tj /F4 10 Tf (N) Tj /F1 10 Tf (, for ) Tj /F4 10 Tf (N ) Tj /F1 10 Tf (large:) Tj T* ET
-Q
Q
q
1 0 0 1 56.69291 56.69291 cm
@@ -5788,14 +5683,47 @@ Q
endstream
endobj
-% 'R186': class PDFStream
-186 0 obj
+% 'R183': class PDFStream
+183 0 obj
% page stream
-<< /Length 3429 >>
+<< /Length 4632 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 667.8236 cm
+1 0 0 1 62.69291 583.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 180 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 161.71 Tm /F4 10 Tf 12 TL ( return lb) Tj T* T* (def monitor\(tasks\):) Tj T* ( root = Tk\(\)) Tj T* ( for task in tasks:) Tj T* ( task.run\(\)) Tj T* ( taskwidget\(root, task\).pack\(\)) Tj T* ( root.mainloop\(\)) Tj T* T* (if __name__ == '__main__':) Tj T* ( import plac) Tj T* ( with plac.Interpreter\(plac.call\(FakeImporter\)\) as i:) Tj T* ( tasks = [i.submit\('import_file f1'\), i.submit\('import_file f2'\)]) Tj T* ( monitor\(tasks\)) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 550.8236 cm
+q
+BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Parallel computing with plac) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 436.8236 cm
+q
+BT 1 0 0 1 0 100.82 Tm 1.174751 Tw 12 TL /F1 10 Tf 0 0 .501961 rg (plac ) Tj 0 0 0 rg (is certainly not intended as a tool for parallel computing, but still you can use it to launch a set of) Tj T* 0 Tw .494269 Tw (commands and to collect the results, similarly to the MapReduce pattern recently popularized by Google.) Tj T* 0 Tw .329431 Tw (In order to give an example, I will consider the "Hello World" of parallel computing, i.e. the computation of) Tj T* 0 Tw .229431 Tw (pi with independent processes. There is a huge number of algorithms to compute pi; here I will describe a) Tj T* 0 Tw .30683 Tw (trivial one chosen for simplicity, not per efficienty. The trick is to consider the first quadrant of a circle with) Tj T* 0 Tw .102488 Tw (radius 1 and to extract a number of points ) Tj /F4 10 Tf (\(x, y\) ) Tj /F1 10 Tf (with ) Tj /F4 10 Tf (x ) Tj /F1 10 Tf (and ) Tj /F4 10 Tf (y ) Tj /F1 10 Tf (random variables in the interval ) Tj /F4 10 Tf ([0,1]) Tj /F1 10 Tf (.) Tj T* 0 Tw .743876 Tw (The probability of extracting a number inside the quadrant \(i.e. with ) Tj /F4 10 Tf (x^2 + y^2 < 1) Tj /F1 10 Tf (\) is proportional to) Tj T* 0 Tw .725251 Tw (the area of the quadrant \(i.e. ) Tj /F4 10 Tf (pi/4) Tj /F1 10 Tf (\). The value of ) Tj /F4 10 Tf (pi ) Tj /F1 10 Tf (therefore can be extracted by multiplying by 4 the) Tj T* 0 Tw (ratio between the number of points in the quadrant versus the total number of points ) Tj /F4 10 Tf (N) Tj /F1 10 Tf (, for ) Tj /F4 10 Tf (N ) Tj /F1 10 Tf (large:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 331.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -5815,20 +5743,20 @@ Q
Q
Q
q
-1 0 0 1 62.69291 599.8236 cm
+1 0 0 1 62.69291 263.6236 cm
q
0 0 0 rg
BT 1 0 0 1 0 52.82 Tm /F1 10 Tf 12 TL .046654 Tw (The algorithm is trivially parallelizable: if you have n CPUs, you can compute pi n times with N/n iterations,) Tj T* 0 Tw 1.122488 Tw (sum the results and divide the total by n. I have a Macbook with two cores, therefore I would expect a) Tj T* 0 Tw 2.347984 Tw (speedup factor of 2 with respect to a sequential computation. Moreover, I would expect a threaded) Tj T* 0 Tw 2.827984 Tw (computation to be even slower than a sequential computation, due to the GIL and the scheduling) Tj T* 0 Tw (overhead.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 569.8236 cm
+1 0 0 1 62.69291 233.6236 cm
q
BT 1 0 0 1 0 16.82 Tm .313984 Tw 12 TL /F1 10 Tf 0 0 0 rg (Here is a script implementing the algorithm and working in three different modes \(parallel mode, threaded) Tj T* 0 Tw (mode and sequential mode\) depending on a ) Tj /F4 10 Tf (mode ) Tj /F1 10 Tf (option:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 92.62362 cm
+1 0 0 1 62.69291 92.42362 cm
q
q
1 0 0 1 0 0 cm
@@ -5838,10 +5766,10 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 468 re B*
+n -6 -6 468.6898 132 re B*
Q
q
-BT 1 0 0 1 0 449.71 Tm 12 TL /F4 10 Tf 0 0 0 rg (from __future__ import with_statement) Tj T* (from random import random) Tj T* (import multiprocessing) Tj T* (import plac) Tj T* T* (class PiCalculator\(object\):) Tj T* ( """Compute pi in parallel with threads or processes""") Tj T* ( ) Tj T* ( @plac.annotations\() Tj T* ( npoints=\('number of integration points', 'positional', None, int\),) Tj T* ( mode=\('sequential|parallel|threaded', 'option', 'm', str, 'SPT'\)\)) Tj T* ( def __init__\(self, npoints, mode='S'\):) Tj T* ( self.npoints = npoints) Tj T* ( if mode == 'P':) Tj T* ( self.mpcommands = ['calc_pi']) Tj T* ( elif mode == 'T':) Tj T* ( self.thcommands = ['calc_pi']) Tj T* ( elif mode == 'S':) Tj T* ( self.commands = ['calc_pi']) Tj T* ( self.n_cpu = multiprocessing.cpu_count\(\)) Tj T* ( ) Tj T* ( def submit_tasks\(self\):) Tj T* ( self.i = plac.Interpreter\(self\).__enter__\(\) ) Tj T* ( return [self.i.submit\('calc_pi %d' % \(self.npoints / self.n_cpu\)\)) Tj T* ( for _ in range\(self.n_cpu\)]) Tj T* T* ( def close\(self\):) Tj T* ( self.i.close\(\)) Tj T* T* ( @plac.annotations\() Tj T* ( npoints=\('npoints', 'positional', None, int\)\)) Tj T* ( def calc_pi\(self, npoints\):) Tj T* ( counts = 0) Tj T* ( for j in xrange\(npoints\):) Tj T* ( n, r = divmod\(j, 1000000\)) Tj T* ( if r == 0:) Tj T* ( yield '%dM iterations' % n) Tj T* ( x, y = random\(\), random\(\)) Tj T* ET
+BT 1 0 0 1 0 113.71 Tm 12 TL /F4 10 Tf 0 0 0 rg (from __future__ import with_statement) Tj T* (from random import random) Tj T* (import multiprocessing) Tj T* (import plac) Tj T* T* (class PiCalculator\(object\):) Tj T* ( """Compute pi in parallel with threads or processes""") Tj T* ( ) Tj T* ( @plac.annotations\() Tj T* ( npoints=\('number of integration points', 'positional', None, int\),) Tj T* ET
Q
Q
Q
@@ -5858,14 +5786,14 @@ Q
endstream
endobj
-% 'R187': class PDFStream
-187 0 obj
+% 'R184': class PDFStream
+184 0 obj
% page stream
-<< /Length 3154 >>
+<< /Length 2492 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 451.8236 cm
+1 0 0 1 62.69291 115.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -5875,30 +5803,47 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 312 re B*
+n -6 -6 468.6898 648 re B*
Q
q
-BT 1 0 0 1 0 293.71 Tm 12 TL /F4 10 Tf 0 0 0 rg ( if x*x + y*y ) Tj (<) Tj ( 1:) Tj T* ( counts += 1) Tj T* ( yield \(4.0 * counts\)/npoints) Tj T* T* ( def run\(self\):) Tj T* ( tasks = self.i.tasks\(\)) Tj T* ( for t in tasks:) Tj T* ( t.run\(\)) Tj T* ( try:) Tj T* ( total = 0) Tj T* ( for task in tasks:) Tj T* ( total += task.result) Tj T* ( except: # the task was killed) Tj T* ( print tasks) Tj T* ( return) Tj T* ( return total / self.n_cpu) Tj T* T* (if __name__ == '__main__':) Tj T* ( pc = plac.call\(PiCalculator\)) Tj T* ( pc.submit_tasks\(\)) Tj T* ( try:) Tj T* ( import time; t0 = time.time\(\)) Tj T* ( print '%f in %f seconds ' % \(pc.run\(\), time.time\(\) - t0\)) Tj T* ( finally:) Tj T* ( pc.close\(\)) Tj T* ET
+BT 1 0 0 1 0 629.71 Tm 12 TL /F4 10 Tf 0 0 0 rg ( mode=\('sequential|parallel|threaded', 'option', 'm', str, 'SPT'\)\)) Tj T* ( def __init__\(self, npoints, mode='S'\):) Tj T* ( self.npoints = npoints) Tj T* ( if mode == 'P':) Tj T* ( self.mpcommands = ['calc_pi']) Tj T* ( elif mode == 'T':) Tj T* ( self.thcommands = ['calc_pi']) Tj T* ( elif mode == 'S':) Tj T* ( self.commands = ['calc_pi']) Tj T* ( self.n_cpu = multiprocessing.cpu_count\(\)) Tj T* ( ) Tj T* ( def submit_tasks\(self\):) Tj T* ( self.i = plac.Interpreter\(self\).__enter__\(\) ) Tj T* ( return [self.i.submit\('calc_pi %d' % \(self.npoints / self.n_cpu\)\)) Tj T* ( for _ in range\(self.n_cpu\)]) Tj T* T* ( def close\(self\):) Tj T* ( self.i.close\(\)) Tj T* T* ( @plac.annotations\() Tj T* ( npoints=\('npoints', 'positional', None, int\)\)) Tj T* ( def calc_pi\(self, npoints\):) Tj T* ( counts = 0) Tj T* ( for j in xrange\(npoints\):) Tj T* ( n, r = divmod\(j, 1000000\)) Tj T* ( if r == 0:) Tj T* ( yield '%dM iterations' % n) Tj T* ( x, y = random\(\), random\(\)) Tj T* ( if x*x + y*y ) Tj (<) Tj ( 1:) Tj T* ( counts += 1) Tj T* ( yield \(4.0 * counts\)/npoints) Tj T* T* ( def run\(self\):) Tj T* ( tasks = self.i.tasks\(\)) Tj T* ( for t in tasks:) Tj T* ( t.run\(\)) Tj T* ( try:) Tj T* ( total = 0) Tj T* ( for task in tasks:) Tj T* ( total += task.result) Tj T* ( except: # the task was killed) Tj T* ( print tasks) Tj T* ( return) Tj T* ( return total / self.n_cpu) Tj T* T* (if __name__ == '__main__':) Tj T* ( pc = plac.call\(PiCalculator\)) Tj T* ( pc.submit_tasks\(\)) Tj T* ( try:) Tj T* ( import time; t0 = time.time\(\)) Tj T* ( print '%f in %f seconds ' % \(pc.run\(\), time.time\(\) - t0\)) Tj T* ( finally:) Tj T* ( pc.close\(\)) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 371.8236 cm
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 235.3849 0 Td (23) Tj T* -235.3849 0 Td ET
+Q
+Q
+
+endstream
+
+endobj
+% 'R185': class PDFStream
+185 0 obj
+% page stream
+<< /Length 4799 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 693.0236 cm
q
BT 1 0 0 1 0 64.82 Tm .381797 Tw 12 TL /F1 10 Tf 0 0 0 rg (Notice the ) Tj /F4 10 Tf (submit_tasks ) Tj /F1 10 Tf (method, which instantiates and initializes a ) Tj /F4 10 Tf (plac.Interpreter ) Tj /F1 10 Tf (object and) Tj T* 0 Tw 3.38152 Tw (submits a number of commands corresponding to the number of available CPUs. The ) Tj /F4 10 Tf (calc_pi) Tj T* 0 Tw 3.796651 Tw /F1 10 Tf (command yield a log message every million of interactions, just to monitor the progress of the) Tj T* 0 Tw 1.751318 Tw (computation. The ) Tj /F4 10 Tf (run ) Tj /F1 10 Tf (method starts all the submitted commands in parallel and sums the results. It) Tj T* 0 Tw 1.17104 Tw (returns the average value of ) Tj /F4 10 Tf (pi ) Tj /F1 10 Tf (after the slowest CPU has finished its job \(if the CPUs are equal and) Tj T* 0 Tw (equally busy they should finish more or less at the same time\).) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 353.8236 cm
+1 0 0 1 62.69291 675.0236 cm
q
0 0 0 rg
BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (Here are the results on my old Macbook with Ubuntu 10.04 and Python 2.6, for 10 million of iterations:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 260.6236 cm
+1 0 0 1 62.69291 581.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -5919,43 +5864,26 @@ Q
Q
Q
q
-1 0 0 1 62.69291 228.6236 cm
+1 0 0 1 62.69291 549.8236 cm
q
0 0 0 rg
BT 1 0 0 1 0 16.82 Tm /F1 10 Tf 12 TL 1.711751 Tw (As you see using processes one gets a 2x speedup indeed, where the threaded mode is some 20%) Tj T* 0 Tw (slower than the sequential mode.) Tj T* ET
Q
Q
q
-1 0 0 1 56.69291 56.69291 cm
-q
-0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 235.3849 0 Td (23) Tj T* -235.3849 0 Td ET
-Q
-Q
-
-endstream
-
-endobj
-% 'R188': class PDFStream
-188 0 obj
-% page stream
-<< /Length 6437 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
-q
-1 0 0 1 62.69291 744.0236 cm
+1 0 0 1 62.69291 516.8236 cm
q
BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (The plac server) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 630.0236 cm
+1 0 0 1 62.69291 402.8236 cm
q
BT 1 0 0 1 0 100.82 Tm 1.258443 Tw 12 TL /F1 10 Tf 0 0 0 rg (A command-line oriented interface can be easily converted into a socket-based interface. Starting from) Tj T* 0 Tw .930574 Tw (release 0.7 plac features a builtin server which is able to accept commands from multiple clients and to) Tj T* 0 Tw .994692 Tw (execute them. The server works by instantiating a separate interpreter for each client, so that if a client) Tj T* 0 Tw 1.08784 Tw (interpreter dies for any reason the other interpreters keep working. To avoid external dependencies the) Tj T* 0 Tw .872209 Tw (server is based on the ) Tj /F4 10 Tf (asynchat ) Tj /F1 10 Tf (module in the standard library, but it would not be difficult to replace) Tj T* 0 Tw 2.386412 Tw (the server with a different one \(for instance, a Twisted server\). Since ) Tj /F4 10 Tf (asynchat) Tj /F1 10 Tf (-based servers are) Tj T* 0 Tw .755984 Tw (asynchronous, any blocking command in the interpreter should be run in a separated process or thread.) Tj T* 0 Tw 1.157633 Tw (The default port for the ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (server is 2199, and the command to signal end-of-connection is EOF. For) Tj T* 0 Tw (instance, here is how you could manage remote import on a database:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 512.8236 cm
+1 0 0 1 62.69291 309.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -5965,24 +5893,24 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 108 re B*
+n -6 -6 468.6898 84 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 89.71 Tm /F4 10 Tf 12 TL (import plac) Tj T* (from importer2 import FakeImporter) Tj T* (from ishelve2 import ShelveInterface) Tj T* T* (if __name__ == '__main__':) Tj T* ( main = FakeImporter\('dsn'\)) Tj T* ( #main = ShelveInterface\(\)) Tj T* ( plac.Interpreter\(main\).start_server\(\) # default port 2199) Tj T* ET
+BT 1 0 0 1 0 65.71 Tm /F4 10 Tf 12 TL (import plac) Tj T* (from importer2 import FakeImporter) Tj T* T* (if __name__ == '__main__':) Tj T* ( main = FakeImporter\('dsn'\)) Tj T* ( plac.Interpreter\(main\).start_server\(\) # default port 2199) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 492.8236 cm
+1 0 0 1 62.69291 289.6236 cm
q
BT 1 0 0 1 0 4.82 Tm 12 TL /F1 10 Tf 0 0 0 rg (You can connect to the server with ) Tj /F4 10 Tf (telnet ) Tj /F1 10 Tf (on port 2199, as follows:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 315.6236 cm
+1 0 0 1 62.69291 112.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -6002,25 +5930,42 @@ Q
Q
Q
q
-1 0 0 1 62.69291 282.6236 cm
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 235.3849 0 Td (24) Tj T* -235.3849 0 Td ET
+Q
+Q
+
+endstream
+
+endobj
+% 'R186': class PDFStream
+186 0 obj
+% page stream
+<< /Length 7057 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 744.0236 cm
q
BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Summary) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 240.6236 cm
+1 0 0 1 62.69291 702.0236 cm
q
BT 1 0 0 1 0 28.82 Tm 2.203318 Tw 12 TL /F1 10 Tf 0 0 0 rg (Once ) Tj 0 0 .501961 rg (plac ) Tj 0 0 0 rg (claimed to be the easiest command-line arguments parser in the world. Having read this) Tj T* 0 Tw .673322 Tw (document you may think that it is not so easy after all. But it is a false impression. Actually the rules are) Tj T* 0 Tw (quite simple:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 234.6236 cm
+1 0 0 1 62.69291 696.0236 cm
Q
q
-1 0 0 1 62.69291 234.6236 cm
+1 0 0 1 62.69291 696.0236 cm
Q
q
-1 0 0 1 62.69291 216.6236 cm
+1 0 0 1 62.69291 678.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -6040,13 +5985,13 @@ q
Q
Q
q
-1 0 0 1 62.69291 216.6236 cm
+1 0 0 1 62.69291 678.0236 cm
Q
q
-1 0 0 1 62.69291 216.6236 cm
+1 0 0 1 62.69291 678.0236 cm
Q
q
-1 0 0 1 62.69291 156.6236 cm
+1 0 0 1 62.69291 618.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -6124,13 +6069,13 @@ q
Q
Q
q
-1 0 0 1 62.69291 156.6236 cm
+1 0 0 1 62.69291 618.0236 cm
Q
q
-1 0 0 1 62.69291 156.6236 cm
+1 0 0 1 62.69291 618.0236 cm
Q
q
-1 0 0 1 62.69291 126.6236 cm
+1 0 0 1 62.69291 588.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -6150,13 +6095,13 @@ q
Q
Q
q
-1 0 0 1 62.69291 126.6236 cm
+1 0 0 1 62.69291 588.0236 cm
Q
q
-1 0 0 1 62.69291 126.6236 cm
+1 0 0 1 62.69291 588.0236 cm
Q
q
-1 0 0 1 62.69291 96.62362 cm
+1 0 0 1 62.69291 558.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -6176,30 +6121,13 @@ q
Q
Q
q
-1 0 0 1 62.69291 96.62362 cm
+1 0 0 1 62.69291 558.0236 cm
Q
q
-1 0 0 1 62.69291 96.62362 cm
-Q
-q
-1 0 0 1 56.69291 56.69291 cm
-q
-0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 235.3849 0 Td (24) Tj T* -235.3849 0 Td ET
-Q
+1 0 0 1 62.69291 558.0236 cm
Q
-
-endstream
-
-endobj
-% 'R189': class PDFStream
-189 0 obj
-% page stream
-<< /Length 4381 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 735.0236 cm
+1 0 0 1 62.69291 528.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -6219,13 +6147,13 @@ q
Q
Q
q
-1 0 0 1 62.69291 735.0236 cm
+1 0 0 1 62.69291 528.0236 cm
Q
q
-1 0 0 1 62.69291 735.0236 cm
+1 0 0 1 62.69291 528.0236 cm
Q
q
-1 0 0 1 62.69291 705.0236 cm
+1 0 0 1 62.69291 498.0236 cm
0 0 0 rg
BT /F3 10 Tf 12 TL ET
q
@@ -6245,38 +6173,38 @@ q
Q
Q
q
-1 0 0 1 62.69291 705.0236 cm
+1 0 0 1 62.69291 498.0236 cm
Q
q
-1 0 0 1 62.69291 705.0236 cm
+1 0 0 1 62.69291 498.0236 cm
Q
q
-1 0 0 1 62.69291 687.0236 cm
+1 0 0 1 62.69291 480.0236 cm
q
BT 1 0 0 1 0 4.82 Tm 12 TL /F1 10 Tf 0 0 0 rg (Moreover, remember that ) Tj /F4 10 Tf (plac_runner.py ) Tj /F1 10 Tf (is your friend.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 654.0236 cm
+1 0 0 1 62.69291 447.0236 cm
q
BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Appendix: custom annotation objects) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 624.0236 cm
+1 0 0 1 62.69291 417.0236 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 594.0236 cm
+1 0 0 1 62.69291 387.0236 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 464.8236 cm
+1 0 0 1 62.69291 257.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -6297,14 +6225,14 @@ Q
Q
Q
q
-1 0 0 1 62.69291 444.8236 cm
+1 0 0 1 62.69291 237.8236 cm
q
0 0 0 rg
BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (You can use such annotations objects as follows:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 267.6236 cm
+1 0 0 1 62.69291 96.62362 cm
q
q
1 0 0 1 0 0 cm
@@ -6314,25 +6242,35 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 168 re B*
+n -6 -6 468.6898 132 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 149.71 Tm /F4 10 Tf 12 TL (# example11.py) Tj T* (import plac) Tj T* (from annotations import Positional) Tj T* T* (@plac.annotations\() Tj T* ( i=Positional\("This is an int", int\),) Tj T* ( n=Positional\("This is a float", float\),) Tj T* ( rest=Positional\("Other arguments"\)\)) Tj T* (def main\(i, n, *rest\):) Tj T* ( print\(i, n, rest\)) Tj T* T* (if __name__ == '__main__':) Tj T* ( import plac; plac.call\(main\)) Tj T* ET
+BT 1 0 0 1 0 113.71 Tm /F4 10 Tf 12 TL (# example11.py) Tj T* (import plac) Tj T* (from annotations import Positional) Tj T* T* (@plac.annotations\() Tj T* ( i=Positional\("This is an int", int\),) Tj T* ( n=Positional\("This is a float", float\),) Tj T* ( rest=Positional\("Other arguments"\)\)) Tj T* (def main\(i, n, *rest\):) Tj T* ( print\(i, n, rest\)) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 247.6236 cm
+1 0 0 1 56.69291 56.69291 cm
q
0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (Here is the usage message you get:) Tj T* ET
+BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 235.3849 0 Td (25) Tj T* -235.3849 0 Td ET
Q
Q
+
+endstream
+
+endobj
+% 'R187': class PDFStream
+187 0 obj
+% page stream
+<< /Length 1692 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 118.4236 cm
+1 0 0 1 62.69291 715.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -6342,35 +6280,46 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 120 re B*
+n -6 -6 468.6898 48 re B*
Q
q
0 0 0 rg
-BT 1 0 0 1 0 101.71 Tm /F4 10 Tf 12 TL (usage: example11.py [-h] i n [rest [rest ...]]) Tj T* T* (positional arguments:) Tj T* ( i This is an int) Tj T* ( n This is a float) Tj T* ( rest Other arguments) Tj T* T* (optional arguments:) Tj T* ( -h, --help show this help message and exit) Tj T* ET
+BT 1 0 0 1 0 29.71 Tm /F4 10 Tf 12 TL T* (if __name__ == '__main__':) Tj T* ( import plac; plac.call\(main\)) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 56.69291 56.69291 cm
+1 0 0 1 62.69291 695.8236 cm
q
0 0 0 rg
-BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 235.3849 0 Td (25) Tj T* -235.3849 0 Td ET
+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
-
-endstream
-
-endobj
-% 'R190': class PDFStream
-190 0 obj
-% page stream
-<< /Length 698 >>
-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 566.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 120 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 101.71 Tm /F4 10 Tf 12 TL (usage: example11.py [-h] i n [rest [rest ...]]) Tj T* T* (positional arguments:) Tj T* ( i This is an int) Tj T* ( n This is a float) Tj T* ( rest Other arguments) Tj T* T* (optional arguments:) Tj T* ( -h, --help show this help message and exit) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 522.6236 cm
q
BT 1 0 0 1 0 28.82 Tm .713516 Tw 12 TL /F1 10 Tf 0 0 0 rg (You can go on and define ) Tj /F4 10 Tf (Option ) Tj /F1 10 Tf (and ) Tj /F4 10 Tf (Flag ) Tj /F1 10 Tf (classes, if you like. Using custom annotation objects you) Tj T* 0 Tw .17528 Tw (could do advanced things like extracting the annotations from a configuration file or from a database, but I) Tj T* 0 Tw (expect such use cases to be quite rare: the default mechanism should work pretty well for most users.) Tj T* ET
Q
@@ -6386,220 +6335,220 @@ Q
endstream
endobj
-% 'R191': class PDFPageLabels
-191 0 obj
+% 'R188': class PDFPageLabels
+188 0 obj
% Document Root
<< /Nums [ 0
- 192 0 R
+ 189 0 R
1
- 193 0 R
+ 190 0 R
2
- 194 0 R
+ 191 0 R
3
- 195 0 R
+ 192 0 R
4
- 196 0 R
+ 193 0 R
5
- 197 0 R
+ 194 0 R
6
- 198 0 R
+ 195 0 R
7
- 199 0 R
+ 196 0 R
8
- 200 0 R
+ 197 0 R
9
- 201 0 R
+ 198 0 R
10
- 202 0 R
+ 199 0 R
11
- 203 0 R
+ 200 0 R
12
- 204 0 R
+ 201 0 R
13
- 205 0 R
+ 202 0 R
14
- 206 0 R
+ 203 0 R
15
- 207 0 R
+ 204 0 R
16
- 208 0 R
+ 205 0 R
17
- 209 0 R
+ 206 0 R
18
- 210 0 R
+ 207 0 R
19
- 211 0 R
+ 208 0 R
20
- 212 0 R
+ 209 0 R
21
- 213 0 R
+ 210 0 R
22
- 214 0 R
+ 211 0 R
23
- 215 0 R
+ 212 0 R
24
- 216 0 R
+ 213 0 R
25
- 217 0 R ] >>
+ 214 0 R ] >>
+endobj
+% 'R189': class PDFPageLabel
+189 0 obj
+% None
+<< /S /D
+ /St 1 >>
+endobj
+% 'R190': class PDFPageLabel
+190 0 obj
+% None
+<< /S /D
+ /St 2 >>
+endobj
+% 'R191': class PDFPageLabel
+191 0 obj
+% None
+<< /S /D
+ /St 3 >>
endobj
% 'R192': class PDFPageLabel
192 0 obj
% None
<< /S /D
- /St 1 >>
+ /St 4 >>
endobj
% 'R193': class PDFPageLabel
193 0 obj
% None
<< /S /D
- /St 2 >>
+ /St 5 >>
endobj
% 'R194': class PDFPageLabel
194 0 obj
% None
<< /S /D
- /St 3 >>
+ /St 6 >>
endobj
% 'R195': class PDFPageLabel
195 0 obj
% None
<< /S /D
- /St 4 >>
+ /St 7 >>
endobj
% 'R196': class PDFPageLabel
196 0 obj
% None
<< /S /D
- /St 5 >>
+ /St 8 >>
endobj
% 'R197': class PDFPageLabel
197 0 obj
% None
<< /S /D
- /St 6 >>
+ /St 9 >>
endobj
% 'R198': class PDFPageLabel
198 0 obj
% None
<< /S /D
- /St 7 >>
+ /St 10 >>
endobj
% 'R199': class PDFPageLabel
199 0 obj
% None
<< /S /D
- /St 8 >>
+ /St 11 >>
endobj
% 'R200': class PDFPageLabel
200 0 obj
% None
<< /S /D
- /St 9 >>
+ /St 12 >>
endobj
% 'R201': class PDFPageLabel
201 0 obj
% None
<< /S /D
- /St 10 >>
+ /St 13 >>
endobj
% 'R202': class PDFPageLabel
202 0 obj
% None
<< /S /D
- /St 11 >>
+ /St 14 >>
endobj
% 'R203': class PDFPageLabel
203 0 obj
% None
<< /S /D
- /St 12 >>
+ /St 15 >>
endobj
% 'R204': class PDFPageLabel
204 0 obj
% None
<< /S /D
- /St 13 >>
+ /St 16 >>
endobj
% 'R205': class PDFPageLabel
205 0 obj
% None
<< /S /D
- /St 14 >>
+ /St 17 >>
endobj
% 'R206': class PDFPageLabel
206 0 obj
% None
<< /S /D
- /St 15 >>
+ /St 18 >>
endobj
% 'R207': class PDFPageLabel
207 0 obj
% None
<< /S /D
- /St 16 >>
+ /St 19 >>
endobj
% 'R208': class PDFPageLabel
208 0 obj
% None
<< /S /D
- /St 17 >>
+ /St 20 >>
endobj
% 'R209': class PDFPageLabel
209 0 obj
% None
<< /S /D
- /St 18 >>
+ /St 21 >>
endobj
% 'R210': class PDFPageLabel
210 0 obj
% None
<< /S /D
- /St 19 >>
+ /St 22 >>
endobj
% 'R211': class PDFPageLabel
211 0 obj
% None
<< /S /D
- /St 20 >>
+ /St 23 >>
endobj
% 'R212': class PDFPageLabel
212 0 obj
% None
<< /S /D
- /St 21 >>
+ /St 24 >>
endobj
% 'R213': class PDFPageLabel
213 0 obj
% None
<< /S /D
- /St 22 >>
+ /St 25 >>
endobj
% 'R214': class PDFPageLabel
214 0 obj
% None
<< /S /D
- /St 23 >>
-endobj
-% 'R215': class PDFPageLabel
-215 0 obj
-% None
-<< /S /D
- /St 24 >>
-endobj
-% 'R216': class PDFPageLabel
-216 0 obj
-% None
-<< /S /D
- /St 25 >>
-endobj
-% 'R217': class PDFPageLabel
-217 0 obj
-% None
-<< /S /D
/St 26 >>
endobj
xref
-0 218
+0 215
0000000000 65535 f
0000000113 00000 n
0000000257 00000 n
@@ -6646,186 +6595,183 @@ xref
0000009926 00000 n
0000010170 00000 n
0000010414 00000 n
-0000010658 00000 n
-0000010902 00000 n
-0000011145 00000 n
-0000011397 00000 n
-0000011634 00000 n
-0000012327 00000 n
-0000012579 00000 n
-0000012831 00000 n
-0000013083 00000 n
-0000013326 00000 n
-0000013578 00000 n
-0000013830 00000 n
-0000014082 00000 n
-0000014334 00000 n
-0000014591 00000 n
-0000014981 00000 n
-0000015218 00000 n
-0000015521 00000 n
-0000015818 00000 n
-0000016070 00000 n
-0000016322 00000 n
-0000016574 00000 n
-0000016834 00000 n
-0000017086 00000 n
-0000017347 00000 n
-0000017598 00000 n
-0000017859 00000 n
-0000018111 00000 n
-0000018348 00000 n
-0000018747 00000 n
-0000018998 00000 n
-0000019234 00000 n
-0000019561 00000 n
-0000019833 00000 n
-0000020085 00000 n
-0000020337 00000 n
-0000020574 00000 n
-0000020919 00000 n
-0000021171 00000 n
-0000021423 00000 n
-0000021667 00000 n
-0000022003 00000 n
-0000022240 00000 n
-0000022558 00000 n
-0000022814 00000 n
-0000023066 00000 n
-0000023317 00000 n
-0000023569 00000 n
-0000023828 00000 n
-0000024073 00000 n
-0000024436 00000 n
-0000024686 00000 n
-0000024937 00000 n
-0000025187 00000 n
-0000025439 00000 n
-0000025692 00000 n
-0000025945 00000 n
-0000026198 00000 n
-0000026438 00000 n
-0000026824 00000 n
-0000027061 00000 n
-0000027381 00000 n
-0000027634 00000 n
-0000027887 00000 n
-0000028139 00000 n
-0000028391 00000 n
-0000028644 00000 n
-0000028897 00000 n
-0000029150 00000 n
-0000029389 00000 n
-0000029779 00000 n
-0000030018 00000 n
-0000030324 00000 n
-0000030622 00000 n
-0000030860 00000 n
-0000031180 00000 n
-0000031453 00000 n
-0000031692 00000 n
-0000032023 00000 n
-0000032277 00000 n
-0000032516 00000 n
-0000032832 00000 n
+0000010657 00000 n
+0000010909 00000 n
+0000011146 00000 n
+0000011821 00000 n
+0000012073 00000 n
+0000012325 00000 n
+0000012577 00000 n
+0000012820 00000 n
+0000013072 00000 n
+0000013324 00000 n
+0000013576 00000 n
+0000013828 00000 n
+0000014085 00000 n
+0000014475 00000 n
+0000014712 00000 n
+0000015015 00000 n
+0000015312 00000 n
+0000015564 00000 n
+0000015816 00000 n
+0000016068 00000 n
+0000016328 00000 n
+0000016580 00000 n
+0000016841 00000 n
+0000017092 00000 n
+0000017353 00000 n
+0000017605 00000 n
+0000017842 00000 n
+0000018241 00000 n
+0000018492 00000 n
+0000018728 00000 n
+0000019055 00000 n
+0000019327 00000 n
+0000019579 00000 n
+0000019831 00000 n
+0000020068 00000 n
+0000020413 00000 n
+0000020665 00000 n
+0000020917 00000 n
+0000021161 00000 n
+0000021497 00000 n
+0000021734 00000 n
+0000022052 00000 n
+0000022308 00000 n
+0000022560 00000 n
+0000022811 00000 n
+0000023063 00000 n
+0000023322 00000 n
+0000023567 00000 n
+0000023930 00000 n
+0000024180 00000 n
+0000024431 00000 n
+0000024681 00000 n
+0000024933 00000 n
+0000025185 00000 n
+0000025437 00000 n
+0000025690 00000 n
+0000025930 00000 n
+0000026314 00000 n
+0000026551 00000 n
+0000026871 00000 n
+0000027124 00000 n
+0000027377 00000 n
+0000027630 00000 n
+0000027883 00000 n
+0000028136 00000 n
+0000028387 00000 n
+0000028640 00000 n
+0000028879 00000 n
+0000029255 00000 n
+0000029553 00000 n
+0000029792 00000 n
+0000030098 00000 n
+0000030396 00000 n
+0000030634 00000 n
+0000030954 00000 n
+0000031226 00000 n
+0000031479 00000 n
+0000031718 00000 n
+0000032059 00000 n
+0000032298 00000 n
+0000032619 00000 n
+0000032873 00000 n
0000033131 00000 n
-0000033385 00000 n
-0000033643 00000 n
-0000033974 00000 n
-0000034228 00000 n
-0000034467 00000 n
-0000034783 00000 n
-0000035067 00000 n
-0000035366 00000 n
-0000035620 00000 n
-0000035859 00000 n
-0000036190 00000 n
-0000036429 00000 n
-0000036735 00000 n
-0000037020 00000 n
-0000037184 00000 n
-0000037438 00000 n
-0000037567 00000 n
-0000037743 00000 n
-0000037963 00000 n
-0000038169 00000 n
-0000038364 00000 n
-0000038562 00000 n
-0000038766 00000 n
-0000038962 00000 n
-0000039158 00000 n
-0000039378 00000 n
-0000039585 00000 n
-0000039795 00000 n
-0000039998 00000 n
-0000040197 00000 n
-0000040417 00000 n
-0000040641 00000 n
-0000040851 00000 n
-0000041048 00000 n
-0000041237 00000 n
-0000041422 00000 n
-0000041774 00000 n
-0000051079 00000 n
-0000056632 00000 n
-0000060776 00000 n
-0000066440 00000 n
-0000072692 00000 n
-0000078048 00000 n
-0000082470 00000 n
-0000086862 00000 n
-0000090708 00000 n
-0000095346 00000 n
-0000101209 00000 n
-0000106144 00000 n
-0000111123 00000 n
-0000114442 00000 n
-0000118622 00000 n
-0000124896 00000 n
-0000129123 00000 n
-0000134076 00000 n
-0000138989 00000 n
-0000143684 00000 n
-0000148751 00000 n
-0000152283 00000 n
-0000155540 00000 n
-0000162080 00000 n
-0000166564 00000 n
-0000167368 00000 n
-0000167830 00000 n
-0000167909 00000 n
-0000167988 00000 n
-0000168067 00000 n
-0000168146 00000 n
-0000168225 00000 n
-0000168304 00000 n
-0000168383 00000 n
-0000168462 00000 n
-0000168541 00000 n
-0000168621 00000 n
-0000168701 00000 n
-0000168781 00000 n
-0000168861 00000 n
-0000168941 00000 n
-0000169021 00000 n
-0000169101 00000 n
-0000169181 00000 n
-0000169261 00000 n
-0000169341 00000 n
-0000169421 00000 n
-0000169501 00000 n
-0000169581 00000 n
-0000169661 00000 n
-0000169741 00000 n
-0000169821 00000 n
+0000033462 00000 n
+0000033701 00000 n
+0000034022 00000 n
+0000034261 00000 n
+0000034567 00000 n
+0000034866 00000 n
+0000035105 00000 n
+0000035426 00000 n
+0000035680 00000 n
+0000035919 00000 n
+0000036235 00000 n
+0000036520 00000 n
+0000036684 00000 n
+0000036938 00000 n
+0000037067 00000 n
+0000037243 00000 n
+0000037463 00000 n
+0000037669 00000 n
+0000037864 00000 n
+0000038062 00000 n
+0000038266 00000 n
+0000038462 00000 n
+0000038658 00000 n
+0000038864 00000 n
+0000039074 00000 n
+0000039277 00000 n
+0000039476 00000 n
+0000039696 00000 n
+0000039920 00000 n
+0000040130 00000 n
+0000040327 00000 n
+0000040516 00000 n
+0000040701 00000 n
+0000041053 00000 n
+0000050435 00000 n
+0000055843 00000 n
+0000060129 00000 n
+0000065526 00000 n
+0000071778 00000 n
+0000077134 00000 n
+0000081556 00000 n
+0000085948 00000 n
+0000089794 00000 n
+0000094432 00000 n
+0000100295 00000 n
+0000105230 00000 n
+0000110369 00000 n
+0000113559 00000 n
+0000117346 00000 n
+0000120871 00000 n
+0000126958 00000 n
+0000131344 00000 n
+0000136786 00000 n
+0000141884 00000 n
+0000147062 00000 n
+0000151797 00000 n
+0000154392 00000 n
+0000159294 00000 n
+0000166454 00000 n
+0000168253 00000 n
+0000168715 00000 n
+0000168794 00000 n
+0000168873 00000 n
+0000168952 00000 n
+0000169031 00000 n
+0000169110 00000 n
+0000169189 00000 n
+0000169268 00000 n
+0000169347 00000 n
+0000169426 00000 n
+0000169506 00000 n
+0000169586 00000 n
+0000169666 00000 n
+0000169746 00000 n
+0000169826 00000 n
+0000169906 00000 n
+0000169986 00000 n
+0000170066 00000 n
+0000170146 00000 n
+0000170226 00000 n
+0000170306 00000 n
+0000170386 00000 n
+0000170466 00000 n
+0000170546 00000 n
+0000170626 00000 n
+0000170706 00000 n
trailer
<< /ID
% ReportLab generated PDF document -- digest (http://www.reportlab.com)
- [(\304n@JE\214\371#\356\257O\34599\262\256) (\304n@JE\214\371#\356\257O\34599\262\256)]
+ [(\270\205\223\242_\260\304s\324\201\036t\\;\334\337) (\270\205\223\242_\260\304s\324\201\036t\\;\334\337)]
- /Info 143 0 R
- /Root 142 0 R
- /Size 218 >>
+ /Info 141 0 R
+ /Root 140 0 R
+ /Size 215 >>
startxref
-169870
+170755
%%EOF
diff --git a/plac/doc/plac_adv.txt b/plac/doc/plac_adv.txt
index b909dfe..b867231 100644
--- a/plac/doc/plac_adv.txt
+++ b/plac/doc/plac_adv.txt
@@ -3,7 +3,7 @@ Advanced usages of plac
:Author: Michele Simionato
:E-mail: michele.simionato@gmail.com
-:Date: July 2010
+:Date: August 2010
:Download page: http://pypi.python.org/pypi/plac
:Project page: http://micheles.googlecode.com/hg/plac/doc/plac.html
:Installation: ``easy_install -U plac``
@@ -593,54 +593,55 @@ Here is an example::
$ plac ishelve.py .show
a=1
-Notice that it non-interactive mode the runner just invokes ``plac.call``
+Notice that in non-interactive mode the runner just invokes ``plac.call``
on the ``main`` object of the Python module.
-Multiline support and Emacs integration
---------------------------------------------------------
-
-plac_ is optimized for the simplest use case and by default it provide
-support for simple command-line languages where a command take
-a single line. This is the simplest case: it is easy to keep
-track of the line number and to print it in the error message, if
-there is some error in a plac_ script. Starting from release 0.7
-plac_ is beginning to support multiline input: it is now possible
-to define command-line languages with commands spanning multiple
-lines. The topical use case is the implementation of a tool
-to interact with a relational database: the tool must be able to send
-complex SQL queries spanning multiple lines to the backend.
-To support multiline input the ``Interpreter`` class provides
-a method ``multiline(stdin=sys.stdin, terminator=';', verbose=False)``
-which reads input from ``stdin`` until the terminator character
-(by default a semicolon) is reached.
-
-Since the Python readline module does not expose the
-multiline functionality of the underlying C library (which is there),
-plac_ multiline mode does not have readline functionality. This is
-not a big deal really, because if you are writing multiple line
-commands you don't really want to type them at the command-line. It is
-much better to use a real editor to type them, and to call plac_ from
-the editor. Since I use Emacs I will give the recipe to integrate
-Emacs with plac_: something equivalent can be done for vi and for
-other editors/IDEs.
-
-The multiline mode can be enabled by invoking the plac_ runner with
-the ``-m`` option. Since the multiline mode is intended for use with
-Emacs in inferior mode, it does not print any prompt. Here is an example
-of usage::
-
- $ plac -m ishelve2.py
- set a 1;
- setting a=1
- show a;
- a = 1
-
-To integrate plac_ with Emacs, enters the following lines in your
-.emacs:
-
-.. include:: plac.el
- :literal:
-
+..
+
+ Multiline support and Emacs integration
+
+ plac_ is optimized for the simplest use case and by default it provide
+ support for simple command-line languages where a command take
+ a single line. This is the simplest case: it is easy to keep
+ track of the line number and to print it in the error message, if
+ there is some error in a plac_ script. Starting from release 0.7
+ plac_ is beginning to support multiline input: it is now possible
+ to define command-line languages with commands spanning multiple
+ lines. The topical use case is the implementation of a tool
+ to interact with a relational database: the tool must be able to send
+ complex SQL queries spanning multiple lines to the backend.
+ To support multiline input the ``Interpreter`` class provides
+ a method ``multiline(stdin=sys.stdin, terminator=';', verbose=False)``
+ which reads input from ``stdin`` until the terminator character
+ (by default a semicolon) is reached.
+
+ Since the Python readline module does not expose the
+ multiline functionality of the underlying C library (which is there),
+ plac_ multiline mode does not have readline functionality. This is
+ not a big deal really, because if you are writing multiple line
+ commands you don't really want to type them at the command-line. It is
+ much better to use a real editor to type them, and to call plac_ from
+ the editor. Since I use Emacs I will give the recipe to integrate
+ Emacs with plac_: something equivalent can be done for vi and for
+ other editors/IDEs.
+
+ The multiline mode can be enabled by invoking the plac_ runner with
+ the ``-m`` option. Since the multiline mode is intended for use with
+ Emacs in inferior mode, it does not print any prompt. Here is an example
+ of usage::
+
+ $ plac -m ishelve2.py
+ set a 1;
+ setting a=1
+ show a;
+ a = 1
+
+ To integrate plac_ with Emacs, enters the following lines in your
+ .emacs:
+
+ .. include:: plac.el
+ :literal:
+
A non class-based example
--------------------------------------------------------
diff --git a/plac/doc/server_ex.py b/plac/doc/server_ex.py
index f13bb53..e3d76ec 100644
--- a/plac/doc/server_ex.py
+++ b/plac/doc/server_ex.py
@@ -1,8 +1,9 @@
import plac
from importer2 import FakeImporter
-from ishelve2 import ShelveInterface
-if __name__ == '__main__':
+def main(port=2199):
main = FakeImporter('dsn')
- #main = ShelveInterface()
- plac.Interpreter(main).start_server() # default port 2199
+ plac.Interpreter(main).start_server(port)
+
+if __name__ == '__main__':
+ plac.call(main)
diff --git a/plac/doc/test_server.py b/plac/doc/test_server.py
index 5567f40..dd14e5c 100644
--- a/plac/doc/test_server.py
+++ b/plac/doc/test_server.py
@@ -10,6 +10,7 @@ set a 1
''',
'''\
set b 1
+wrong command
showall
''']
diff --git a/plac/plac_ext.py b/plac/plac_ext.py
index 99bc96c..3490f74 100644
--- a/plac/plac_ext.py
+++ b/plac/plac_ext.py
@@ -101,6 +101,7 @@ class ReadlineInput(object):
readline.set_completer(self.complete)
def __enter__(self):
+ self.old_completer = readline.get_completer()
try:
if self.histfile:
readline.read_history_file(self.histfile)
@@ -109,6 +110,7 @@ class ReadlineInput(object):
return self
def __exit__(self, etype, exc, tb):
+ readline.set_completer(self.old_completer)
if self.histfile:
readline.write_history_file(self.histfile)
@@ -548,7 +550,7 @@ class _AsynHandler(asynchat.async_chat):
task = self.i.submit(line)
task.run() # synchronous or not
if task.etype: # manage exception
- error = '%s: %s on command %s%s' % (
+ error = '%s: %s\nReceived: %s' % (
task.etype.__name__, task.exc, ' '.join(task.arglist))
self.log_info(task.traceback + error) # on the server
self.write(error + self.terminator) # back to the client