You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by rh...@apache.org on 2015/02/04 17:23:48 UTC

[1/2] qpid-proton git commit: added Message.recv(receiver) -> delivery to compliment of Message.send(sender); made Message(foo) default to Message(body=foo) instead of just barfing

Repository: qpid-proton
Updated Branches:
  refs/heads/master 7318675ca -> c90655b88


added Message.recv(receiver) -> delivery to compliment of Message.send(sender); made Message(foo) default to Message(body=foo) instead of just barfing


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/c666db8d
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/c666db8d
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/c666db8d

Branch: refs/heads/master
Commit: c666db8de92dd607df9427946bf7c0f08860a709
Parents: 7318675
Author: Rafael Schloming <rh...@alum.mit.edu>
Authored: Wed Feb 4 11:21:54 2015 -0500
Committer: Rafael Schloming <rh...@alum.mit.edu>
Committed: Wed Feb 4 11:23:04 2015 -0500

----------------------------------------------------------------------
 proton-c/bindings/python/proton/__init__.py | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/c666db8d/proton-c/bindings/python/proton/__init__.py
----------------------------------------------------------------------
diff --git a/proton-c/bindings/python/proton/__init__.py b/proton-c/bindings/python/proton/__init__.py
index 5c9fe63..68f7632 100644
--- a/proton-c/bindings/python/proton/__init__.py
+++ b/proton-c/bindings/python/proton/__init__.py
@@ -778,7 +778,7 @@ class Message(object):
 
   DEFAULT_PRIORITY = PN_DEFAULT_PRIORITY
 
-  def __init__(self, **kwargs):
+  def __init__(self, body=None, **kwargs):
     """
     @param kwargs: Message property name/value pairs to initialise the Message
     """
@@ -788,7 +788,7 @@ class Message(object):
     self.instructions = None
     self.annotations = None
     self.properties = None
-    self.body = None
+    self.body = body
     for k,v in kwargs.iteritems():
       getattr(self, k)          # Raise exception if it's not a valid attribute.
       setattr(self, k, v)
@@ -1128,6 +1128,17 @@ The format of the message.
       dlv.settle()
     return dlv
 
