[pytango] 271/483: green pytango feature
Sandor Bodo-Merle
sbodomerle-guest at moszumanska.debian.org
Thu Sep 28 19:14:49 UTC 2017
This is an automated email from the git hooks/post-receive script.
sbodomerle-guest pushed a commit to annotated tag bliss_8.10
in repository pytango.
commit 07464f01cca7212e2d3e8df8a8eb63903259ca4e
Author: tiagocoutinho <tiagocoutinho at 4e9c00fd-8f2e-0410-aa12-93ce3db5e235>
Date: Wed Jul 17 14:44:09 2013 +0000
green pytango feature
git-svn-id: http://svn.code.sf.net/p/tango-cs/code/bindings/PyTango/trunk@23143 4e9c00fd-8f2e-0410-aa12-93ce3db5e235
---
doc/client/miscellaneous.rst | 8 +-
doc/client/other.rst | 5 +-
doc/utilities.rst | 4 +
src/boost/cpp/base_types.cpp | 6 +
src/boost/cpp/defs.h | 6 +
src/boost/cpp/device_proxy.cpp | 8 +-
src/boost/python/__init__.py | 6 +-
src/boost/python/attribute_proxy.py | 71 +++++++-
src/boost/python/base_types.py | 10 ++
src/boost/python/connection.py | 25 ++-
src/boost/python/device_proxy.py | 311 ++++++++++++++++++++++++++++++++----
src/boost/python/group.py | 4 +-
src/boost/python/tango_futures.py | 61 +++++++
src/boost/python/tango_gevent.py | 37 +++++
src/boost/python/tango_green.py | 140 ++++++++++++++++
src/boost/python/utils.py | 39 ++++-
16 files changed, 695 insertions(+), 46 deletions(-)
diff --git a/doc/client/miscellaneous.rst b/doc/client/miscellaneous.rst
index 55cd8c2..e8f5b9c 100644
--- a/doc/client/miscellaneous.rst
+++ b/doc/client/miscellaneous.rst
@@ -1,6 +1,11 @@
+.. currentmodule:: PyTango
+Green creation of PyTango objects
+---------------------------------
-.. currentmodule:: PyTango
+.. autofunction:: get_device_proxy
+
+.. autofunction:: get_attribute_proxy
API util
--------
@@ -15,6 +20,7 @@ See also `Event configuration information`_
Attribute
~~~~~~~~~
+
.. autoclass:: PyTango.AttributeAlarmInfo
:members:
diff --git a/doc/client/other.rst b/doc/client/other.rst
index 910e026..d8b7fe8 100644
--- a/doc/client/other.rst
+++ b/doc/client/other.rst
@@ -50,6 +50,9 @@ Enumerations
.. autoclass:: PyTango.DispLevel
+.. autoclass:: PyTango.GreenMode
+
+
Other classes
~~~~~~~~~~~~~
@@ -57,4 +60,4 @@ Other classes
:members:
.. autoclass:: PyTango.TimeVal
- :members:
\ No newline at end of file
+ :members:
diff --git a/doc/utilities.rst b/doc/utilities.rst
index 962e8dd..5412ca9 100644
--- a/doc/utilities.rst
+++ b/doc/utilities.rst
@@ -12,6 +12,10 @@ The Utilities API
:members:
:undoc-members:
+.. autofunction:: PyTango.utils.get_green_mode
+
+.. autofunction:: PyTango.utils.set_green_mode
+
.. autofunction:: PyTango.utils.is_scalar_type
.. autofunction:: PyTango.utils.is_array_type
diff --git a/src/boost/cpp/base_types.cpp b/src/boost/cpp/base_types.cpp
index b2fd009..66e05b4 100644
--- a/src/boost/cpp/base_types.cpp
+++ b/src/boost/cpp/base_types.cpp
@@ -188,6 +188,12 @@ void export_base_types()
.value("Nothing", PyTango::ExtractAsNothing)
;
+ enum_<PyTango::GreenMode>("GreenMode")
+ .value("Synchronous", PyTango::GreenModeSynchronous)
+ .value("Futures", PyTango::GreenModeFutures)
+ .value("Gevent", PyTango::GreenModeGevent)
+ ;
+
enum_<PyTango::ImageFormat>("_ImageFormat")
.value("RawImage", PyTango::RawImage)
.value("JpegImage", PyTango::JpegImage)
diff --git a/src/boost/cpp/defs.h b/src/boost/cpp/defs.h
index 8e1e5e2..c73ccb1 100644
--- a/src/boost/cpp/defs.h
+++ b/src/boost/cpp/defs.h
@@ -64,4 +64,10 @@ namespace PyTango
RawImage,
JpegImage
};
+
+ enum GreenMode {
+ GreenModeSynchronous,
+ GreenModeFutures,
+ GreenModeGevent
+ };
}
diff --git a/src/boost/cpp/device_proxy.cpp b/src/boost/cpp/device_proxy.cpp
index bc5c099..8ab73e3 100644
--- a/src/boost/cpp/device_proxy.cpp
+++ b/src/boost/cpp/device_proxy.cpp
@@ -553,21 +553,21 @@ void export_device_proxy()
&PyDeviceProxy::read_attribute,
( arg_("self"), arg_("attr_name"), arg_("extract_as")=PyTango::ExtractAsNumpy ) )
- .def("read_attributes",
+ .def("_read_attributes",
&PyDeviceProxy::read_attributes,
( arg_("self"), arg_("attr_names"), arg_("extract_as")=PyTango::ExtractAsNumpy ) )
- .def("write_attribute",
+ .def("_write_attribute",
(void (*)(Tango::DeviceProxy&, const string &, bopy::object ))
&PyDeviceProxy::write_attribute,
( arg_("self"), arg_("attr_name"), arg_("value") ) )
- .def("write_attribute",
+ .def("_write_attribute",
(void (*)(Tango::DeviceProxy&, const Tango::AttributeInfo &, bopy::object ))
&PyDeviceProxy::write_attribute,
( arg_("self"), arg_("attr_info"), arg_("value") ) )
- .def("write_attributes",
+ .def("_write_attributes",
&PyDeviceProxy::write_attributes,
( arg_("self"), arg_("name_val") ) )
diff --git a/src/boost/python/__init__.py b/src/boost/python/__init__.py
index 64e8aee..08ccd5f 100644
--- a/src/boost/python/__init__.py
+++ b/src/boost/python/__init__.py
@@ -143,7 +143,7 @@ from ._PyTango import (AccessControlType, ApiUtil, ArchiveEventInfo,
DeviceImpl, DeviceInfo, DeviceUnlocked, Device_2Impl,
Device_3Impl, Device_4Impl, DispLevel, EncodedAttribute, ErrSeverity,
EventData, EventSystemFailed, EventType,
- Except, ExtractAs, FMT_UNKNOWN, GroupAttrReply, GroupAttrReplyList,
+ Except, ExtractAs, GreenMode, FMT_UNKNOWN, GroupAttrReply, GroupAttrReplyList,
GroupCmdReply, GroupCmdReplyList, GroupReply, GroupReplyList,
IMAGE, ImageAttr, KeepAliveCmdCode, Level, LockCmdCode, LockerInfo,
LockerLanguage, LogLevel, LogTarget, Logger, Logging, MessBoxType,
@@ -176,7 +176,7 @@ from .log4tango import TangoStream, LogIt, DebugIt, InfoIt, WarnIt, \
from .device_server import ChangeEventProp, PeriodicEventProp, \
ArchiveEventProp, AttributeAlarm, EventProperties, AttributeConfig, \
AttributeConfig_2, AttributeConfig_3, MultiAttrProp
-from .attribute_proxy import AttributeProxy
+from .attribute_proxy import AttributeProxy, get_attribute_proxy
from .group import Group
from .pyutil import Util
from .device_class import DeviceClass
@@ -186,6 +186,8 @@ from .globals import get_class, get_classes, get_cpp_class, get_cpp_classes, \
from .utils import is_scalar_type, is_array_type, is_numerical_type, \
is_int_type, is_float_type, obj_2_str, seqStr_2_obj
from .utils import server_run
+from .utils import set_green_mode, get_green_mode
+from .device_proxy import get_device_proxy
from .tango_numpy import NumpyType, numpy_type, numpy_spectrum, numpy_image
from .pytango_init import init as __init
diff --git a/src/boost/python/attribute_proxy.py b/src/boost/python/attribute_proxy.py
index 66fd972..1e6d59d 100644
--- a/src/boost/python/attribute_proxy.py
+++ b/src/boost/python/attribute_proxy.py
@@ -29,16 +29,77 @@ To access these members use directly :mod:`PyTango` module and NOT
PyTango.attribute_proxy.
"""
-__all__ = [ "AttributeProxy", "attribute_proxy_init"]
+__all__ = [ "AttributeProxy", "attribute_proxy_init", "get_attribute_proxy" ]
__docformat__ = "restructuredtext"
+import collections
+
from ._PyTango import StdStringVector, DbData, DbDatum, DeviceProxy
from ._PyTango import __AttributeProxy as _AttributeProxy
from .utils import seq_2_StdStringVector, seq_2_DbData, DbData_2_dict, \
- is_pure_str, is_non_str_seq
-import collections
+ is_pure_str, is_non_str_seq, get_green_mode
+from .tango_green import result, submit, green
+
+def get_attribute_proxy(*args, **kwargs):
+ """
+ get_attribute_proxy(self, full_attr_name, green_mode=None, wait=True, timeout=True) -> AttributeProxy
+ get_attribute_proxy(self, device_proxy, attr_name, green_mode=None, wait=True, timeout=True) -> AttributeProxy
+
+ Returns a new :class:`~PyTango.AttributeProxy`.
+ There is no difference between using this function and the direct
+ :class:`~PyTango.AttributeProxy` constructor if you use the default kwargs.
+
+ The added value of this function becomes evident when you choose a green_mode
+ to be *Futures* or *Gevent*. The AttributeProxy constructor internally makes some
+ network calls which makes it *slow*. By using one of the *green modes* as
+ green_mode you are allowing other python code to be executed in a cooperative way.
+
+ :param full_attr_name: the full name of the attribute
+ :type full_attr_name: str
+ :param device_proxy: the :class:`~PyTango.DeviceProxy`
+ :type device_proxy: DeviceProxy
+ :param attr_name: attribute name for the given device proxy
+ :type attr_name: str
+ :param green_mode: determines the mode of execution of the device (including
+ the way it is created). Defaults to the current global
+ green_mode (check :func:`~PyTango.utils.get_green_mode` and
+ :func:`~PyTango.utils.set_green_mode`)
+ :type green_mode: :obj:`~PyTango.GreenMode`
+ :param wait: whether or not to wait for result. If green_mode
+ Ignored when green_mode is Synchronous (always waits).
+ :type wait: bool
+ :param timeout: The number of seconds to wait for the result.
+ If None, then there is no limit on the wait time.
+ Ignored when green_mode is Synchronous or wait is False.
+ :type timeout: float
+ :returns:
+ if green_mode is Synchronous or wait is True:
+ :class:`~PyTango.AttributeProxy`
+ else if green_mode is Futures:
+ :class:`concurrent.futures.Future`
+ else if green_mode is Gevent:
+ :class:`gevent.event.AsynchResult`
+ :throws:
+ * a *DevFailed* if green_mode is Synchronous or wait is True
+ and there is an error creating the attribute.
+ * a *concurrent.futures.TimeoutError* if green_mode is Futures,
+ wait is False, timeout is not None and the time to create the attribute
+ has expired.
+ * a *gevent.timeout.Timeout* if green_mode is Gevent, wait is False,
+ timeout is not None and the time to create the attribute has expired.
+
+ New in PyTango 8.1.0
+ """
+ # we cannot use the green wrapper because it consumes the green_mode and we
+ # want to forward it to the DeviceProxy constructor
+ green_mode = kwargs.get('green_mode', get_green_mode())
+ wait = kwargs.pop('wait', True)
+ timeout = kwargs.pop('timeout', None)
+
+ d = submit(green_mode, AttributeProxy, *args, **kwargs)
+ return result(d, green_mode, wait=wait, timeout=timeout)
def __AttributeProxy__get_property(self, propname, value=None):
"""
@@ -239,10 +300,12 @@ class AttributeProxy(object):
python reimplementation of the AttributeProxy found on the C++ API.
"""
def __init__(self, *args, **kwds):
+ green_mode = kwds.pop('green_mode', get_green_mode())
self.__attr_proxy = _AttributeProxy(*args, **kwds)
# get_device_proxy() returns a different python object each time
# we don't want a different object, so we save the current one.
- self.__dev_proxy = self.__attr_proxy.get_device_proxy()
+ self.__dev_proxy = dp = self.__attr_proxy.get_device_proxy()
+ dp.set_green_mode(green_mode)
def get_device_proxy(self):
"""
diff --git a/src/boost/python/base_types.py b/src/boost/python/base_types.py
index 909a0f4..ca4b24d 100644
--- a/src/boost/python/base_types.py
+++ b/src/boost/python/base_types.py
@@ -594,6 +594,16 @@ def __doc_base_types():
- OPERATOR
- EXPERT
""" )
+
+ document_enum("GreenMode", """
+ An enumeration representing the GreenMode
+
+ - Synchronous
+ - Futures
+ - Gevent
+
+ New in PyTango 8.1.0
+ """ )
ArchiveEventInfo.__doc__ = """
A structure containing available archiving event information for an attribute
diff --git a/src/boost/python/connection.py b/src/boost/python/connection.py
index 0245c0b..3f51b5c 100644
--- a/src/boost/python/connection.py
+++ b/src/boost/python/connection.py
@@ -36,6 +36,7 @@ from ._PyTango import Connection, DeviceData, __CallBackAutoDie, CmdArgType, \
DeviceProxy, Database, ExtractAs
from .utils import document_method as __document_method
from .utils import document_static_method as __document_static_method
+from .tango_green import green
def __CallBackAutoDie__cmd_ended_aux(self, fn):
@@ -79,7 +80,7 @@ def __get_command_inout_param(self, cmd_name, cmd_param=None):
def __Connection__command_inout(self, name, *args, **kwds):
"""
- command_inout( self, cmd_name, cmd_param=None) -> any
+ command_inout( self, cmd_name, cmd_param=None, green_mode=None, wait=True, timeout=None) -> any
Execute a command on a device.
@@ -88,9 +89,26 @@ def __Connection__command_inout(self, name, *args, **kwds):
- cmd_param : (any) It should be a value of the type expected by the
command or a DeviceData object with this value inserted.
It can be ommited if the command should not get any argument.
+ - green_mode : (GreenMode) Defaults to the current DeviceProxy GreenMode.
+ (see :meth:`~PyTango.DeviceProxy.get_green_mode` and
+ :meth:`~PyTango.DeviceProxy.set_green_mode`).
+ - wait : (bool) whether or not to wait for result. If green_mode
+ is *Synchronous*, this parameter is ignored as it always
+ waits for the result.
+ Ignored when green_mode is Synchronous (always waits).
+ - timeout : (float) The number of seconds to wait for the result.
+ If None, then there is no limit on the wait time.
+ Ignored when green_mode is Synchronous or wait is False.
Return : The result of the command. The type depends on the command. It may be None.
Throws : ConnectionFailed, CommunicationFailed, DeviceUnlocked, DevFailed from device
+ TimeoutError (green_mode == Futures) If the future didn't finish executing before the given timeout.
+ Timeout (green_mode == Gevent) If the async result didn't finish executing before the given timeout.
+
+ .. versionadded:: 8.1.0
+ *green_mode* parameter.
+ *wait* parameter.
+ *timeout* parameter.
"""
r = Connection.command_inout_raw(self, name, *args, **kwds)
if isinstance(r, DeviceData):
@@ -100,6 +118,7 @@ def __Connection__command_inout(self, name, *args, **kwds):
return None
else:
return r
+__Connection__command_inout.__name__ = "command_inout"
def __Connection__command_inout_raw(self, cmd_name, cmd_param = None):
"""
@@ -198,6 +217,7 @@ def __Connection__command_inout_asynch(self, cmd_name, *args):
return self.__command_inout_asynch_id(cmd_name, argin, forget)
else:
raise TypeError("Wrong number of attributes!")
+__Connection__command_inout_asynch.__name__ = "command_inout_asynch"
def __Connection__command_inout_reply(self, idx, timeout=None):
"""
@@ -244,11 +264,12 @@ def __Connection__command_inout_reply(self, idx, timeout=None):
return None
else:
return r
+__Connection__command_inout_reply.__name__ = "command_inout_reply"
def __init_Connection():
Connection.defaultCommandExtractAs = ExtractAs.Numpy
Connection.command_inout_raw = __Connection__command_inout_raw
- Connection.command_inout = __Connection__command_inout
+ Connection.command_inout = green(__Connection__command_inout)
Connection.command_inout_asynch = __Connection__command_inout_asynch
Connection.command_inout_reply = __Connection__command_inout_reply
diff --git a/src/boost/python/device_proxy.py b/src/boost/python/device_proxy.py
index 677a821..2afad96 100644
--- a/src/boost/python/device_proxy.py
+++ b/src/boost/python/device_proxy.py
@@ -27,21 +27,92 @@ This is an internal PyTango module.
from __future__ import with_statement
-__all__ = ["device_proxy_init"]
+__all__ = ["device_proxy_init", "get_device_proxy"]
__docformat__ = "restructuredtext"
+
+import collections
+import numbers
import threading
from ._PyTango import StdStringVector, DbData, DbDatum, AttributeInfo, \
AttributeInfoEx, AttributeInfoList, AttributeInfoListEx, DeviceProxy, \
__CallBackAutoDie, __CallBackPushEvent, EventType, DevFailed, Except, \
- ExtractAs
+ ExtractAs, GreenMode
+
from .utils import is_pure_str, is_non_str_seq, is_integer, \
seq_2_StdStringVector, StdStringVector_2_seq, seq_2_DbData, DbData_2_dict
+
from .utils import document_method as __document_method
-import collections
-import numbers
+from .utils import get_green_mode
+
+from .tango_green import result, submit, green
+
+
+def get_device_proxy(*args, **kwargs):
+ """get_device_proxy(self, dev_name, green_mode=None, wait=True, timeout=True) -> DeviceProxy
+ get_device_proxy(self, dev_name, need_check_acc, green_mode=None, wait=True, timeout=True) -> DeviceProxy
+
+ Returns a new :class:`~PyTango.DeviceProxy`.
+ There is no difference between using this function and the direct
+ :class:`~PyTango.DeviceProxy` constructor if you use the default kwargs.
+
+ The added value of this function becomes evident when you choose a green_mode
+ to be *Futures* or *Gevent*. The DeviceProxy constructor internally makes some
+ network calls which makes it *slow*. By using one of the *green modes* as
+ green_mode you are allowing other python code to be executed in a cooperative way.
+
+ .. note::
+ The timeout parameter has no relation with the tango device client side
+ timeout (gettable by :meth:`~PyTango.DeviceProxy.get_timeout_millis` and
+ settable through :meth:`~PyTango.DeviceProxy.set_timeout_millis`)
+
+ :param dev_name: the device name or alias
+ :type dev_name: str
+ :param need_check_acc: in first version of the function it defaults to True.
+ Determines if at creation time of DeviceProxy it should check
+ for channel access (rarely used)
+ :type need_check_acc: bool
+ :param green_mode: determines the mode of execution of the device (including
+ the way it is created). Defaults to the current global
+ green_mode (check :func:`~PyTango.utils.get_green_mode` and
+ :func:`~PyTango.utils.set_green_mode`)
+ :type green_mode: :obj:`~PyTango.GreenMode`
+ :param wait: whether or not to wait for result. If green_mode
+ Ignored when green_mode is Synchronous (always waits).
+ :type wait: bool
+ :param timeout: The number of seconds to wait for the result.
+ If None, then there is no limit on the wait time.
+ Ignored when green_mode is Synchronous or wait is False.
+ :type timeout: float
+ :returns:
+ if green_mode is Synchronous or wait is True:
+ :class:`~PyTango.DeviceProxy`
+ else if green_mode is Futures:
+ :class:`concurrent.futures.Future`
+ else if green_mode is Gevent:
+ :class:`gevent.event.AsynchResult`
+ :throws:
+ * a *DevFailed* if green_mode is Synchronous or wait is True
+ and there is an error creating the device.
+ * a *concurrent.futures.TimeoutError* if green_mode is Futures,
+ wait is False, timeout is not None and the time to create the device
+ has expired.
+ * a *gevent.timeout.Timeout* if green_mode is Gevent, wait is False,
+ timeout is not None and the time to create the device has expired.
+
+ New in PyTango 8.1.0
+ """
+ # we cannot use the green wrapper because it consumes the green_mode and we
+ # want to forward it to the DeviceProxy constructor
+ green_mode = kwargs.get('green_mode', get_green_mode())
+ wait = kwargs.pop('wait', True)
+ timeout = kwargs.pop('timeout', None)
+
+ d = submit(green_mode, DeviceProxy, *args, **kwargs)
+ return result(d, green_mode, wait=wait, timeout=timeout)
+
class __TangoInfo(object):
"""Helper class for when DeviceProxy.info() is not available"""
@@ -63,6 +134,44 @@ def __check_read_attribute(dev_attr):
raise DevFailed(*dev_attr.get_err_stack())
return dev_attr
+def __DeviceProxy__init__(self, *args, **kwargs):
+ self.__dict__['_green_mode'] = kwargs.pop('green_mode', get_green_mode())
+ self.__dict__['_executors'] = executors = {}
+ executors[GreenMode.Futures] = kwargs.pop('executor', None)
+ executors[GreenMode.Gevent] = kwargs.pop('threadpool', None)
+ return DeviceProxy.__init_orig__(self, *args, **kwargs)
+
+def __DeviceProxy__get_green_mode(self):
+ """Returns the green mode in use by this DeviceProxy.
+ It returns None if it is using the global PyTango green mode
+ (see :func:`PyTango.utils.get_green_mode`).
+
+ :returns: the green mode in use by this DeviceProxy.
+ :rtype: GreenMode
+
+ .. seealso::
+ :func:`PyTango.utils.get_green_mode`
+ :func:`PyTango.utils.set_green_mode`
+
+ New in PyTango 8.1.0
+ """
+ return self._green_mode
+
+def __DeviceProxy__set_green_mode(self, green_mode=None):
+ """Sets the green mode to be used by this DeviceProxy
+ Setting it to None means use the global PyTango green mode
+ (see :func:`PyTango.utils.get_green_mode`).
+
+ :param green_mode: the new green mode
+ :type green_mode: GreenMode
+
+ New in PyTango 8.1.0
+ """
+ if green_mode is None:
+ green_mode = get_green_mode()
+ self._green_mode = green_mode
+
+
def __DeviceProxy__refresh_cmd_cache(self):
cmd_list = self.command_list_query()
cmd_cache = {}
@@ -154,6 +263,12 @@ def __DeviceProxy__contains(self, key):
def __DeviceProxy__read_attribute(self, value, extract_as=ExtractAs.Numpy):
return __check_read_attribute(self._read_attribute(value, extract_as))
+#def __DeviceProxy__read_attribute(self, value, extract_as=ExtractAs.Numpy,
+# green_mode=None, wait=True, timeout=None):
+# green_mode, submit = submitable(green_mode)
+# result = submit(__DeviceProxy__read_attribute_raw, self, value, extract_as=extract_as)
+# return get_result(result, green_mode, wait=wait, timeout=timeout)
+
def __DeviceProxy__read_attributes_asynch(self, attr_names, cb=None, extract_as=ExtractAs.Numpy):
"""
read_attributes_asynch( self, attr_names) -> int
@@ -859,26 +974,44 @@ def __DeviceProxy__str(self):
info = self._get_info_()
return "%s(%s)" % (info.dev_class, self.dev_name())
+def __DeviceProxy__read_attributes(self, *args, **kwargs):
+ return self._read_attributes(*args, **kwargs)
+
+def __DeviceProxy__write_attribute(self, *args, **kwargs):
+ return self._write_attribute(*args, **kwargs)
+
+def __DeviceProxy__write_attributes(self, *args, **kwargs):
+ return self._write_attributes(*args, **kwargs)
+
def __init_DeviceProxy():
+ DeviceProxy.__init_orig__ = DeviceProxy.__init__
+ DeviceProxy.__init__ = __DeviceProxy__init__
+
+ DeviceProxy.get_green_mode = __DeviceProxy__get_green_mode
+ DeviceProxy.set_green_mode = __DeviceProxy__set_green_mode
+
DeviceProxy.__getattr__ = __DeviceProxy__getattr
DeviceProxy.__setattr__ = __DeviceProxy__setattr
DeviceProxy.__getitem__ = __DeviceProxy__getitem
DeviceProxy.__setitem__ = __DeviceProxy__setitem
DeviceProxy.__contains__ = __DeviceProxy__contains
-
+
DeviceProxy._getAttributeNames = __DeviceProxy__getAttributeNames
DeviceProxy.__refresh_cmd_cache = __DeviceProxy__refresh_cmd_cache
DeviceProxy.__refresh_attr_cache = __DeviceProxy__refresh_attr_cache
- DeviceProxy.read_attribute = __DeviceProxy__read_attribute
+ DeviceProxy.read_attribute = green(__DeviceProxy__read_attribute)
+ DeviceProxy.read_attributes = green(__DeviceProxy__read_attributes)
DeviceProxy.read_attributes_asynch = __DeviceProxy__read_attributes_asynch
DeviceProxy.read_attribute_asynch = __DeviceProxy__read_attribute_asynch
DeviceProxy.read_attribute_reply = __DeviceProxy__read_attribute_reply
DeviceProxy.write_attributes_asynch = __DeviceProxy__write_attributes_asynch
DeviceProxy.write_attribute_asynch = __DeviceProxy__write_attribute_asynch
DeviceProxy.write_attribute_reply = DeviceProxy.write_attributes_reply
- DeviceProxy.write_read_attribute = __DeviceProxy__write_read_attribute
+ DeviceProxy.write_read_attribute = green(__DeviceProxy__write_read_attribute)
+ DeviceProxy.write_attribute = green(__DeviceProxy__write_attribute)
+ DeviceProxy.write_attributes = green(__DeviceProxy__write_attributes)
DeviceProxy.get_property = __DeviceProxy__get_property
DeviceProxy.put_property = __DeviceProxy__put_property
@@ -904,7 +1037,7 @@ def __doc_DeviceProxy():
def document_method(method_name, desc, append=True):
return __document_method(DeviceProxy, method_name, desc, append)
- DeviceProxy.__doc__ = """
+ DeviceProxy.__doc__ = """\
DeviceProxy is the high level Tango object which provides the client with
an easy-to-use interface to TANGO devices. DeviceProxy provides interfaces
to all TANGO Device interfaces.The DeviceProxy manages timeouts, stateless
@@ -913,6 +1046,51 @@ def __doc_DeviceProxy():
Example :
dev = PyTango.DeviceProxy("sys/tg_test/1")
+
+ DeviceProxy(dev_name, green_mode=None, wait=True, timeout=True) -> DeviceProxy
+ DeviceProxy(self, dev_name, need_check_acc, green_mode=None, wait=True, timeout=True) -> DeviceProxy
+
+ Creates a new :class:`~PyTango.DeviceProxy`.
+
+ :param dev_name: the device name or alias
+ :type dev_name: str
+ :param need_check_acc: in first version of the function it defaults to True.
+ Determines if at creation time of DeviceProxy it should check
+ for channel access (rarely used)
+ :type need_check_acc: bool
+ :param green_mode: determines the mode of execution of the device (including.
+ the way it is created). Defaults to the current global
+ green_mode (check :func:`~PyTango.utils.get_green_mode` and
+ :func:`~PyTango.utils.set_green_mode`)
+ :type green_mode: :obj:`~PyTango.GreenMode`
+ :param wait: whether or not to wait for result. If green_mode
+ Ignored when green_mode is Synchronous (always waits).
+ :type wait: bool
+ :param timeout: The number of seconds to wait for the result.
+ If None, then there is no limit on the wait time.
+ Ignored when green_mode is Synchronous or wait is False.
+ :type timeout: float
+ :returns:
+ if green_mode is Synchronous or wait is True:
+ :class:`~PyTango.DeviceProxy`
+ elif green_mode is Futures:
+ :class:`concurrent.futures.Future`
+ elif green_mode is Gevent:
+ :class:`gevent.event.AsynchResult`
+ :throws:
+ * :class:`~PyTango.DevFailed` if green_mode is Synchronous or wait is True
+ and there is an error creating the device.
+ * :class:`concurrent.futures.TimeoutError` if green_mode is Futures,
+ wait is False, timeout is not None and the time to create the device
+ has expired.
+ * :class:`gevent.timeout.Timeout` if green_mode is Gevent, wait is False,
+ timeout is not None and the time to create the device has expired.
+
+ .. versionadded:: 8.1.0
+ *green_mode* parameter.
+ *wait* parameter.
+ *timeout* parameter.
+
"""
#-------------------------------------
@@ -1165,16 +1343,29 @@ def __doc_DeviceProxy():
# set_attribute_config -> in code
document_method("read_attribute", """
- read_attribute(self, attr_name, extract_as=ExtractAs.Numpy) -> DeviceAttribute
+ read_attribute(self, attr_name, extract_as=ExtractAs.Numpy, green_mode=None, wait=True, timeout=None) -> DeviceAttribute
Read a single attribute.
Parameters :
- attr_name : (str) The name of the attribute to read.
- extract_as : (ExtractAs) Defaults to numpy.
+ - green_mode : (GreenMode) Defaults to the current DeviceProxy GreenMode.
+ (see :meth:`~PyTango.DeviceProxy.get_green_mode` and
+ :meth:`~PyTango.DeviceProxy.set_green_mode`).
+ - wait : (bool) whether or not to wait for result. If green_mode
+ is *Synchronous*, this parameter is ignored as it always
+ waits for the result.
+ Ignored when green_mode is Synchronous (always waits).
+ - timeout : (float) The number of seconds to wait for the result.
+ If None, then there is no limit on the wait time.
+ Ignored when green_mode is Synchronous or wait is False.
+
Return : (DeviceAttribute)
Throws : ConnectionFailed, CommunicationFailed, DevFailed from device
+ TimeoutError (green_mode == Futures) If the future didn't finish executing before the given timeout.
+ Timeout (green_mode == Gevent) If the async result didn't finish executing before the given timeout.
.. versionchanged:: 7.1.4
For DevEncoded attributes, before it was returning a DeviceAttribute.value
@@ -1189,50 +1380,107 @@ def __doc_DeviceProxy():
in which case it returns **(format<str>, data<str>)**. Carefull, if
using python >= 3 data<str> is decoded using default python
*utf-8* encoding. This means that PyTango assumes tango DS was written
- encapsulating string into *utf-8* which is the default python enconding.
+ encapsulating string into *utf-8* which is the default python encoding.
+
+ .. versionadded:: 8.1.0
+ *green_mode* parameter.
+ *wait* parameter.
+ *timeout* parameter.
""" )
document_method("read_attributes", """
- read_attributes(self, attr_names, extract_as=ExtractAs.Numpy) -> sequence<DeviceAttribute>
+ read_attributes(self, attr_names, extract_as=ExtractAs.Numpy, green_mode=None, wait=True, timeout=None) -> sequence<DeviceAttribute>
- Read the list of specified attributes.
+ Read the list of specified attributes.
- Parameters :
- - attr_names : (sequence<str>) A list of attributes to read.
- - extract_as : (ExtractAs) Defaults to numpy.
- Return : (sequence<DeviceAttribute>)
+ Parameters :
+ - attr_names : (sequence<str>) A list of attributes to read.
+ - extract_as : (ExtractAs) Defaults to numpy.
+ - green_mode : (GreenMode) Defaults to the current DeviceProxy GreenMode.
+ (see :meth:`~PyTango.DeviceProxy.get_green_mode` and
+ :meth:`~PyTango.DeviceProxy.set_green_mode`).
+ - wait : (bool) whether or not to wait for result. If green_mode
+ is *Synchronous*, this parameter is ignored as it always
+ waits for the result.
+ Ignored when green_mode is Synchronous (always waits).
+ - timeout : (float) The number of seconds to wait for the result.
+ If None, then there is no limit on the wait time.
+ Ignored when green_mode is Synchronous or wait is False.
+
+ Return : (sequence<DeviceAttribute>)
+
+ Throws : ConnectionFailed, CommunicationFailed, DevFailed from device
+ TimeoutError (green_mode == Futures) If the future didn't finish executing before the given timeout.
+ Timeout (green_mode == Gevent) If the async result didn't finish executing before the given timeout.
- Throws : ConnectionFailed, CommunicationFailed, DevFailed from device
+ .. versionadded:: 8.1.0
+ *green_mode* parameter.
+ *wait* parameter.
+ *timeout* parameter.
""" )
document_method("write_attribute", """
- write_attribute(self, attr_name, value) -> None
- write_attribute(self, attr_info, value) -> None
+ write_attribute(self, attr_name, value, green_mode=None, wait=True, timeout=None) -> None
+ write_attribute(self, attr_info, value, green_mode=None, wait=True, timeout=None) -> None
- Write a single attribute.
+ Write a single attribute.
- Parameters :
- - attr_name : (str) The name of the attribute to write.
- - attr_info : (AttributeInfo)
- - value : The value. For non SCALAR attributes it may be any sequence of sequences.
-
- Throws : ConnectionFailed, CommunicationFailed, DeviceUnlocked, DevFailed from device
+ Parameters :
+ - attr_name : (str) The name of the attribute to write.
+ - attr_info : (AttributeInfo)
+ - value : The value. For non SCALAR attributes it may be any sequence of sequences.
+ - green_mode : (GreenMode) Defaults to the current DeviceProxy GreenMode.
+ (see :meth:`~PyTango.DeviceProxy.get_green_mode` and
+ :meth:`~PyTango.DeviceProxy.set_green_mode`).
+ - wait : (bool) whether or not to wait for result. If green_mode
+ is *Synchronous*, this parameter is ignored as it always
+ waits for the result.
+ Ignored when green_mode is Synchronous (always waits).
+ - timeout : (float) The number of seconds to wait for the result.
+ If None, then there is no limit on the wait time.
+ Ignored when green_mode is Synchronous or wait is False.
+
+ Throws : ConnectionFailed, CommunicationFailed, DeviceUnlocked, DevFailed from device
+ TimeoutError (green_mode == Futures) If the future didn't finish executing before the given timeout.
+ Timeout (green_mode == Gevent) If the async result didn't finish executing before the given timeout.
+
+ .. versionadded:: 8.1.0
+ *green_mode* parameter.
+ *wait* parameter.
+ *timeout* parameter.
""" )
document_method("write_attributes", """
- write_attributes(self, name_val) -> None
+ write_attributes(self, name_val, green_mode=None, wait=True, timeout=None) -> None
Write the specified attributes.
Parameters :
- name_val: A list of pairs (attr_name, value). See write_attribute
+ - green_mode : (GreenMode) Defaults to the current DeviceProxy GreenMode.
+ (see :meth:`~PyTango.DeviceProxy.get_green_mode` and
+ :meth:`~PyTango.DeviceProxy.set_green_mode`).
+ - wait : (bool) whether or not to wait for result. If green_mode
+ is *Synchronous*, this parameter is ignored as it always
+ waits for the result.
+ Ignored when green_mode is Synchronous (always waits).
+ - timeout : (float) The number of seconds to wait for the result.
+ If None, then there is no limit on the wait time.
+ Ignored when green_mode is Synchronous or wait is False.
Throws : ConnectionFailed, CommunicationFailed, DeviceUnlocked,
DevFailed or NamedDevFailedList from device
+ TimeoutError (green_mode == Futures) If the future didn't finish executing before the given timeout.
+ Timeout (green_mode == Gevent) If the async result didn't finish executing before the given timeout.
+
+ .. versionadded:: 8.1.0
+ *green_mode* parameter.
+ *wait* parameter.
+ *timeout* parameter.
""" )
document_method("write_read_attribute", """
- write_read_attribute(self, attr_name, value, extract_as=ExtractAs.Numpy) -> DeviceAttribute
+ write_read_attribute(self, attr_name, value, extract_as=ExtractAs.Numpy, green_mode=None, wait=True, timeout=None) -> DeviceAttribute
Write then read a single attribute in a single network call.
By default (serialisation by device), the execution of this call in
@@ -1243,8 +1491,15 @@ def __doc_DeviceProxy():
Throws : ConnectionFailed, CommunicationFailed, DeviceUnlocked,
DevFailed from device, WrongData
+ TimeoutError (green_mode == Futures) If the future didn't finish executing before the given timeout.
+ Timeout (green_mode == Gevent) If the async result didn't finish executing before the given timeout.
New in PyTango 7.0.0
+
+ .. versionadded:: 8.1.0
+ *green_mode* parameter.
+ *wait* parameter.
+ *timeout* parameter.
""" )
#-------------------------------------
diff --git a/src/boost/python/group.py b/src/boost/python/group.py
index c121e9b..265702f 100644
--- a/src/boost/python/group.py
+++ b/src/boost/python/group.py
@@ -177,8 +177,8 @@ def __init_proxy_Group():
for fname in proxy_methods:
proxy_call_define(fname)
- #Group.add.im_func.__doc__ = _RealGroup.add.__doc__
- #Group.get_group.im_func.__doc__ = _RealGroup.get_group.__doc__
+ #Group.add.__func__.__doc__ = _RealGroup.add.__doc__
+ #Group.get_group.__func__.__doc__ = _RealGroup.get_group.__doc__
#Group.__doc__ = _RealGroup.__doc__
diff --git a/src/boost/python/tango_futures.py b/src/boost/python/tango_futures.py
new file mode 100644
index 0000000..7afbfd8
--- /dev/null
+++ b/src/boost/python/tango_futures.py
@@ -0,0 +1,61 @@
+################################################################################
+##
+## This file is part of PyTango, a python binding for Tango
+##
+## http://www.tango-controls.org/static/PyTango/latest/doc/html/index.html
+##
+## Copyright 2011 CELLS / ALBA Synchrotron, Bellaterra, Spain
+##
+## PyTango is free software: you can redistribute it and/or modify
+## it under the terms of the GNU Lesser General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## PyTango is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public License
+## along with PyTango. If not, see <http://www.gnu.org/licenses/>.
+##
+################################################################################
+
+__all__ = ["uses_future", "get_global_executor", "submit", "spawn"]
+
+__use_future = None
+__global_executor = None
+MAX_WORKERS = 8
+MODE = 'thread'
+
+def uses_future():
+ global __use_future
+ if __use_future is None:
+ try:
+ import concurrent.futures
+ __use_future = True
+ except ImportError:
+ __use_future = False
+ return __use_future
+
+def __get_executor_class():
+ import concurrent.futures
+ ret = None
+ if MODE == 'thread':
+ ret = concurrent.futures.ThreadPoolExecutor
+ else:
+ ret = concurrent.futures.ProcessPoolExecutor
+ return ret
+
+def get_global_executor():
+ global __global_executor
+ if __global_executor is None:
+ klass = __get_executor_class()
+ if klass is not None:
+ __global_executor = klass(max_workers=MAX_WORKERS)
+ return __global_executor
+
+def submit(fn, *args, **kwargs):
+ return get_global_executor().submit(fn, *args, **kwargs)
+
+spawn = submit
diff --git a/src/boost/python/tango_gevent.py b/src/boost/python/tango_gevent.py
new file mode 100644
index 0000000..72789f6
--- /dev/null
+++ b/src/boost/python/tango_gevent.py
@@ -0,0 +1,37 @@
+################################################################################
+##
+## This file is part of PyTango, a python binding for Tango
+##
+## http://www.tango-controls.org/static/PyTango/latest/doc/html/index.html
+##
+## Copyright 2011 CELLS / ALBA Synchrotron, Bellaterra, Spain
+##
+## PyTango is free software: you can redistribute it and/or modify
+## it under the terms of the GNU Lesser General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## PyTango is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public License
+## along with PyTango. If not, see <http://www.gnu.org/licenses/>.
+##
+################################################################################
+
+__all__ = ["get_global_threadpool", "get_global_executor", "submit", "spawn"]
+
+__docformat__ = "restructuredtext"
+
+def get_global_threadpool():
+ import gevent
+ return gevent.get_hub().threadpool
+
+get_global_executor = get_global_threadpool
+
+def spawn(fn, *args, **kwargs):
+ return get_global_threadpool().spawn(fn, *args, **kwargs)
+
+submit = spawn
diff --git a/src/boost/python/tango_green.py b/src/boost/python/tango_green.py
new file mode 100644
index 0000000..29e7909
--- /dev/null
+++ b/src/boost/python/tango_green.py
@@ -0,0 +1,140 @@
+################################################################################
+##
+## This file is part of PyTango, a python binding for Tango
+##
+## http://www.tango-controls.org/static/PyTango/latest/doc/html/index.html
+##
+## Copyright 2011 CELLS / ALBA Synchrotron, Bellaterra, Spain
+##
+## PyTango is free software: you can redistribute it and/or modify
+## it under the terms of the GNU Lesser General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## PyTango is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public License
+## along with PyTango. If not, see <http://www.gnu.org/licenses/>.
+##
+################################################################################
+
+__all__ = ["get_executor", "submit", "spawn",
+ "get_synch_executor", "synch_submit",
+ "get_gevent_executor", "gevent_submit",
+ "get_futures_executor", "futures_submit"
+ "result", "submitable", "green"]
+
+__docformat__ = "restructuredtext"
+
+from functools import wraps
+
+from ._PyTango import GreenMode
+from .tango_gevent import get_global_executor as get_gevent_executor
+from .tango_gevent import submit as gevent_submit
+from .tango_futures import get_global_executor as get_futures_executor
+from .tango_futures import submit as futures_submit
+from .utils import get_green_mode
+
+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)
+
+__executor_map = {
+ GreenMode.Synchronous: get_synch_executor,
+ GreenMode.Futures: get_futures_executor,
+ GreenMode.Gevent: get_gevent_executor,
+}
+
+__submit_map = {
+ GreenMode.Synchronous: synch_submit,
+ GreenMode.Futures: futures_submit,
+ GreenMode.Gevent: gevent_submit,
+}
+
+def get_executor(mode):
+ return __executor_map[mode]()
+
+def get_submitter(mode):
+ executor = get_executor(mode)
+ if mode == GreenMode.Gevent:
+ return executor.spawn
+ return executor.submit
+
+def submit(mode, fn, *args, **kwargs):
+ return get_submitter(mode)(fn, *args, **kwargs)
+
+spawn = submit
+
+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
+ if green_mode is None:
+ if hasattr(obj, "_green_mode"):
+ green_mode = obj._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
+
+def green(fn):
+ """make a method green. Can be used as a decorator"""
+
+ @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)
+ timeout = kwargs.pop('timeout', None)
+
+ # get the proper submitable for the given green_mode
+ green_mode, submit = submitable(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
+
diff --git a/src/boost/python/utils.py b/src/boost/python/utils.py
index c47c8e1..6676c57 100644
--- a/src/boost/python/utils.py
+++ b/src/boost/python/utils.py
@@ -28,7 +28,8 @@ This is an internal PyTango module.
from __future__ import with_statement
from __future__ import print_function
-__all__ = [ "is_pure_str", "is_seq", "is_non_str_seq", "is_integer",
+__all__ = [ "get_green_mode", "set_green_mode",
+ "is_pure_str", "is_seq", "is_non_str_seq", "is_integer",
"is_number", "is_scalar_type", "is_array_type", "is_numerical_type",
"is_int_type", "is_float_type", "is_bool_type", "is_bin_type",
"is_str_type", "obj_2_str", "seqStr_2_obj",
@@ -47,10 +48,13 @@ import numbers
import functools
import inspect
import traceback
+import threading
from ._PyTango import StdStringVector, StdDoubleVector, \
DbData, DbDevInfos, DbDevExportInfos, CmdArgType, AttrDataFormat, \
- EventData, AttrConfEventData, DataReadyEventData, DevFailed, constants
+ EventData, AttrConfEventData, DataReadyEventData, DevFailed, constants, \
+ GreenMode
+
_scalar_int_types = (CmdArgType.DevShort, CmdArgType.DevUShort,
CmdArgType.DevInt, CmdArgType.DevLong, CmdArgType.DevULong,
@@ -101,6 +105,31 @@ _scalar_to_array_type = {
CmdArgType.ConstDevString : CmdArgType.DevVarStringArray,
}
+__current_green_mode = GreenMode.Synchronous
+
+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.
+
+ :param green_mode: the new global default PyTango green mode
+ :type green_mode: GreenMode
+ """
+ global __current_green_mode
+ if green_mode is None:
+ green_mode = GreenMode.Synchronous
+ __current_green_mode = green_mode
+
+def get_green_mode():
+ """Returns the current global default PyTango green mode.
+
+ :returns: the current global default PyTango green mode
+ :rtype: GreenMode
+ """
+ return __current_green_mode
+
__device_classes = None
def get_tango_device_classes():
@@ -596,6 +625,12 @@ def document_method(klass, method_name, d, add=True):
func.__doc__ = "%s\n%s" % (d, cpp_doc)
return
func.__doc__ = d
+
+ if func.__name__ != method_name:
+ try:
+ func.__name__ = method_name
+ except AttributeError:
+ pass
def document_static_method(klass, method_name, d, add=True):
meth, func = __get_meth_func(klass, method_name)
--
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