http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d4b154cb/examples/engine/py/_build/html/tutorial.html ---------------------------------------------------------------------- diff --git a/examples/engine/py/_build/html/tutorial.html b/examples/engine/py/_build/html/tutorial.html new file mode 100644 index 0000000..049fd8a --- /dev/null +++ b/examples/engine/py/_build/html/tutorial.html @@ -0,0 +1,495 @@ + + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + + +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + + <title>Hello World! — Proton 0.9-alpha documentation</title> + + <link rel="stylesheet" href="_static/default.css" type="text/css" /> + <link rel="stylesheet" href="_static/pygments.css" type="text/css" /> + + <script type="text/javascript"> + var DOCUMENTATION_OPTIONS = { + URL_ROOT: '', + VERSION: '0.9-alpha', + COLLAPSE_INDEX: false, + FILE_SUFFIX: '.html', + HAS_SOURCE: true + }; + </script> + <script type="text/javascript" src="_static/jquery.js"></script> + <script type="text/javascript" src="_static/underscore.js"></script> + <script type="text/javascript" src="_static/doctools.js"></script> + <link rel="top" title="Proton 0.9-alpha documentation" href="index.html" /> + <link rel="prev" title="Some Proton Examples" href="index.html" /> + </head> + <body> + <div class="related"> + <h3>Navigation</h3> + <ul> + <li class="right" style="margin-right: 10px"> + <a href="genindex.html" title="General Index" + accesskey="I">index</a></li> + <li class="right" > + <a href="index.html" title="Some Proton Examples" + accesskey="P">previous</a> |</li> + <li><a href="index.html">Proton 0.9-alpha documentation</a> »</li> + </ul> + </div> + + <div class="document"> + <div class="documentwrapper"> + <div class="body"> + + <div class="section" id="hello-world"> +<h1>Hello World!<a class="headerlink" href="#hello-world" title="Permalink to this headline">¶</a></h1> +<p>Tradition dictates that we start with hello world! However rather than +simply striving for the shortest program possible, we’ll aim for a +more illustrative example while still restricting the functionality to +sending and receiving a single message.</p> +<div class="highlight-python"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22</pre></div></td><td class="code"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">proton</span> <span class="kn">import</span> <span class="n">Message</span> +<span class="kn">import</span> <span class="nn">proton_events</span> + +<span class="k">class</span> <span class="nc">HelloWorld</span><span class="p">(</span><span class="n">proton_events</span><span class="o">.</span><span class="n">ClientHandler</span><span class="p">):</span> + <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">server</span><span class="p">,</span> <span class="n">address</span><span class="p">):</span> + <span class="bp">self</span><span class="o">.</span><span class="n">address</span> <span class="o">=</span> <span class="n">address</span> + <span class="bp">self</span><span class="o">.</span><span class="n">conn</span> <span class="o">=</span> <span class="n">proton_events</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">server</span><span class="p">,</span> <span class="n">handler</span><span class="o">=</span><span class="bp">self</span><span class="p">)</span> + + <span class="k">def</span> <span class="nf">on_connection_opened</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="bp">self</span><span class="o">.</span><span class="n">conn</span><span class="o">.</span><span class="n">create_receiver</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">address</span><span class="p">)</span> + <span class="bp">self</span><span class="o">.</span><span class="n">conn</span><span class="o">.</span><span class="n">create_sender</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">address</span><span class="p">)</span> + + <span class="k">def</span> <span class="nf">on_credit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="n">event</span><span class="o">.</span><span class="n">sender</span><span class="o">.</span><span class="n">send_msg</span><span class="p">(</span><span class="n">Message</span><span class="p">(</span><span class="n">body</span><span class="o">=</span><span class="s">u"Hello World!"</span><span class="p">))</span> + <span class="n">event</span><span class="o">.</span><span class="n">sender</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> + + <span class="k">def</span> <span class="nf">on_message</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="k">print</span> <span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">body</span> + <span class="n">event</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> + +<span class="n">HelloWorld</span><span class="p">(</span><span class="s">"localhost:5672"</span><span class="p">,</span> <span class="s">"examples"</span><span class="p">)</span> +<span class="n">proton_events</span><span class="o">.</span><span class="n">run</span><span class="p">()</span> +</pre></div> +</td></tr></table></div> +<p>This example uses proton in an event-driven or reactive manner. The +flow of control is an ‘event loop’, where the events may be triggered +by data arriving on a socket among other things and are then passed to +relevant ‘handlers’. Applications are then structured as a set of +defined handlers for events of interest; to be notified of a +particular event, you define a class with an appropriately name method +on it, inform the event loop of that method which then calls it +whenever the event occurs.</p> +<p>The class we define in this example, <tt class="docutils literal"><span class="pre">HelloWorld</span></tt>, has methods to +handle three types of events.</p> +<p>The first, <tt class="docutils literal"><span class="pre">on_connection_opened()</span></tt>, is called when the connection +is opened, and when that occurs we create a receiver over which to +receive our message and a sender over which to send it.</p> +<p>The second method, <tt class="docutils literal"><span class="pre">on_credit()</span></tt>, is called when our sender has been +issued by the peer with ‘credit’, allowing it to send messages. A +credit based flow control mechanism like this ensures we only send +messages when the recipient is ready and able to receive them. This is +particularly important when the volume of messages might be large. In +our case we are just going to send one message.</p> +<p>The third and final method, <tt class="docutils literal"><span class="pre">on_message()</span></tt>, is called when a message +arrives. Within that method we simply print the body of the message +and then close the connection.</p> +<p>This particular example assumes a broker (or similar service), which +accepts connections and routes published messages to intended +recipients. The constructor for the <tt class="docutils literal"><span class="pre">HelloWorld</span></tt> class takes the +details of the broker to connect to, and the address through which the +message is sent and received (for a broker this corresponds to a queue +or topic name).</p> +<p>After an instance of <tt class="docutils literal"><span class="pre">HelloWorld</span></tt> is constructed, the event loop is +entered by the call to the <tt class="docutils literal"><span class="pre">run()</span></tt> method on the last line. This +call will return only when the loop determines there are no more +events possible (at which point our example program will then exit).</p> +</div> +<div class="section" id="hello-world-direct"> +<h1>Hello World, Direct!<a class="headerlink" href="#hello-world-direct" title="Permalink to this headline">¶</a></h1> +<p>Though often used in conjunction with a broker, AMQP does not +<em>require</em> this. It also allows senders and receivers can communicate +directly if desired.</p> +<p>Let’s modify our example to demonstrate this.</p> +<div class="highlight-python"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33</pre></div></td><td class="code"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">proton</span> <span class="kn">import</span> <span class="n">Message</span> +<span class="kn">from</span> <span class="nn">proton_events</span> <span class="kn">import</span> <span class="n">ClientHandler</span><span class="p">,</span> <span class="n">EventLoop</span><span class="p">,</span> <span class="n">FlowController</span><span class="p">,</span> <span class="n">Handshaker</span><span class="p">,</span> <span class="n">IncomingMessageHandler</span> + +<span class="k">class</span> <span class="nc">HelloWorldReceiver</span><span class="p">(</span><span class="n">IncomingMessageHandler</span><span class="p">):</span> + <span class="k">def</span> <span class="nf">on_message</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="k">print</span> <span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">body</span> + <span class="n">event</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> + +<span class="k">class</span> <span class="nc">HelloWorld</span><span class="p">(</span><span class="n">ClientHandler</span><span class="p">):</span> + <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">eventloop</span><span class="p">,</span> <span class="n">url</span><span class="p">,</span> <span class="n">address</span><span class="p">):</span> + <span class="bp">self</span><span class="o">.</span><span class="n">eventloop</span> <span class="o">=</span> <span class="n">eventloop</span> + <span class="bp">self</span><span class="o">.</span><span class="n">acceptor</span> <span class="o">=</span> <span class="n">eventloop</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="n">url</span><span class="p">)</span> + <span class="bp">self</span><span class="o">.</span><span class="n">conn</span> <span class="o">=</span> <span class="n">eventloop</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">handler</span><span class="o">=</span><span class="bp">self</span><span class="p">)</span> + <span class="bp">self</span><span class="o">.</span><span class="n">address</span> <span class="o">=</span> <span class="n">address</span> + + <span class="k">def</span> <span class="nf">on_connection_opened</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> +<span class="hll"> <span class="bp">self</span><span class="o">.</span><span class="n">conn</span><span class="o">.</span><span class="n">create_sender</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">address</span><span class="p">)</span> +</span> + <span class="k">def</span> <span class="nf">on_credit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="n">event</span><span class="o">.</span><span class="n">sender</span><span class="o">.</span><span class="n">send_msg</span><span class="p">(</span><span class="n">Message</span><span class="p">(</span><span class="n">body</span><span class="o">=</span><span class="s">u"Hello World!"</span><span class="p">))</span> + <span class="n">event</span><span class="o">.</span><span class="n">sender</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> + + <span class="k">def</span> <span class="nf">on_accepted</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="bp">self</span><span class="o">.</span><span class="n">conn</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> + + <span class="k">def</span> <span class="nf">on_connection_closed</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="bp">self</span><span class="o">.</span><span class="n">acceptor</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> + + <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> + <span class="bp">self</span><span class="o">.</span><span class="n">eventloop</span><span class="o">.</span><span class="n">run</span><span class="p">()</span> + +<span class="n">eventloop</span> <span class="o">=</span> <span class="n">EventLoop</span><span class="p">(</span><span class="n">HelloWorldReceiver</span><span class="p">(),</span> <span class="n">Handshaker</span><span class="p">(),</span> <span class="n">FlowController</span><span class="p">(</span><span class="mi">1</span><span class="p">))</span> +<span class="hll"><span class="n">HelloWorld</span><span class="p">(</span><span class="n">eventloop</span><span class="p">,</span> <span class="s">"localhost:8888"</span><span class="p">,</span> <span class="s">"examples"</span><span class="p">)</span><span class="o">.</span><span class="n">run</span><span class="p">()</span> +</span></pre></div> +</td></tr></table></div> +<p>The first difference, on line 17, is that rather than creating a +receiver on the same connection as our sender, we listen for incoming +connections by invoking the <tt class="docutils literal"><span class="pre">listen()</span> <span class="pre">method</span> <span class="pre">on</span> <span class="pre">the</span> <span class="pre">``EventLoop</span></tt> +instance.</p> +<p>Another difference is that the <tt class="docutils literal"><span class="pre">EventLoop</span></tt> instance we use is not +the default instance as was used in the original example, but one we +construct ourselves on line 38, passing in some event handlers. The +first of these is <tt class="docutils literal"><span class="pre">HelloWorldReceiver</span></tt>, as used in the original +example. We pass it to the event loop, because we aren’t going to +directly create the receiver here ourselves. Rather we will accept an +incoming connection on which the message will be received. This +handler would then be notified of any incoming message event on any of +the connections the event loop controls. As well as our own handler, we +specify a couple of useful handlers from the <tt class="docutils literal"><span class="pre">proton_events</span></tt> +toolkit. The <tt class="docutils literal"><span class="pre">Handshaker</span></tt> handler will ensure our server follows the +basic handshaking rules laid down by the protocol. The +<tt class="docutils literal"><span class="pre">FlowController</span></tt> will issue credit for incoming messages. We won’t +worry about them in more detail than that for now.</p> +<p>The last difference is that we close the <tt class="docutils literal"><span class="pre">acceptor</span></tt> returned from +the <tt class="docutils literal"><span class="pre">listen()</span></tt> call as part of the handling of the connection close +event (line 33).</p> +<p>So now we have our example working without a broker involved!</p> +</div> +<div class="section" id="the-basics"> +<h1>The Basics<a class="headerlink" href="#the-basics" title="Permalink to this headline">¶</a></h1> +<p>TODO: These examples show reliable (at-least-once) send and receive +with reconnect ability. Need to write some explanation. Could also do +with some further cleanup.</p> +<div class="highlight-python"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11</pre></div></td><td class="code"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">proton_events</span> + +<span class="k">class</span> <span class="nc">Recv</span><span class="p">(</span><span class="n">proton_events</span><span class="o">.</span><span class="n">ClientHandler</span><span class="p">):</span> + <span class="k">def</span> <span class="nf">on_message</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="k">print</span> <span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">body</span> + +<span class="k">try</span><span class="p">:</span> + <span class="n">conn</span> <span class="o">=</span> <span class="n">proton_events</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="s">"localhost:5672"</span><span class="p">,</span> <span class="n">handler</span><span class="o">=</span><span class="n">Recv</span><span class="p">())</span> + <span class="n">conn</span><span class="o">.</span><span class="n">create_receiver</span><span class="p">(</span><span class="s">"examples"</span><span class="p">)</span> + <span class="n">proton_events</span><span class="o">.</span><span class="n">run</span><span class="p">()</span> +<span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span> <span class="k">pass</span> +</pre></div> +</td></tr></table></div> +<div class="highlight-python"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29</pre></div></td><td class="code"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">proton</span> <span class="kn">import</span> <span class="n">Message</span> +<span class="kn">import</span> <span class="nn">proton_events</span> + +<span class="k">class</span> <span class="nc">Send</span><span class="p">(</span><span class="n">proton_events</span><span class="o">.</span><span class="n">ClientHandler</span><span class="p">):</span> + <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">messages</span><span class="p">):</span> + <span class="bp">self</span><span class="o">.</span><span class="n">sent</span> <span class="o">=</span> <span class="mi">0</span> + <span class="bp">self</span><span class="o">.</span><span class="n">confirmed</span> <span class="o">=</span> <span class="mi">0</span> + <span class="bp">self</span><span class="o">.</span><span class="n">total</span> <span class="o">=</span> <span class="n">messages</span> + + <span class="k">def</span> <span class="nf">on_credit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="k">while</span> <span class="n">event</span><span class="o">.</span><span class="n">link</span><span class="o">.</span><span class="n">credit</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">sent</span> <span class="o"><</span> <span class="bp">self</span><span class="o">.</span><span class="n">total</span><span class="p">:</span> + <span class="n">msg</span> <span class="o">=</span> <span class="n">Message</span><span class="p">(</span><span class="n">body</span><span class="o">=</span><span class="p">{</span><span class="s">'sequence'</span><span class="p">:(</span><span class="bp">self</span><span class="o">.</span><span class="n">sent</span><span class="o">+</span><span class="mi">1</span><span class="p">)})</span> + <span class="n">event</span><span class="o">.</span><span class="n">link</span><span class="o">.</span><span class="n">send_msg</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span> + <span class="bp">self</span><span class="o">.</span><span class="n">sent</span> <span class="o">+=</span> <span class="mi">1</span> + + <span class="k">def</span> <span class="nf">on_accepted</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="bp">self</span><span class="o">.</span><span class="n">confirmed</span> <span class="o">+=</span> <span class="mi">1</span> + <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">confirmed</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">total</span><span class="p">:</span> + <span class="k">print</span> <span class="s">"all messages confirmed"</span> + <span class="n">event</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> + + <span class="k">def</span> <span class="nf">on_disconnected</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="bp">self</span><span class="o">.</span><span class="n">sent</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">confirmed</span> + +<span class="k">try</span><span class="p">:</span> + <span class="n">conn</span> <span class="o">=</span> <span class="n">proton_events</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="s">"localhost:5672"</span><span class="p">,</span> <span class="n">handler</span><span class="o">=</span><span class="n">Send</span><span class="p">(</span><span class="mi">10000</span><span class="p">))</span> + <span class="n">conn</span><span class="o">.</span><span class="n">create_sender</span><span class="p">(</span><span class="s">"examples"</span><span class="p">)</span> + <span class="n">proton_events</span><span class="o">.</span><span class="n">run</span><span class="p">()</span> +<span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span> <span class="k">pass</span> +</pre></div> +</td></tr></table></div> +</div> +<div class="section" id="request-response"> +<h1>Request/Response<a class="headerlink" href="#request-response" title="Permalink to this headline">¶</a></h1> +<p>A common pattern is to send a request message and expect a response +message in return. AMQP has special support for this pattern. Let’s +have a look at a simple example. We’ll start with the ‘server’, +i.e. the program that will process the request and send the +response. Note that we are still using a broker in this example.</p> +<p>Our server will provide a very simple service: it will respond with +the body of the request converted to uppercase.</p> +<div class="highlight-python"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30</pre></div></td><td class="code"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">proton</span> <span class="kn">import</span> <span class="n">Message</span> +<span class="kn">from</span> <span class="nn">proton_events</span> <span class="kn">import</span> <span class="n">EventLoop</span><span class="p">,</span> <span class="n">ClientHandler</span> + +<span class="k">class</span> <span class="nc">Server</span><span class="p">(</span><span class="n">ClientHandler</span><span class="p">):</span> + <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">eventloop</span><span class="p">,</span> <span class="n">host</span><span class="p">,</span> <span class="n">address</span><span class="p">):</span> + <span class="bp">self</span><span class="o">.</span><span class="n">eventloop</span> <span class="o">=</span> <span class="n">eventloop</span> + <span class="bp">self</span><span class="o">.</span><span class="n">conn</span> <span class="o">=</span> <span class="n">eventloop</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="n">handler</span><span class="o">=</span><span class="bp">self</span><span class="p">)</span> + <span class="bp">self</span><span class="o">.</span><span class="n">receiver</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">conn</span><span class="o">.</span><span class="n">create_receiver</span><span class="p">(</span><span class="n">address</span><span class="p">,</span> <span class="n">handler</span><span class="o">=</span><span class="bp">self</span><span class="p">)</span> + <span class="bp">self</span><span class="o">.</span><span class="n">senders</span> <span class="o">=</span> <span class="p">{}</span> + <span class="bp">self</span><span class="o">.</span><span class="n">relay</span> <span class="o">=</span> <span class="bp">None</span> + + <span class="k">def</span> <span class="nf">on_message</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="n">sender</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">relay</span> + <span class="k">if</span> <span class="ow">not</span> <span class="n">sender</span><span class="p">:</span> + <span class="n">sender</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">senders</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">reply_to</span><span class="p">)</span> + <span class="k">if</span> <span class="ow">not</span> <span class="n">sender</span><span class="p">:</span> + <span class="n">sender</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">conn</span><span class="o">.</span><span class="n">create_sender</span><span class="p">(</span><span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">reply_to</span><span class="p">)</span> + <span class="bp">self</span><span class="o">.</span><span class="n">senders</span><span class="p">[</span><span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">reply_to</span><span class="p">]</span> <span class="o">=</span> <span class="n">sender</span> + <span class="n">sender</span><span class="o">.</span><span class="n">send_msg</span><span class="p">(</span><span class="n">Message</span><span class="p">(</span><span class="n">address</span><span class="o">=</span><span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">reply_to</span><span class="p">,</span> <span class="n">body</span><span class="o">=</span><span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">body</span><span class="o">.</span><span class="n">upper</span><span class="p">()))</span> + + <span class="k">def</span> <span class="nf">on_connection_opened</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">remote_offered_capabilities</span> <span class="ow">and</span> <span class="s">'ANONYMOUS-RELAY'</span> <span class="ow">in</span> <span class="n">event</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">remote_offered_capabilities</span><span class="p">:</span> + <span class="bp">self</span><span class="o">.</span><span class="n">relay</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">conn</span><span class="o">.</span><span class="n">create_sender</span><span class="p">(</span><span class="bp">None</span><span class="p">)</span> + + <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> + <span class="bp">self</span><span class="o">.</span><span class="n">eventloop</span><span class="o">.</span><span class="n">run</span><span class="p">()</span> + +<span class="k">try</span><span class="p">:</span> + <span class="n">Server</span><span class="p">(</span><span class="n">EventLoop</span><span class="p">(),</span> <span class="s">"localhost:5672"</span><span class="p">,</span> <span class="s">"examples"</span><span class="p">)</span><span class="o">.</span><span class="n">run</span><span class="p">()</span> +<span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span> <span class="k">pass</span> +</pre></div> +</td></tr></table></div> +<p>The code here is not too different from the simple receiver example. When +we receive a request however, we look at the reply-to address and +create a sender for that over which to send the response. We’ll cache +the senders incase we get further requests wit the same reply-to.</p> +<p>Now let’s create a simple client to test this service out.</p> +<div class="highlight-python"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34</pre></div></td><td class="code"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">proton</span> <span class="kn">import</span> <span class="n">Message</span> +<span class="kn">from</span> <span class="nn">proton_events</span> <span class="kn">import</span> <span class="n">EventLoop</span><span class="p">,</span> <span class="n">ClientHandler</span> + +<span class="k">class</span> <span class="nc">Client</span><span class="p">(</span><span class="n">ClientHandler</span><span class="p">):</span> + <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">eventloop</span><span class="p">,</span> <span class="n">host</span><span class="p">,</span> <span class="n">address</span><span class="p">,</span> <span class="n">requests</span><span class="p">):</span> + <span class="bp">self</span><span class="o">.</span><span class="n">eventloop</span> <span class="o">=</span> <span class="n">eventloop</span> + <span class="bp">self</span><span class="o">.</span><span class="n">conn</span> <span class="o">=</span> <span class="n">eventloop</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">host</span><span class="p">)</span> + <span class="bp">self</span><span class="o">.</span><span class="n">sender</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">conn</span><span class="o">.</span><span class="n">create_sender</span><span class="p">(</span><span class="n">address</span><span class="p">)</span> + <span class="bp">self</span><span class="o">.</span><span class="n">receiver</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">conn</span><span class="o">.</span><span class="n">create_receiver</span><span class="p">(</span><span class="bp">None</span><span class="p">,</span> <span class="n">dynamic</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">handler</span><span class="o">=</span><span class="bp">self</span><span class="p">)</span> + <span class="bp">self</span><span class="o">.</span><span class="n">requests</span> <span class="o">=</span> <span class="n">requests</span> + + <span class="k">def</span> <span class="nf">next_request</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> + <span class="n">req</span> <span class="o">=</span> <span class="n">Message</span><span class="p">(</span><span class="n">reply_to</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">receiver</span><span class="o">.</span><span class="n">remote_source</span><span class="o">.</span><span class="n">address</span><span class="p">,</span> <span class="n">body</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">requests</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> + <span class="bp">self</span><span class="o">.</span><span class="n">sender</span><span class="o">.</span><span class="n">send_msg</span><span class="p">(</span><span class="n">req</span><span class="p">)</span> + + <span class="k">def</span> <span class="nf">on_link_opened</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="bp">self</span><span class="o">.</span><span class="n">next_request</span><span class="p">()</span> + + <span class="k">def</span> <span class="nf">on_message</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="k">print</span> <span class="s">"</span><span class="si">%s</span><span class="s"> => </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">requests</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">),</span> <span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">body</span><span class="p">)</span> + <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">requests</span><span class="p">:</span> + <span class="bp">self</span><span class="o">.</span><span class="n">next_request</span><span class="p">()</span> + <span class="k">else</span><span class="p">:</span> + <span class="bp">self</span><span class="o">.</span><span class="n">conn</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> + + <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> + <span class="bp">self</span><span class="o">.</span><span class="n">eventloop</span><span class="o">.</span><span class="n">run</span><span class="p">()</span> + +<span class="n">REQUESTS</span><span class="o">=</span> <span class="p">[</span><span class="s">"Twas brillig, and the slithy toves"</span><span class="p">,</span> + <span class="s">"Did gire and gymble in the wabe."</span><span class="p">,</span> + <span class="s">"All mimsy were the borogroves,"</span><span class="p">,</span> + <span class="s">"And the mome raths outgrabe."</span><span class="p">]</span> + +<span class="n">Client</span><span class="p">(</span><span class="n">EventLoop</span><span class="p">(),</span> <span class="s">"localhost:5672"</span><span class="p">,</span> <span class="s">"examples"</span><span class="p">,</span> <span class="n">REQUESTS</span><span class="p">)</span><span class="o">.</span><span class="n">run</span><span class="p">()</span> +</pre></div> +</td></tr></table></div> +<p>As well as sending requests, we need to be able to get back the +responses. We create a receiver for that (see line 8), but we don’t +specify an address, we set the dynamic option which tells the broker +we are connected to to create a temporary address over which we can +receive our responses.</p> +<p>We need to use the address allocated by the broker as the reply_to +address of our requests. To be notified when the broker has sent us +back the address to use, we add an <tt class="docutils literal"><span class="pre">on_link_remote_open()</span></tt> method to +our receiver’s handler, and use that as the trigger to send our first +request.</p> +</div> + + + </div> + </div> + <div class="clearer"></div> + </div> + <div class="related"> + <h3>Navigation</h3> + <ul> + <li class="right" style="margin-right: 10px"> + <a href="genindex.html" title="General Index" + >index</a></li> + <li class="right" > + <a href="index.html" title="Some Proton Examples" + >previous</a> |</li> + <li><a href="index.html">Proton 0.9-alpha documentation</a> »</li> + </ul> + </div> + <div class="footer"> + © Copyright 2014, Apache Qpid. + Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3. + </div> + </body> +</html> \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d4b154cb/examples/engine/py/abstract_server.py ---------------------------------------------------------------------- diff --git a/examples/engine/py/abstract_server.py b/examples/engine/py/abstract_server.py new file mode 100644 index 0000000..2d0de32 --- /dev/null +++ b/examples/engine/py/abstract_server.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +from proton_server import Server + +class Application(Server): + def __init__(self, host, address): + super(Application, self).__init__(host, address) + + def on_request(self, request, reply_to): + response = request.upper() + self.send(response, reply_to) + print "Request from: %s" % reply_to + +try: + Application("localhost:5672", "examples").run() +except KeyboardInterrupt: pass + http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d4b154cb/examples/engine/py/client.py ---------------------------------------------------------------------- diff --git a/examples/engine/py/client.py b/examples/engine/py/client.py new file mode 100755 index 0000000..a649dec --- /dev/null +++ b/examples/engine/py/client.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +from proton import Message +from proton.handlers import MessagingHandler +from proton.reactors import EventLoop + +class Client(MessagingHandler): + def __init__(self, host, address, requests): + super(Client, self).__init__() + self.host = host + self.address = address + self.requests = requests + + def on_start(self, event): + self.conn = event.reactor.connect(self.host) + self.sender = self.conn.create_sender(self.address) + self.receiver = self.conn.create_receiver(None, dynamic=True) + + def next_request(self): + if self.receiver.remote_source.address: + req = Message(reply_to=self.receiver.remote_source.address, body=self.requests[0]) + self.sender.send_msg(req) + + def on_link_opened(self, event): + if event.receiver == self.receiver: + self.next_request() + + def on_message(self, event): + print "%s => %s" % (self.requests.pop(0), event.message.body) + if self.requests: + self.next_request() + else: + self.conn.close() + +REQUESTS= ["Twas brillig, and the slithy toves", + "Did gire and gymble in the wabe.", + "All mimsy were the borogroves,", + "And the mome raths outgrabe."] + +EventLoop(Client("localhost:5672", "examples", REQUESTS)).run() + http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d4b154cb/examples/engine/py/client_http.py ---------------------------------------------------------------------- diff --git a/examples/engine/py/client_http.py b/examples/engine/py/client_http.py new file mode 100755 index 0000000..ab7b1cd --- /dev/null +++ b/examples/engine/py/client_http.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +from proton import Message +from proton.handlers import MessagingHandler +from proton_tornado import TornadoLoop +from tornado.ioloop import IOLoop +import tornado.web + +class Client(MessagingHandler): + def __init__(self, host, address): + super(Client, self).__init__() + self.host = host + self.address = address + self.sent = [] + self.pending = [] + self.reply_address = None + self.sender = None + self.receiver = None + + def on_start(self, event): + context = event.reactor.connect(self.host) + self.sender = context.create_sender(self.address) + self.receiver = context.create_receiver(None, dynamic=True) + + def on_link_opened(self, event): + if event.receiver == self.receiver: + self.reply_address = event.link.remote_source.address + self.do_request() + + def on_credit(self, event): + self.do_request() + + def on_message(self, event): + if self.sent: + request, handler = self.sent.pop(0) + print "%s => %s" % (request, event.message.body) + handler(event.message.body) + self.do_request() + + def do_request(self): + if self.pending and self.reply_address and self.sender.credit: + request, handler = self.pending.pop(0) + self.sent.append((request, handler)) + req = Message(reply_to=self.reply_address, body=request) + self.sender.send_msg(req) + + def request(self, body, handler): + self.pending.append((body, handler)) + self.do_request() + +class ExampleHandler(tornado.web.RequestHandler): + def initialize(self, client): + self.client = client + + def get(self): + self._write_open() + self._write_form() + self._write_close() + + @tornado.web.asynchronous + def post(self): + client.request(self.get_body_argument("message"), lambda x: self.on_response(x)) + + def on_response(self, body): + self.set_header("Content-Type", "text/html") + self._write_open() + self._write_form() + self.write("Response: " + body) + self._write_close() + self.finish() + + def _write_open(self): + self.write('<html><body>') + + def _write_close(self): + self.write('</body></html>') + + def _write_form(self): + self.write('<form action="/client" method="POST">' + 'Request: <input type="text" name="message">' + '<input type="submit" value="Submit">' + '</form>') + + +client = Client("localhost:5672", "examples") +loop = TornadoLoop(client) +app = tornado.web.Application([tornado.web.url(r"/client", ExampleHandler, dict(client=client))]) +app.listen(8888) +try: + loop.run() +except KeyboardInterrupt: + loop.stop() http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d4b154cb/examples/engine/py/conf.py ---------------------------------------------------------------------- diff --git a/examples/engine/py/conf.py b/examples/engine/py/conf.py new file mode 100644 index 0000000..8644399 --- /dev/null +++ b/examples/engine/py/conf.py @@ -0,0 +1,242 @@ +# -*- coding: utf-8 -*- +# +# Proton documentation build configuration file, created by +# sphinx-quickstart on Thu Jul 31 10:31:05 2014. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = [] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'Proton' +copyright = u'2014, Apache Qpid' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '0.9' +# The full version, including alpha/beta/rc tags. +release = '0.9-alpha' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +html_theme_options = {'nosidebar':'true'} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# "<project> v<release> documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a <link> tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'Protondoc' + + +# -- Options for LaTeX output -------------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'Proton.tex', u'Proton Documentation', + u'Apache Qpid', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'proton', u'Proton Documentation', + [u'Apache Qpid'], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------------ + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'Proton', u'Proton Documentation', + u'Apache Qpid', 'Proton', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d4b154cb/examples/engine/py/db_common.py ---------------------------------------------------------------------- diff --git a/examples/engine/py/db_common.py b/examples/engine/py/db_common.py new file mode 100644 index 0000000..584c15a --- /dev/null +++ b/examples/engine/py/db_common.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +import Queue +import sqlite3 +import threading + +class Db(object): + def __init__(self, db, events): + self.db = db + self.events = events + self.tasks = Queue.Queue() + self.position = None + self.pending_events = [] + self.thread = threading.Thread(target=self._process) + self.thread.daemon=True + self.thread.start() + + def reset(self): + self.tasks.put(lambda conn: self._reset()) + + def load(self, records, event=None): + self.tasks.put(lambda conn: self._load(conn, records, event)) + + def insert(self, id, data, event=None): + self.tasks.put(lambda conn: self._insert(conn, id, data, event)) + + def delete(self, id, event=None): + self.tasks.put(lambda conn: self._delete(conn, id, event)) + + def _reset(self, ignored=None): + self.position = None + + def _load(self, conn, records, event): + if self.position: + cursor = conn.execute("SELECT * FROM records WHERE id > ? ORDER BY id", (self.position,)) + else: + cursor = conn.execute("SELECT * FROM records ORDER BY id") + while not records.full(): + row = cursor.fetchone() + if row: + self.position = row['id'] + records.put(dict(row)) + else: + break + if event: + self.events.trigger(event) + + def _insert(self, conn, id, data, event): + if id: + conn.execute("INSERT INTO records(id, description) VALUES (?, ?)", (id, data)) + else: + conn.execute("INSERT INTO records(description) VALUES (?)", (data,)) + if event: + self.pending_events.append(event) + + def _delete(self, conn, id, event): + conn.execute("DELETE FROM records WHERE id=?", (id,)) + if event: + self.pending_events.append(event) + + def _process(self): + conn = sqlite3.connect(self.db) + conn.row_factory = sqlite3.Row + with conn: + while True: + f = self.tasks.get(True) + try: + while True: + f(conn) + f = self.tasks.get(False) + except Queue.Empty: pass + conn.commit() + for event in self.pending_events: + self.events.trigger(event) + self.pending_events = [] http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d4b154cb/examples/engine/py/db_ctrl.py ---------------------------------------------------------------------- diff --git a/examples/engine/py/db_ctrl.py b/examples/engine/py/db_ctrl.py new file mode 100755 index 0000000..b28e0eb --- /dev/null +++ b/examples/engine/py/db_ctrl.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +import sqlite3 +import sys + +if len(sys.argv) < 3: + print "Usage: %s [init|insert|list] db" % sys.argv[0] +else: + conn = sqlite3.connect(sys.argv[2]) + with conn: + if sys.argv[1] == "init": + conn.execute("DROP TABLE IF EXISTS records") + conn.execute("CREATE TABLE records(id INTEGER PRIMARY KEY AUTOINCREMENT, description TEXT)") + conn.commit() + elif sys.argv[1] == "list": + cursor = conn.cursor() + cursor.execute("SELECT * FROM records") + rows = cursor.fetchall() + for r in rows: + print r + elif sys.argv[1] == "insert": + while True: + l = sys.stdin.readline() + if not l: break + conn.execute("INSERT INTO records(description) VALUES (?)", (l.rstrip(),)) + conn.commit() + else: + print "Unrecognised command: %s" % sys.argv[1] http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d4b154cb/examples/engine/py/db_recv.py ---------------------------------------------------------------------- diff --git a/examples/engine/py/db_recv.py b/examples/engine/py/db_recv.py new file mode 100755 index 0000000..5779403 --- /dev/null +++ b/examples/engine/py/db_recv.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +from proton.handlers import MessagingHandler +from proton.reactors import ApplicationEvent, EventLoop +from db_common import Db + +class Recv(MessagingHandler): + def __init__(self, host, address): + super(Recv, self).__init__(auto_accept=False) + self.host = host + self.address = address + self.delay = 0 + # TODO: load last tag from db + self.last_id = None + + def on_start(self, event): + self.db = Db("dst_db", event.reactor.get_event_trigger()) + context = event.reactor.connect(self.host) + context.create_receiver(self.address) + + def on_record_inserted(self, event): + self.accept(event.delivery) + + def on_message(self, event): + id = int(event.message.id) + if (not self.last_id) or id > self.last_id: + self.last_id = id + self.db.insert(id, event.message.body, ApplicationEvent("record_inserted", delivery=event.delivery)) + print "inserted message %s" % id + else: + self.accept(event.delivery) + +try: + EventLoop(Recv("localhost:5672", "examples")).run() +except KeyboardInterrupt: pass + + + http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d4b154cb/examples/engine/py/db_send.py ---------------------------------------------------------------------- diff --git a/examples/engine/py/db_send.py b/examples/engine/py/db_send.py new file mode 100755 index 0000000..b3a26fd --- /dev/null +++ b/examples/engine/py/db_send.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +import Queue +import time +from proton import Message +from proton.handlers import MessagingHandler +from proton.reactors import ApplicationEvent, EventLoop +from db_common import Db + +class Send(MessagingHandler): + def __init__(self, host, address): + super(Send, self).__init__() + self.host = host + self.address = address + self.delay = 0 + self.sent = 0 + self.records = Queue.Queue(maxsize=50) + + def on_start(self, event): + self.eventloop = event.reactor + self.db = Db("src_db", event.reactor.get_event_trigger()) + context = event.reactor.connect(self.host) + self.sender = context.create_sender(self.address) + + def on_records_loaded(self, event): + if self.records.empty() and event.subject == self.sent: + print "Exhausted available data, waiting to recheck..." + # check for new data after 5 seconds + self.eventloop.schedule(time.time() + 5, link=self.sender, subject="data") + else: + self.send() + + def request_records(self): + if not self.records.full(): + self.db.load(self.records, event=ApplicationEvent("records_loaded", link=self.sender, subject=self.sent)) + + def on_credit(self, event): + self.send() + + def send(self): + while self.sender.credit and not self.records.empty(): + record = self.records.get(False) + id = record['id'] + self.sender.send_msg(Message(id=id, durable=True, body=record['description']), tag=str(id)) + self.sent += 1 + print "sent message %s" % id + self.request_records() + + def on_settled(self, event): + id = int(event.delivery.tag) + self.db.delete(id) + print "settled message %s" % id + + def on_disconnected(self, event): + self.db.reset() + + def on_timer(self, event): + if event.subject == "data": + print "Rechecking for data..." + self.request_records() + +try: + EventLoop(Send("localhost:5672", "examples")).run() +except KeyboardInterrupt: pass + http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d4b154cb/examples/engine/py/helloworld.py ---------------------------------------------------------------------- diff --git a/examples/engine/py/helloworld.py b/examples/engine/py/helloworld.py new file mode 100755 index 0000000..5aa1482 --- /dev/null +++ b/examples/engine/py/helloworld.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +from proton import Message +from proton.handlers import MessagingHandler +from proton.reactors import EventLoop + +class HelloWorld(MessagingHandler): + def __init__(self, server, address): + super(HelloWorld, self).__init__() + self.server = server + self.address = address + + def on_start(self, event): + ctxt = event.reactor.connect(self.server) + ctxt.create_receiver(self.address) + ctxt.create_sender(self.address) + + def on_credit(self, event): + event.sender.send_msg(Message(body=u"Hello World!")) + event.sender.close() + + def on_message(self, event): + print event.message.body + event.connection.close() + +EventLoop(HelloWorld("localhost:5672", "examples")).run() + http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d4b154cb/examples/engine/py/helloworld_blocking.py ---------------------------------------------------------------------- diff --git a/examples/engine/py/helloworld_blocking.py b/examples/engine/py/helloworld_blocking.py new file mode 100755 index 0000000..9c5e062 --- /dev/null +++ b/examples/engine/py/helloworld_blocking.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +from proton import Message +from proton.utils import BlockingConnection +from proton.handlers import IncomingMessageHandler + +class HelloWorldReceiver(IncomingMessageHandler): + def on_message(self, event): + print event.message.body + event.connection.close() + +conn = BlockingConnection("localhost:5672") +conn.create_receiver("examples", handler=HelloWorldReceiver()) +sender = conn.create_sender("examples") +sender.send_msg(Message(body=u"Hello World!")); +conn.run() + http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d4b154cb/examples/engine/py/helloworld_direct.py ---------------------------------------------------------------------- diff --git a/examples/engine/py/helloworld_direct.py b/examples/engine/py/helloworld_direct.py new file mode 100755 index 0000000..35ac597 --- /dev/null +++ b/examples/engine/py/helloworld_direct.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +from proton import Message +from proton.handlers import MessagingHandler +from proton.reactors import EventLoop + +class HelloWorld(MessagingHandler): + def __init__(self, server, address): + super(HelloWorld, self).__init__() + self.server = server + self.address = address + + def on_start(self, event): + self.acceptor = event.reactor.listen(self.server) + ctxt = event.reactor.connect(self.server) + ctxt.create_sender(self.address) + + def on_credit(self, event): + event.sender.send_msg(Message(body=u"Hello World!")) + event.sender.close() + + def on_message(self, event): + print event.message.body + + def on_accepted(self, event): + event.connection.close() + + def on_connection_closed(self, event): + self.acceptor.close() + +EventLoop(HelloWorld("localhost:8888", "examples")).run() http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d4b154cb/examples/engine/py/helloworld_direct_tornado.py ---------------------------------------------------------------------- diff --git a/examples/engine/py/helloworld_direct_tornado.py b/examples/engine/py/helloworld_direct_tornado.py new file mode 100755 index 0000000..45926c6 --- /dev/null +++ b/examples/engine/py/helloworld_direct_tornado.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +from proton import Message +from proton.handlers import MessagingHandler +from proton_tornado import TornadoLoop + +class HelloWorld(MessagingHandler): + def __init__(self, server, address): + super(HelloWorld, self).__init__() + self.server = server + self.address = address + + def on_start(self, event): + self.eventloop = event.reactor + self.acceptor = event.reactor.listen(self.server) + ctxt = event.reactor.connect(self.server) + ctxt.create_sender(self.address) + + def on_credit(self, event): + event.sender.send_msg(Message(body=u"Hello World!")) + event.sender.close() + + def on_message(self, event): + print event.message.body + + def on_accepted(self, event): + event.connection.close() + + def on_connection_closed(self, event): + self.acceptor.close() + self.eventloop.stop() + +TornadoLoop(HelloWorld("localhost:8888", "examples")).run() + http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d4b154cb/examples/engine/py/helloworld_tornado.py ---------------------------------------------------------------------- diff --git a/examples/engine/py/helloworld_tornado.py b/examples/engine/py/helloworld_tornado.py new file mode 100755 index 0000000..6a82b69 --- /dev/null +++ b/examples/engine/py/helloworld_tornado.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +from proton import Message +from proton.handlers import MessagingHandler +from proton_tornado import TornadoLoop + +class HelloWorld(MessagingHandler): + def __init__(self, server, address): + super(HelloWorld, self).__init__() + self.server = server + self.address = address + + def on_start(self, event): + self.eventloop = event.reactor + ctxt = event.reactor.connect(self.server) + ctxt.create_receiver(self.address) + ctxt.create_sender(self.address) + + def on_credit(self, event): + event.sender.send_msg(Message(body=u"Hello World!")) + event.sender.close() + + def on_message(self, event): + print event.message.body + event.connection.close() + + def on_connection_closed(self, event): + self.eventloop.stop() + +TornadoLoop(HelloWorld("localhost:5672", "examples")).run() + http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d4b154cb/examples/engine/py/index.rst ---------------------------------------------------------------------- diff --git a/examples/engine/py/index.rst b/examples/engine/py/index.rst new file mode 100644 index 0000000..d5f5b76 --- /dev/null +++ b/examples/engine/py/index.rst @@ -0,0 +1,15 @@ +.. Proton documentation master file, created by + sphinx-quickstart on Thu Jul 31 10:31:05 2014. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Some Proton Examples +==================== + +Contents: + +.. toctree:: + :maxdepth: 2 + + tutorial + http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d4b154cb/examples/engine/py/make.bat ---------------------------------------------------------------------- diff --git a/examples/engine/py/make.bat b/examples/engine/py/make.bat new file mode 100644 index 0000000..55ed870 --- /dev/null +++ b/examples/engine/py/make.bat @@ -0,0 +1,190 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +set I18NSPHINXOPTS=%SPHINXOPTS% . +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^<target^>` where ^<target^> is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Proton.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Proton.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "texinfo" ( + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end +) + +if "%1" == "gettext" ( + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +:end http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d4b154cb/examples/engine/py/proton_server.py ---------------------------------------------------------------------- diff --git a/examples/engine/py/proton_server.py b/examples/engine/py/proton_server.py new file mode 100644 index 0000000..b2e2027 --- /dev/null +++ b/examples/engine/py/proton_server.py @@ -0,0 +1,61 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +from proton import Message +from proton.reactors import EventLoop +from proton.handlers import FlowController, IncomingMessageHandler + +class Server(IncomingMessageHandler): + def __init__(self, host, address): + super(Server, self).__init__() + self.eventloop = EventLoop(self, FlowController(10)) + self.conn = self.eventloop.connect(host) + self.receiver = self.conn.create_receiver(address) + self.senders = {} + self.relay = None + + def on_message(self, event): + self.on_request(event.message.body, event.message.reply_to) + + def on_connection_open(self, event): + if event.connection.remote_offered_capabilities and "ANONYMOUS-RELAY" in event.connection.remote_offered_capabilities: + self.relay = self.conn.create_sender(None) + + def on_connection_close(self, endpoint, error): + if error: print "Closed due to %s" % error + self.conn.close() + + def run(self): + self.eventloop.run() + + def send(self, response, reply_to): + sender = self.relay + if not sender: + sender = self.senders.get(reply_to) + if not sender: + sender = self.conn.create_sender(reply_to) + self.senders[reply_to] = sender + msg = Message(body=response) + if self.relay: + msg.address = reply_to + sender.send_msg(msg) + + def on_request(self, request, reply_to): + pass + http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d4b154cb/examples/engine/py/proton_tornado.py ---------------------------------------------------------------------- diff --git a/examples/engine/py/proton_tornado.py b/examples/engine/py/proton_tornado.py new file mode 100644 index 0000000..e49b28e --- /dev/null +++ b/examples/engine/py/proton_tornado.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +from proton.reactors import ApplicationEvent, EventLoop, StartEvent +import tornado.ioloop + +class TornadoLoop(EventLoop): + def __init__(self, *handlers): + super(TornadoLoop, self).__init__(*handlers) + self.loop = tornado.ioloop.IOLoop.current() + + def connect(self, url=None, urls=None, address=None, handler=None, reconnect=None): + conn = super(TornadoLoop, self).connect(url, urls, address, handler, reconnect) + self.events.process() + return conn + + def schedule(self, deadline, connection=None, session=None, link=None, delivery=None, subject=None): + self.loop.call_at(deadline, self.events.dispatch, ApplicationEvent("timer", connection, session, link, delivery, subject)) + + def add(self, conn): + self.loop.add_handler(conn, self._connection_ready, tornado.ioloop.IOLoop.READ | tornado.ioloop.IOLoop.WRITE) + + def remove(self, conn): + self.loop.remove_handler(conn) + + def run(self): + self.events.dispatch(StartEvent(self)) + self.loop.start() + + def stop(self): + self.loop.stop() + + def _get_event_flags(self, conn): + flags = 0 + if conn.reading(): + flags |= tornado.ioloop.IOLoop.READ + # FIXME: need way to update flags to avoid busy loop + #if conn.writing(): + # flags |= tornado.ioloop.IOLoop.WRITE + flags |= tornado.ioloop.IOLoop.WRITE + return flags + + def _connection_ready(self, conn, events): + if events & tornado.ioloop.IOLoop.READ: + conn.readable() + if events & tornado.ioloop.IOLoop.WRITE: + conn.writable() + if events & tornado.ioloop.IOLoop.ERROR:# or conn.closed(): + self.loop.remove_handler(conn) + conn.close() + conn.removed() + self.events.process() + self.loop.update_handler(conn, self._get_event_flags(conn)) --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