+  def recv(self, receiver):
+    dlv = receiver.current
+    if dlv.partial: return None
+    encoded = receiver.recv(dlv.pending)
+    # the sender has already forgotten about the delivery, so we might
+    # as well too
+    if receiver.remote_snd_settle_mode == Link.SND_SETTLED:
+      dlv.settle()
+    self.decode(encoded)
+    return dlv
+
   def __repr2__(self):
     props = []
     for attr in ("inferred", "address", "reply_to", "durable", "ttl",


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[2/2] qpid-proton git commit: updated/improved reactor tutorial/examples

Posted by rh...@apache.org.
updated/improved reactor tutorial/examples


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/c90655b8
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/c90655b8
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/c90655b8

Branch: refs/heads/master
Commit: c90655b88cbaf5c28590f5e7221baa882f54f8b1
Parents: c666db8
Author: Rafael Schloming <rh...@alum.mit.edu>
Authored: Wed Feb 4 11:20:50 2015 -0500
Committer: Rafael Schloming <rh...@alum.mit.edu>
Committed: Wed Feb 4 11:23:31 2015 -0500

----------------------------------------------------------------------
 examples/reactor/py/README.md         | 14 +++++-
 examples/reactor/py/count-randomly.py | 77 ++++++++++++++++++++++++++++++
 examples/reactor/py/counter.py        | 11 +++++
 examples/reactor/py/echo.py           |  5 ++
 examples/reactor/py/global-logger.py  | 58 ++++++++++++++++++++++
 examples/reactor/py/goodbye-world.py  | 15 +++++-
 examples/reactor/py/handlers.py       | 48 +++++++++++++++++++
 examples/reactor/py/hello-world.py    |  2 +-
 examples/reactor/py/logger.py         | 41 ----------------
 examples/reactor/py/reactor-logger.py | 54 +++++++++++++++++++++
 examples/reactor/py/recv.py           | 48 +++++++++++++++++++
 examples/reactor/py/send.py           | 37 +++++++++++---
 examples/reactor/py/unhandled.py      |  6 +--
 13 files changed, 362 insertions(+), 54 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/c90655b8/examples/reactor/py/README.md
----------------------------------------------------------------------
diff --git a/examples/reactor/py/README.md b/examples/reactor/py/README.md
index 24f4f20..e843d09 100644
--- a/examples/reactor/py/README.md
+++ b/examples/reactor/py/README.md
@@ -1,5 +1,12 @@
 The examples in this directory provide a basic introduction to the
 proton reactor API and are best viewed in the order presented below.
+
+The examples contain comments that explain things in a tutorial-style
+manner. At some point soon this content will be pulled out into a
+proper tutorial that references the relevant code snippets from these
+examples. Until then please bear with this clumsy style of
+presentation.
+
 This API is present in C as well and most of these examples will
 transliterate into C in a fairly straightforward way.
 
@@ -8,12 +15,17 @@ transliterate into C in a fairly straightforward way.
 
   - scheduling.py
   - counter.py
+  - count-randomly.py
 
   - unhandled.py
-  - logger.py
+  - reactor-logger.py
+  - global-logger.py
   - delegates.py
 
+  - handlers.py
+
   - echo.py
   - cat.py
 
   - send.py
+  - recv.py

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/c90655b8/examples/reactor/py/count-randomly.py
----------------------------------------------------------------------
diff --git a/examples/reactor/py/count-randomly.py b/examples/reactor/py/count-randomly.py
new file mode 100755
index 0000000..9bcc41f
--- /dev/null
+++ b/examples/reactor/py/count-randomly.py
@@ -0,0 +1,77 @@
+#!/usr/bin/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 time, random
+from proton.reactors import Reactor
+
+# Let's try to modify our counter example. In addition to counting to
+# 10 in quarter second intervals, let's also print out a random number
+# every half second. This is not a super easy thing to express in a
+# purely sequential program, but not so difficult using events.
+
+class Counter:
+
+    def __init__(self, limit):
+        self.limit = limit
+        self.count = 0
+
+    def on_timer_task(self, event):
+        self.count += 1
+        print self.count
+        if not self.done():
+            event.reactor.schedule(0.25, self)
+
+    # add a public API to check for doneness
+    def done(self):
+        return self.count >= self.limit
+
+class Program:
+
+    def on_reactor_init(self, event):
+        self.start = time.time()
+        print "Hello, World!"
+
+        # Save the counter instance in an attribute so we can refer to
+        # it later.
+        self.counter = Counter(10)
+        event.reactor.schedule(0.25, self.counter)
+
+        # Now schedule another event with a different handler. Note
+        # that the timer tasks go to separate handlers, and they don't
+        # interfere with each other.
+        event.reactor.schedule(0.5, self)
+
+    def on_timer_task(self, event):
+        # keep on shouting until we are done counting
+        print "Yay, %s!" % random.randint(10, 100)
+        if not self.counter.done():
+            event.reactor.schedule(0.5, self)
+
+    def on_reactor_final(self, event):
+        print "Goodbye, World! (after %s long seconds)" % (time.time() - self.start)
+
+# In hello-world.py we said the reactor exits when there are no more
+# events to process. While this is true, it's not actually complete.
+# The reactor exits when there are no more events to process and no
+# possibility of future events arising. For that reason the reactor
+# will keep running until there are no more scheduled events and then
+# exit.
+r = Reactor(Program())
+r.run()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/c90655b8/examples/reactor/py/counter.py
----------------------------------------------------------------------
diff --git a/examples/reactor/py/counter.py b/examples/reactor/py/counter.py
index 8a2479a..b1456c0 100755
--- a/examples/reactor/py/counter.py
+++ b/examples/reactor/py/counter.py
@@ -40,10 +40,21 @@ class Program:
     def on_reactor_init(self, event):
         self.start = time.time()
         print "Hello, World!"
+
+        # Note that unlike the previous scheduling example, we pass in
+        # a separate object for the handler. This means that the timer
+        # event we just scheduled will not be seen by Program as it is
+        # being handled by the Counter instance we create.
         event.reactor.schedule(0.25, Counter(10))
 
     def on_reactor_final(self, event):
         print "Goodbye, World! (after %s long seconds)" % (time.time() - self.start)
 
+# In hello-world.py we said the reactor exits when there are no more
+# events to process. While this is true, it's not actually complete.
+# The reactor exits when there are no more events to process and no
+# possibility of future events arising. For that reason the reactor
+# will keep running until there are no more scheduled events and then
+# exit.
 r = Reactor(Program())
 r.run()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/c90655b8/examples/reactor/py/echo.py
----------------------------------------------------------------------
diff --git a/examples/reactor/py/echo.py b/examples/reactor/py/echo.py
index ecf1c9d..66a163c 100755
--- a/examples/reactor/py/echo.py
+++ b/examples/reactor/py/echo.py
@@ -50,6 +50,11 @@ class Echo:
 class Program:
 
     def on_reactor_init(self, event):
+        # Every selectable is a possible source of future events. Our
+        # selectable stays alive until it reads the end of stream
+        # marker. This will keep the whole reactor running until we
+        # type Control-D.
+        print "Type whatever you want and then use Control-D to exit:"
         event.reactor.selectable(Echo(sys.stdin))
 
 r = Reactor(Program())

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/c90655b8/examples/reactor/py/global-logger.py
----------------------------------------------------------------------
diff --git a/examples/reactor/py/global-logger.py b/examples/reactor/py/global-logger.py
new file mode 100755
index 0000000..828ae58
--- /dev/null
+++ b/examples/reactor/py/global-logger.py
@@ -0,0 +1,58 @@
+#!/usr/bin/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 time
+from proton.reactors import Reactor
+
+# Not every event goes to the reactor's event handler. If we have a
+# separate handler for something like a scheduled task, then those
+# events aren't logged by the logger associated with the reactor's
+# handler. Sometimes this is useful if you don't want to see them, but
+# sometimes you want the global picture.
+
+class Logger:
+
+    def on_unhandled(self, name, event):
+        print "LOG:", name, event
+
+class Task:
+
+    def on_timer_task(self, event):
+        print "Mission accomplished!"
+
+class Program:
+
+    def on_reactor_init(self, event):
+        print "Hello, World!"
+        event.reactor.schedule(0, Task())
+
+    def on_reactor_final(self, event):
+        print "Goodbye, World!"
+
+r = Reactor(Program())
+
+# In addition to having a regular handler, the reactor also has a
+# global handler that sees every event. By adding the Logger to the
+# global handler instead of the regular handler, we can log every
+# single event that occurs in the system regardless of whether or not
+# there are specific handlers associated with the objects that are the
+# target of those events.
+r.global_handler.add(Logger())
+r.run()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/c90655b8/examples/reactor/py/goodbye-world.py
----------------------------------------------------------------------
diff --git a/examples/reactor/py/goodbye-world.py b/examples/reactor/py/goodbye-world.py
index 6037ef9..a14525a 100755
--- a/examples/reactor/py/goodbye-world.py
+++ b/examples/reactor/py/goodbye-world.py
@@ -20,12 +20,25 @@
 
 from proton.reactors import Reactor
 
+# So far the reactive hello-world doesn't look too different from a
+# regular old non-reactive hello-world. The on_reactor_init method can
+# be used roughly as a 'main' method would. A program that only uses
+# that one event, however, isn't going to be very reactive. By using
+# other events, we can write a fully reactive program.
+
 class Program:
 
+    # As before we handle the reactor init event.
     def on_reactor_init(self, event):
         print "Hello, World!"
 
-    # The reactor produces an event when it is about to exit.
+    # In addition to an initial event, the reactor also produces an
+    # event when it is about to exit. This may not behave much
+    # differently than just putting the goodbye print statement inside
+    # on_reactor_init, but as we grow our program, this piece of it
+    # will always be what happens last, and will always happen
+    # regardless of what other paths the main logic of our program
+    # might take.
     def on_reactor_final(self, event):
         print "Goodbye, World!"
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/c90655b8/examples/reactor/py/handlers.py
----------------------------------------------------------------------
diff --git a/examples/reactor/py/handlers.py b/examples/reactor/py/handlers.py
new file mode 100755
index 0000000..36f2c22
--- /dev/null
+++ b/examples/reactor/py/handlers.py
@@ -0,0 +1,48 @@
+#!/usr/bin/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 time
+from proton.reactors import Reactor
+
+
+class World:
+
+    def on_reactor_init(self, event):
+        print "World!"
+
+class Goodbye:
+
+    def on_reactor_final(self, event):
+        print "Goodbye, World!"
+
+class Hello:
+
+    def __init__(self):
+        # When an event dispatches itself to a handler, it also checks
+        # if that handler has a "handlers" attribute and dispatches
+        # the event to any children.
+        self.handlers = [World(), Goodbye()]
+
+    # The parent handler always receives the event first.
+    def on_reactor_init(self, event):
+        print "Hello",
+
+r = Reactor(Hello())
+r.run()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/c90655b8/examples/reactor/py/hello-world.py
----------------------------------------------------------------------
diff --git a/examples/reactor/py/hello-world.py b/examples/reactor/py/hello-world.py
index 8c35b85..beff278 100755
--- a/examples/reactor/py/hello-world.py
+++ b/examples/reactor/py/hello-world.py
@@ -38,5 +38,5 @@ r = Reactor(Program())
 
 # When you call run, the reactor will process events. The reactor init
 # event is what kicks off everything else. When the reactor has no
-# more events to process, it will exit.
+# more events to process, it exits.
 r.run()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/c90655b8/examples/reactor/py/logger.py
----------------------------------------------------------------------
diff --git a/examples/reactor/py/logger.py b/examples/reactor/py/logger.py
deleted file mode 100755
index bcc8a9f..0000000
--- a/examples/reactor/py/logger.py
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/usr/bin/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 time
-from proton.reactors import Reactor
-
-class Logger:
-
-    def on_unhandled(self, name, event):
-        print name, event
-
-class Program:
-
-    def on_reactor_init(self, event):
-        print "Hello, World!"
-
-    def on_reactor_final(self, event):
-        print "Goodbye, World!"
-
-# You can pass multiple handlers to the reactor. Each handler will see
-# every event. By combining this with on_unhandled, you can print out
-# every event as it happens.
-r = Reactor(Logger(), Program())
-r.run()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/c90655b8/examples/reactor/py/reactor-logger.py
----------------------------------------------------------------------
diff --git a/examples/reactor/py/reactor-logger.py b/examples/reactor/py/reactor-logger.py
new file mode 100755
index 0000000..932a3f7
--- /dev/null
+++ b/examples/reactor/py/reactor-logger.py
@@ -0,0 +1,54 @@
+#!/usr/bin/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 time
+from proton.reactors import Reactor
+
+class Logger:
+
+    def on_unhandled(self, name, event):
+        print "LOG:", name, event
+
+class Program:
+
+    def on_reactor_init(self, event):
+        print "Hello, World!"
+
+    def on_reactor_final(self, event):
+        print "Goodbye, World!"
+
+# You can pass multiple handlers to a reactor when you construct it.
+# Each of these handlers will see every event the reactor sees. By
+# combining this with on_unhandled, you can log each event that goes
+# to the reactor.
+r = Reactor(Program(), Logger())
+r.run()
+
+# Note that if you wanted to add the logger later, you could also
+# write the above as below. All arguments to the reactor are just
+# added to the default handler for the reactor.
+
+def logging_enabled():
+    return False
+
+r = Reactor(Program())
+if logging_enabled():
+    r.handler.add(Logger())
+r.run()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/c90655b8/examples/reactor/py/recv.py
----------------------------------------------------------------------
diff --git a/examples/reactor/py/recv.py b/examples/reactor/py/recv.py
new file mode 100755
index 0000000..a3e3479
--- /dev/null
+++ b/examples/reactor/py/recv.py
@@ -0,0 +1,48 @@
+#!/usr/bin/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.reactors import Reactor
+from proton.handlers import CHandshaker, CFlowController
+
+class Program:
+
+    def __init__(self):
+        self.handlers = [CHandshaker(), CFlowController()]
+        self.message = Message()
+
+    def on_reactor_init(self, event):
+        # Create an amqp acceptor.
+        event.reactor.acceptor("0.0.0.0", 5672)
+        # There is an optional third argument to the Reactor.acceptor
+        # call. Using it, we could supply a handler here that would
+        # become the handler for all accepted connections. If we omit
+        # it, the reactor simply inherets all the connection events.
+
+    def on_delivery(self, event):
+        # XXX: we could make rcv.recv(self.message) work here to
+        # compliment the similar thing on send
+        rcv = event.receiver
+        if rcv and self.message.recv(rcv):
+            print self.message
+            event.delivery.settle()
+
+r = Reactor(Program())
+r.run()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/c90655b8/examples/reactor/py/send.py
----------------------------------------------------------------------
diff --git a/examples/reactor/py/send.py b/examples/reactor/py/send.py
index b2927a7..7f1482b 100755
--- a/examples/reactor/py/send.py
+++ b/examples/reactor/py/send.py
@@ -25,22 +25,31 @@ from proton.handlers import CHandshaker
 
 # This is a send in terms of low level AMQP events. There are handlers
 # that can streamline this significantly if you don't want to worry
-# about all the details.
+# about all the details, but it is useful to see how the AMQP engine
+# classes interact with handlers and events.
 
 class Send:
 
     def __init__(self, host, message):
         self.host = host
         self.message = message
-        # The default event dispatcher will automatically check for a
-        # handlers property and delegate the event to all children
-        # present.
+        # Use the handlers property to add some default handshaking
+        # behaviour.
         self.handlers = [CHandshaker()]
 
     def on_connection_init(self, event):
         conn = event.connection
         conn.hostname = self.host
+
+        # Every session or link could have their own handler(s) if we
+        # wanted simply by setting the "handler" slot on the
+        # given session or link.
         ssn = conn.session()
+
+        # If a link doesn't have an event handler, the events go to
+        # its parent session. If the session doesn't have a handler
+        # the events go to its parent connection. If the connection
+        # doesn't have a handler, the events go to the reactor.
         snd = ssn.sender("sender")
         conn.open()
         ssn.open()
@@ -49,16 +58,30 @@ class Send:
     def on_link_flow(self, event):
         snd = event.sender
         if snd.credit > 0:
-            snd.send(self.message)
+            dlv = snd.send(self.message)
+            dlv.settle()
             snd.close()
             snd.session.close()
             snd.connection.close()
 
 class Program:
 
+    def __init__(self, hostname, content):
+        self.hostname = hostname
+        self.content = content
+
     def on_reactor_init(self, event):
         # You can use the connection method to create AMQP connections.
-        event.reactor.connection(Send(sys.argv[1], Message(body=sys.argv[2])))
 
-r = Reactor(Program())
+        # This connection's handler is the Send object. All the events
+        # for this connection will go to the Send object instead of
+        # going to the reactor. If you were to omit the Send object,
+        # all the events would go to the reactor.
+        event.reactor.connection(Send(self.hostname, Message(self.content)))
+
+args = sys.argv[1:]
+hostname = args.pop() if args else "localhost"
+content = args.pop() if args else "Hello World!"
+
+r = Reactor(Program(hostname, content))
 r.run()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/c90655b8/examples/reactor/py/unhandled.py
----------------------------------------------------------------------
diff --git a/examples/reactor/py/unhandled.py b/examples/reactor/py/unhandled.py
index 303c89d..8275c5e 100755
--- a/examples/reactor/py/unhandled.py
+++ b/examples/reactor/py/unhandled.py
@@ -23,10 +23,10 @@ from proton.reactors import Reactor
 
 class Program:
 
-    # If an event occurs and an object doesn't have an on_<event>
+    # If an event occurs and its handler doesn't have an on_<event>
     # method, the reactor will attempt to call the on_unhandled method
-    # this can be useful not only for debugging, but for logging and
-    # for delegating/inheritance.
+    # if it exists. This can be useful not only for debugging, but for
+    # logging and for delegating/inheritance.
     def on_unhandled(self, name, event):
         print name, event
 


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org