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