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/01/30 00:12:54 UTC

qpid-proton git commit: added reactor examples

Repository: qpid-proton
Updated Branches:
  refs/heads/master 0028c1c31 -> 77d98a207


added reactor 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/77d98a20
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/77d98a20
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/77d98a20

Branch: refs/heads/master
Commit: 77d98a2070237adf9da610304a00b2f1ce0d4fd4
Parents: 0028c1c
Author: Rafael Schloming <rh...@alum.mit.edu>
Authored: Thu Jan 29 18:12:38 2015 -0500
Committer: Rafael Schloming <rh...@alum.mit.edu>
Committed: Thu Jan 29 18:12:38 2015 -0500

----------------------------------------------------------------------
 examples/reactor/py/README.md        | 19 +++++++++
 examples/reactor/py/cat.py           | 56 +++++++++++++++++++++++++++
 examples/reactor/py/counter.py       | 49 +++++++++++++++++++++++
 examples/reactor/py/delegates.py     | 48 +++++++++++++++++++++++
 examples/reactor/py/echo.py          | 56 +++++++++++++++++++++++++++
 examples/reactor/py/goodbye-world.py | 33 ++++++++++++++++
 examples/reactor/py/hello-world.py   | 42 ++++++++++++++++++++
 examples/reactor/py/logger.py        | 41 ++++++++++++++++++++
 examples/reactor/py/scheduling.py    | 52 +++++++++++++++++++++++++
 examples/reactor/py/send.py          | 64 +++++++++++++++++++++++++++++++
 examples/reactor/py/unhandled.py     | 34 ++++++++++++++++
 11 files changed, 494 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/77d98a20/examples/reactor/py/README.md
