[pytango] 20/25: Add asyncio support for clients
Sandor Bodo-Merle
sbodomerle-guest at moszumanska.debian.org
Thu Sep 28 19:17:17 UTC 2017
This is an automated email from the git hooks/post-receive script.
sbodomerle-guest pushed a commit to tag v8.1.9
in repository pytango.
commit 3c013ab76a293efa1b7c184f887b6a2a8265a61d
Author: Vincent Michel <vincent.michel at maxlab.lu.se>
Date: Tue Aug 9 11:37:15 2016 +0200
Add asyncio support for clients
---
src/boost/python/green.py | 247 +++++++++++++++++++++++++++++++---------------
1 file changed, 170 insertions(+), 77 deletions(-)
diff --git a/src/boost/python/green.py b/src/boost/python/green.py
index a0ec36f..4fc1fc5 100644
--- a/src/boost/python/green.py
+++ b/src/boost/python/green.py
@@ -1,4 +1,4 @@
-# ------------------------------------------------------------------------------
+# -----------------------------------------------------------------------------
# This file is part of PyTango (http://www.tinyurl.com/PyTango)
#
# Copyright 2006-2012 CELLS / ALBA Synchrotron, Bellaterra, Spain
@@ -7,43 +7,64 @@
# Distributed under the terms of the GNU Lesser General Public License,
# either version 3 of the License, or (at your option) any later version.
# See LICENSE.txt for more info.
-# ------------------------------------------------------------------------------
-
-__all__ = ["get_green_mode", "set_green_mode",
- "get_executor", "submit", "spawn",
- "get_synch_executor", "synch_submit",
- "get_gevent_executor", "gevent_submit",
- "get_futures_executor", "futures_submit",
- "get_event_loop", "get_gevent_event_loop",
- "result", "submitable", "green", "green_cb"]
+# -----------------------------------------------------------------------------
+
+__all__ = [
+ "get_green_mode", "set_green_mode",
+ "get_executor", "submit", "spawn", "result", "wait",
+ "get_synch_executor", "synch_submit", "synch_wait",
+ "get_gevent_executor", "gevent_submit", "gevent_wait",
+ "get_futures_executor", "futures_submit", "futures_wait",
+ "get_asyncio_executor", "asyncio_submit", "asyncio_wait",
+ "get_object_submitter", "get_object_waiter", "get_object_green_mode",
+ "green", "green_cb", "get_wait_default_value",
+ "get_event_loop", "get_gevent_event_loop"]
__docformat__ = "restructuredtext"
+
+# Imports
import os
-from functools import wraps
+from functools import wraps, partial
+# Tango imports
from ._PyTango import GreenMode
+
+# Gevent imports
from .tango_gevent import get_global_executor as get_gevent_executor
from .tango_gevent import submit as gevent_submit
+from .tango_gevent import wait as gevent_wait
from .tango_gevent import get_event_loop as get_gevent_event_loop
+
+# Futures imports
from .tango_futures import get_global_executor as get_futures_executor
from .tango_futures import submit as futures_submit
+from .tango_futures import wait as futures_wait
+
+# Asyncio imports
+from .tango_asyncio import get_global_executor as get_asyncio_executor
+from .tango_asyncio import submit as asyncio_submit
+from .tango_asyncio import wait as asyncio_wait
+from .tango_asyncio import get_event_loop as get_asyncio_event_loop
+
+
+# Handle current green mode
__default_green_mode = GreenMode.Synchronous
try:
- __current_green_mode = getattr(GreenMode,
- os.environ.get("PYTANGO_GREEN_MODE",
- "Synchronous").capitalize())
-except:
+ __current_green_mode = getattr(
+ GreenMode,
+ os.environ["PYTANGO_GREEN_MODE"].capitalize())
+except Exception:
__current_green_mode = __default_green_mode
def set_green_mode(green_mode=None):
"""Sets the global default PyTango green mode.
- Advice: Use only in your final application. Don't use this in a python library
- in order not to interfere with the beavior of other libraries and/or
- application where your library is being.
+ Advice: Use only in your final application. Don't use this in a python
+ library in order not to interfere with the beavior of other libraries
+ and/or application where your library is being.
:param green_mode: the new global default PyTango green mode
:type green_mode: GreenMode
@@ -57,7 +78,9 @@ def set_green_mode(green_mode=None):
elif green_mode == GreenMode.Futures:
# check if we can change to futures mode
import PyTango.futures
-
+ elif green_mode == GreenMode.Asyncio:
+ # check if we can change to asyncio mode
+ import PyTango.asyncio
__current_green_mode = green_mode
@@ -70,91 +93,160 @@ def get_green_mode():
return __current_green_mode
+# Synchronous execution
+
class SynchExecutor(object):
def submit(self, fn, *args, **kwargs):
return fn(*args, **kwargs)
__synch_executor = SynchExecutor()
+
def get_synch_executor():
return __synch_executor
+
def synch_submit(fn, *args, **kwargs):
return get_synch_executor().submit(fn, *args, **kwargs)
+
+def synch_wait(res, timeout=None):
+ return res
+
+
+# Excutor, submitter and waiter mapping
+
__executor_map = {
GreenMode.Synchronous: get_synch_executor,
GreenMode.Futures: get_futures_executor,
GreenMode.Gevent: get_gevent_executor,
+ GreenMode.Asyncio: get_asyncio_executor,
}
__submit_map = {
GreenMode.Synchronous: synch_submit,
GreenMode.Futures: futures_submit,
GreenMode.Gevent: gevent_submit,
+ GreenMode.Asyncio: asyncio_submit,
+}
+
+__wait_map = {
+ GreenMode.Synchronous: synch_wait,
+ GreenMode.Futures: futures_wait,
+ GreenMode.Gevent: gevent_wait,
+ GreenMode.Asyncio: asyncio_wait,
}
+
__event_loop_map = {
+ GreenMode.Synchronous: (lambda: None),
+ GreenMode.Futures: (lambda: None),
GreenMode.Gevent: get_gevent_event_loop,
+ GreenMode.Asyncio: get_asyncio_event_loop,
}
+
+# Getters
+
def get_executor(mode):
return __executor_map[mode]()
+
def get_submitter(mode):
return __submit_map[mode]
+
+def get_waiter(mode):
+ return __wait_map[mode]
+
+
+def get_wait_default_value(mode):
+ if mode is None:
+ mode = get_green_mode()
+ return mode not in (GreenMode.Asyncio,)
+
+
+# Generic submitter/spawner and waiter
+
def submit(mode, fn, *args, **kwargs):
return get_submitter(mode)(fn, *args, **kwargs)
spawn = submit
+
+def wait_result(ret, green_mode=None, timeout=None):
+ if green_mode is None:
+ green_mode = get_green_mode()
+ return get_waiter(green_mode)(ret, timeout=timeout)
+
+wait = wait_result
+
+
+def result(ret, green_mode=None, wait=True, timeout=None):
+ if not wait:
+ return ret
+ return wait_result(ret, green_mode=green_mode, timeout=timeout)
+
+
def get_event_loop(mode):
- f = __event_loop_map.get(mode)
- if f:
- return f()
-
-def result(value, green_mode, wait=True, timeout=None):
- if wait and not green_mode is GreenMode.Synchronous:
- if green_mode == GreenMode.Futures:
- return value.result(timeout=timeout)
- elif green_mode == GreenMode.Gevent:
- return value.get(timeout=timeout)
- return value
-
-def submitable(obj, green_mode=None):
- """Returns a proper submit callable for the given object.
-
- If the object has *_executors* and *_green_mode* members it returns a submit
- callable for the executor corresponding to the green_mode.
- Otherwise it returns the global submit callable for the given green_mode
-
- :returns: green_mode, submit callable"""
- # determine the efective green_mode
+ return __event_loop_map[mode]()
+
+
+# Get object submitter, waiter and green_mode
+
+def get_object_green_mode(obj):
+ if hasattr(obj, "get_green_mode"):
+ return obj.get_green_mode()
+ return get_green_mode()
+
+
+def get_object_submitter(obj, green_mode=None):
+ """Returns the proper submit callable for the given object.
+
+ If the object has *_executors* and *_green_mode* members it returns
+ the submit callable for the executor corresponding to the green_mode.
+ Otherwise it returns the global submit callable for the given green_mode.
+
+ :returns: submit callable"""
+ # Get green mode
+ if green_mode is None:
+ green_mode = get_object_green_mode(obj)
+ # Get executor
+ executors = getattr(obj, "_executors", {})
+ executor = executors.get(green_mode, None)
+ if executor is None:
+ executor = get_executor(green_mode)
+ # Get submitter
+ if green_mode == GreenMode.Gevent:
+ return executor.spawn
+ return executor.submit
+
+
+def get_object_waiter(obj, green_mode=None):
+ """Returns the proper wait callable for the given object.
+
+ If the object has *_executors* and *_green_mode* members it returns
+ the wait callable for the executor corresponding to the green_mode.
+ Otherwise it returns the global wait callable for the given green_mode.
+
+ :returns: wait callable"""
+ # Get green mode
if green_mode is None:
- if hasattr(obj, "get_green_mode"):
- green_mode = obj.get_green_mode()
- else:
- green_mode = get_green_mode()
-
- if green_mode == GreenMode.Synchronous:
- return green_mode, synch_submit
-
- has_executors = hasattr(obj, "_executors")
- s_func = __submit_map[green_mode]
- if green_mode == GreenMode.Futures:
- if has_executors:
- executor = obj._executors.get(GreenMode.Futures)
- if executor:
- s_func = executor.submit
- elif green_mode == GreenMode.Gevent:
- if has_executors:
- executor = obj._executors.get(GreenMode.Gevent)
- if executor:
- s_func = executor.spawn
- else:
- raise TypeError("Undefined green_mode '%s' for %s" % (str(green_mode)), str(obj))
- return green_mode, s_func
+ green_mode = get_object_green_mode(obj)
+ # Get waiter
+ waiter = get_waiter(green_mode)
+ # Asyncio corner case
+ if green_mode == GreenMode.Asyncio:
+ executors = getattr(obj, "_executors", {})
+ executor = executors.get(GreenMode.Asyncio)
+ if executor is None:
+ return waiter
+ return partial(waiter, loop=executor.loop)
+ # Return waiter
+ return waiter
+
+
+# Green decorators
def green(fn):
"""make a method green. Can be used as a decorator"""
@@ -162,30 +254,31 @@ def green(fn):
@wraps(fn)
def greener(self, *args, **kwargs):
# first take out all green parameters
- green_mode = kwargs.pop('green_mode', None)
- wait = kwargs.pop('wait', True)
+ green_mode = kwargs.pop('green_mode', get_object_green_mode(self))
+ wait = kwargs.pop('wait', get_wait_default_value(green_mode))
timeout = kwargs.pop('timeout', None)
# get the proper submitable for the given green_mode
- green_mode, submit = submitable(self, green_mode)
+ submitter = get_object_submitter(self, green_mode)
+ waiter = get_object_waiter(self, green_mode)
# submit the method
- ret = submit(fn, self, *args, **kwargs)
-
- # return the proper result
- return result(ret, green_mode, wait=wait, timeout=timeout)
- return greener
+ ret = submitter(fn, self, *args, **kwargs)
+
+ # return the proper result
+ return waiter(ret, timeout=timeout) if wait else ret
+
+ return greener
+
def green_cb(fn, green_mode=None):
"""return a green verion of the given callback."""
+ event_loop = get_event_loop(green_mode)
+ if event_loop is None:
+ return fn
@wraps(fn)
def greener(*args, **kwargs):
- event_loop = get_event_loop(green_mode)
- if event_loop is None:
- fn(*args, **kwargs)
- else:
- event_loop.submit(fn, *args, **kwargs)
+ event_loop.submit(fn, *args, **kwargs)
return greener
-
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/pytango.git
More information about the debian-science-commits
mailing list