commit c74c1f781d73614ae49b7118ec3762ea5a4f1736
parent 8b1a5add4bc4eca3a1c80cc9ce26addd1f6225d8
Author: Joris Vink <joris@coders.se>
Date: Thu, 22 Nov 2018 15:23:44 +0100
Add python-async example.
Diffstat:
8 files changed, 254 insertions(+), 0 deletions(-)
diff --git a/examples/python-async/.gitignore b/examples/python-async/.gitignore
@@ -0,0 +1,6 @@
+*.o
+.flavor
+.objs
+python-async.so
+assets.h
+cert
diff --git a/examples/python-async/README.md b/examples/python-async/README.md
@@ -0,0 +1,11 @@
+Kore python async/await examples.
+
+Run:
+```
+ $ kodev run
+```
+
+Test:
+```
+ $ curl -k https://127.0.0.1:8888/queue
+```
diff --git a/examples/python-async/conf/build.conf b/examples/python-async/conf/build.conf
@@ -0,0 +1,34 @@
+# python-async build config
+# You can switch flavors using: kodev flavor [newflavor]
+
+# Set to yes if you wish to produce a single binary instead
+# of a dynamic library. If you set this to yes you must also
+# set kore_source together with kore_flavor.
+single_binary=yes
+kore_source=../../
+kore_flavor=PYTHON=1
+
+# The flags below are shared between flavors
+cflags=-Wall -Wmissing-declarations -Wshadow
+cflags=-Wstrict-prototypes -Wmissing-prototypes
+cflags=-Wpointer-arith -Wcast-qual -Wsign-compare
+
+cxxflags=-Wall -Wmissing-declarations -Wshadow
+cxxflags=-Wpointer-arith -Wcast-qual -Wsign-compare
+
+# Mime types for assets served via the builtin asset_serve_*
+#mime_add=txt:text/plain; charset=utf-8
+#mime_add=png:image/png
+#mime_add=html:text/html; charset=utf-8
+
+dev {
+ # These flags are added to the shared ones when
+ # you build the "dev" flavor.
+ cflags=-g
+ cxxflags=-g
+}
+
+#prod {
+# You can specify additional flags here which are only
+# included if you build with the "prod" flavor.
+#}
diff --git a/examples/python-async/conf/python-async.conf b/examples/python-async/conf/python-async.conf
@@ -0,0 +1,21 @@
+# python-async configuration
+
+bind 127.0.0.1 8888
+
+tls_dhparam dh2048.pem
+
+python_path src
+
+python_import ./src/setup.py
+python_import ./src/async_lock.py
+python_import ./src/async_queue.py
+python_import ./src/async_process.py
+
+domain * {
+ certfile cert/server.pem
+ certkey cert/key.pem
+
+ static /queue async_queue
+ static /lock async_lock
+ static /proc async_proc
+}
diff --git a/examples/python-async/src/async_lock.py b/examples/python-async/src/async_lock.py
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2018 Joris Vink <joris@coders.se>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+
+#
+# Locking example.
+#
+# The handler for /lock will grab the shared lock, suspend itself for
+# 5 seconds before releasing the lock and responding.
+#
+# While the lock is held, other requests to /lock will block until it
+# is released.
+
+import kore
+
+# The shared lock
+lock = kore.lock()
+
+async def async_lock(req):
+ # A kore.lock should be used with the "async with" syntax.
+ async with lock:
+ # Suspend for 5 seconds.
+ await kore.suspend(5000)
+
+ # Now respond.
+ req.response(200, b'')
diff --git a/examples/python-async/src/async_process.py b/examples/python-async/src/async_process.py
@@ -0,0 +1,64 @@
+#
+# Copyright (c) 2018 Joris Vink <joris@coders.se>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+
+#
+# Asynchronous process example.
+#
+# Wait for the result of an external process asynchronously.
+# The handler will execute "/bin/ls" on the current directory and
+# read the result.
+#
+
+import kore
+import json
+
+async def async_proc(req):
+ #
+ # You may specify a timeout when creating the kore.proc object.
+ # If the timeout is reached before the process exits kore will
+ # raise a TimeoutError exception.
+ #
+ # Ex: set timeout to 100ms:
+ # proc = kore.proc("/bin/ls -lR", 100)
+
+ proc = kore.proc("/bin/ls -lR")
+
+ try:
+ stdout = ""
+
+ # Read until EOF (None is returned)
+ while True:
+ chunk = await proc.recv(1024)
+ if chunk is None:
+ break
+ stdout += chunk.decode()
+
+ # Reap the process.
+ retcode = await proc.reap()
+
+ # Respond with the return code + the result as JSON.
+ payload = {
+ "retcode": retcode,
+ "stdout": stdout
+ }
+
+ data = json.dumps(payload, indent=4)
+ req.response(200, data.encode())
+ except Exception as e:
+ # If an exception occurs we must kill the process first.
+ proc.kill()
+ errmsg = "Exception: %s" % e
+ req.response(500, errmsg.encode())
diff --git a/examples/python-async/src/async_queue.py b/examples/python-async/src/async_queue.py
@@ -0,0 +1,57 @@
+#
+# Copyright (c) 2018 Joris Vink <joris@coders.se>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+
+#
+# Asynchronous queue example.
+#
+
+import kore
+
+# The shared queue.
+tq = kore.queue()
+
+# Entry point for our independent coroutine that is created when kore starts.
+async def queue_helper():
+ while True:
+ # Wait for a dictionary to arrive.
+ obj = await tq.pop()
+ kore.log(kore.LOG_INFO, "coro(): received %s" % obj)
+
+ # Create a message to send back.
+ msg = "%d = %s" % (kore.time(), obj["msg"])
+
+ # Send it on the received queue.
+ obj["rq"].push(msg)
+
+async def async_queue(req):
+ # Create our own queue.
+ rq = kore.queue()
+
+ # The dictionary we are going to send.
+ obj = {
+ # Receive queue object.
+ "rq": rq,
+ "msg": "hello"
+ }
+
+ # Push it onto the tq queue now, which will wake up the other coroutine.
+ tq.push(obj)
+
+ # Wait for a response.
+ response = await rq.pop()
+
+ # Send the response to the client.
+ req.response(200, response.encode())
diff --git a/examples/python-async/src/setup.py b/examples/python-async/src/setup.py
@@ -0,0 +1,23 @@
+#
+# Copyright (c) 2018 Joris Vink <joris@coders.se>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+
+import kore
+
+from async_queue import queue_helper
+
+# Kore worker started, start the queue helper coroutine.
+def kore_worker_configure():
+ kore.task_create(queue_helper())