----------------------------------------------------------------------
diff --git a/examples/reactor/py/README.md b/examples/reactor/py/README.md
new file mode 100644
index 0000000..24f4f20
--- /dev/null
+++ b/examples/reactor/py/README.md
@@ -0,0 +1,19 @@
+The examples in this directory provide a basic introduction to the
+proton reactor API and are best viewed in the order presented below.
+This API is present in C as well and most of these examples will
+transliterate into C in a fairly straightforward way.
+
+  - hello-world.py
+  - goodbye-world.py
+
+  - scheduling.py
+  - counter.py
+
+  - unhandled.py
+  - logger.py
+  - delegates.py
+
+  - echo.py
+  - cat.py
+
+  - send.py

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/77d98a20/examples/reactor/py/cat.py
----------------------------------------------------------------------
diff --git a/examples/reactor/py/cat.py b/examples/reactor/py/cat.py
new file mode 100755
index 0000000..e3af19a
--- /dev/null
+++ b/examples/reactor/py/cat.py
@@ -0,0 +1,56 @@
+#!/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 sys, os
+from proton.reactors import Reactor
+
+class Echo:
+
+    def __init__(self, source):
+        self.source = source
+
+    def on_selectable_init(self, event):
+        sel = event.context # XXX: no selectable property yet
+
+        # We can configure a selectable with any file descriptor we want.
+        sel.fileno(self.source.fileno())
+        # Ask to be notified when the file is readable.
+        sel.reading = True
+        event.reactor.update(sel)
+
+    def on_selectable_readable(self, event):
+        sel = event.context
+
+        # The on_selectable_readable event tells us that there is data
+        # to be read, or the end of stream has been reached.
+        data = os.read(sel.fileno(), 1024)
+        if data:
+            print data,
+        else:
+            sel.terminate()
+            event.reactor.update(sel)
+
+class Program:
+
+    def on_reactor_init(self, event):
+        event.reactor.selectable(Echo(open(sys.argv[1])))
+
+r = Reactor(Program())
+r.run()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/77d98a20/examples/reactor/py/counter.py
----------------------------------------------------------------------
diff --git a/examples/reactor/py/counter.py b/examples/reactor/py/counter.py
new file mode 100755
index 0000000..8a2479a
--- /dev/null
+++ b/examples/reactor/py/counter.py
@@ -0,0 +1,49 @@
+#!/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 Counter:
+
+    def __init__(self, limit):
+        self.limit = limit
+        self.count = 0
+
+    def on_timer_task(self, event):
+        self.count += 1
+        print self.count
+        if self.count < self.limit:
+            # A recurring task can be acomplished by just scheduling
+            # another event.
+            event.reactor.schedule(0.25, self)
+
+class Program:
+
+    def on_reactor_init(self, event):
+        self.start = time.time()
+        print "Hello, World!"
+        event.reactor.schedule(0.25, Counter(10))
+
+    def on_reactor_final(self, event):
+        print "Goodbye, World! (after %s long seconds)" % (time.time() - self.start)
+
+r = Reactor(Program())
+r.run()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/77d98a20/examples/reactor/py/delegates.py
----------------------------------------------------------------------
diff --git a/examples/reactor/py/delegates.py b/examples/reactor/py/delegates.py
new file mode 100755
index 0000000..b81338d
--- /dev/null
+++ b/examples/reactor/py/delegates.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
+
+# Events know how to dispatch themselves to handlers. By combining
+# this with on_unhandled, you can provide a kind of inheritance
+# between handlers using delegation.
+
+class Hello:
+
+    def on_reactor_init(self, event):
+        print "Hello, World!"
+
+class Goodbye:
+
+    def on_reactor_final(self, event):
+        print "Goodbye, World!"
+
+class Program:
+
+    def __init__(self, *delegates):
+        self.delegates = delegates
+
+    def on_unhandled(self, name, event):
+        for d in self.delegates:
+            event.dispatch(d)
+
+r = Reactor(Program(Hello(), Goodbye()))
+r.run()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/77d98a20/examples/reactor/py/echo.py
----------------------------------------------------------------------
diff --git a/examples/reactor/py/echo.py b/examples/reactor/py/echo.py
new file mode 100755
index 0000000..ecf1c9d
--- /dev/null
+++ b/examples/reactor/py/echo.py
@@ -0,0 +1,56 @@
+#!/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 sys, os
+from proton.reactors import Reactor
+
+class Echo:
+
+    def __init__(self, source):
+        self.source = source
+
+    def on_selectable_init(self, event):
+        sel = event.context # XXX: no selectable property yet
+
+        # We can configure a selectable with any file descriptor we want.
+        sel.fileno(self.source.fileno())
+        # Ask to be notified when the file is readable.
+        sel.reading = True
+        event.reactor.update(sel)
+
+    def on_selectable_readable(self, event):
+        sel = event.context
+
+        # The on_selectable_readable event tells us that there is data
+        # to be read, or the end of stream has been reached.
+        data = os.read(sel.fileno(), 1024)
+        if data:
+            print data,
+        else:
+            sel.terminate()
+            event.reactor.update(sel)
+
+class Program:
+
+    def on_reactor_init(self, event):
+        event.reactor.selectable(Echo(sys.stdin))
+
+r = Reactor(Program())
+r.run()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/77d98a20/examples/reactor/py/goodbye-world.py
----------------------------------------------------------------------
diff --git a/examples/reactor/py/goodbye-world.py b/examples/reactor/py/goodbye-world.py
new file mode 100755
index 0000000..6037ef9
--- /dev/null
+++ b/examples/reactor/py/goodbye-world.py
@@ -0,0 +1,33 @@
+#!/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.reactors import Reactor
+
+class Program:
+
+    def on_reactor_init(self, event):
+        print "Hello, World!"
+
+    # The reactor produces an event when it is about to exit.
+    def on_reactor_final(self, event):
+        print "Goodbye, World!"
+
+r = Reactor(Program())
+r.run()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/77d98a20/examples/reactor/py/hello-world.py
----------------------------------------------------------------------
diff --git a/examples/reactor/py/hello-world.py b/examples/reactor/py/hello-world.py
new file mode 100755
index 0000000..8c35b85
--- /dev/null
+++ b/examples/reactor/py/hello-world.py
@@ -0,0 +1,42 @@
+#!/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.reactors import Reactor
+
+# The proton reactor provides a general purpose event processing
+# library for writing reactive programs. A reactive program is defined
+# by a set of event handlers. An event handler is just any class or
+# object that defines the "on_<event>" methods that it cares to
+# handle.
+
+class Program:
+
+    # The reactor init event is produced by the reactor itself when it
+    # starts.
+    def on_reactor_init(self, event):
+        print "Hello, World!"
+
+# When you construct a reactor, you give it a handler.
+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.
+r.run()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/77d98a20/examples/reactor/py/logger.py
----------------------------------------------------------------------
diff --git a/examples/reactor/py/logger.py b/examples/reactor/py/logger.py
new file mode 100755
index 0000000..bcc8a9f
--- /dev/null
+++ b/examples/reactor/py/logger.py
@@ -0,0 +1,41 @@
+#!/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/77d98a20/examples/reactor/py/scheduling.py
----------------------------------------------------------------------
diff --git a/examples/reactor/py/scheduling.py b/examples/reactor/py/scheduling.py
new file mode 100755
index 0000000..b2a1af7
--- /dev/null
+++ b/examples/reactor/py/scheduling.py
@@ -0,0 +1,52 @@
+#!/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 Program:
+
+    def on_reactor_init(self, event):
+        self.start = time.time()
+        print "Hello, World!"
+
+        # If we want to hang around for a bit longer, we can schedule
+        # a task event for some point in the future. This will cause the
+        # reactor to stick around until it has a chance to process the
+        # event.
+
+        # The first argument is the delay. The second argument to is
+        # the handler for the event. We are just using self for now,
+        # but we could pass in another object if we wanted.
+        task = event.reactor.schedule(1.0, self)
+
+        # We can ignore the task if we want to, but we can also use it
+        # to pass stuff to the handler.
+        task.something_to_say = "Yay"
+
+    def on_timer_task(self, event):
+        task = event.context # xxx: don't have a task property on event yet
+        print task.something_to_say, "my task is complete!"
+
+    def on_reactor_final(self, event):
+        print "Goodbye, World! (after %s long seconds)" % (time.time() - self.start)
+
+r = Reactor(Program())
+r.run()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/77d98a20/examples/reactor/py/send.py
----------------------------------------------------------------------
diff --git a/examples/reactor/py/send.py b/examples/reactor/py/send.py
new file mode 100755
index 0000000..b2927a7
--- /dev/null
+++ b/examples/reactor/py/send.py
@@ -0,0 +1,64 @@
+#!/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 sys
+from proton import Message
+from proton.reactors import Reactor
+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.
+
+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.
+        self.handlers = [CHandshaker()]
+
+    def on_connection_init(self, event):
+        conn = event.connection
+        conn.hostname = self.host
+        ssn = conn.session()
+        snd = ssn.sender("sender")
+        conn.open()
+        ssn.open()
+        snd.open()
+
+    def on_link_flow(self, event):
+        snd = event.sender
+        if snd.credit > 0:
+            snd.send(self.message)
+            snd.close()
+            snd.session.close()
+            snd.connection.close()
+
+class Program:
+
+    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())
+r.run()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/77d98a20/examples/reactor/py/unhandled.py
----------------------------------------------------------------------
diff --git a/examples/reactor/py/unhandled.py b/examples/reactor/py/unhandled.py
new file mode 100755
index 0000000..303c89d
--- /dev/null
+++ b/examples/reactor/py/unhandled.py
@@ -0,0 +1,34 @@
+#!/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 Program:
+
+    # If an event occurs and an object 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.
+    def on_unhandled(self, name, event):
+        print name, event
+
+r = Reactor(Program())
+r.run()


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