[pytango] 06/483: merge 7.1.4 to trunk

Sandor Bodo-Merle sbodomerle-guest at moszumanska.debian.org
Thu Sep 28 19:14:19 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 4ded7c4fd48b8df5e40a3e6b1ea8d4f173348cd5
Author: tiagocoutinho <tiagocoutinho at 4e9c00fd-8f2e-0410-aa12-93ce3db5e235>
Date:   Mon Apr 11 14:39:49 2011 +0000

    merge 7.1.4 to trunk
    
    git-svn-id: http://svn.code.sf.net/p/tango-cs/code/bindings/PyTango/trunk@16493 4e9c00fd-8f2e-0410-aa12-93ce3db5e235
---
 PyTango/__init__.py                   |   3 +-
 PyTango/attribute_proxy.py            |  31 +-
 PyTango/db.py                         |  16 +-
 PyTango/device_attribute.py           |   6 +-
 PyTango/device_class.py               |  23 +-
 PyTango/device_proxy.py               |  23 +-
 PyTango/device_server.py              | 117 ++---
 PyTango/encoded_attribute.py          | 383 +++++++++++++++
 PyTango/group_element.py              |   4 +-
 PyTango/ipython/ipython_00_10.py      |  10 +-
 PyTango/pytango_init.py               |   2 +
 PyTango/release.py                    |   4 +-
 PyTango/utils.py                      | 178 ++++++-
 doc/_templates/layout.html            |   5 -
 doc/api.rst                           |   2 +
 doc/client/miscellaneous.rst          |   2 +-
 doc/conf.py                           |   1 +
 doc/encoded.rst                       |  12 +
 doc/index.rst                         |  10 +-
 doc/revision.rst                      |  24 +-
 doc/server/index.rst                  | 566 ++++++++++++-----------
 doc/utilities.rst                     |  27 ++
 setup.py                              |  10 +-
 src/api_util.cpp                      |  22 +-
 src/archive_event_info.cpp            |   2 +-
 src/attr_conf_event_data.cpp          |   2 +-
 src/attribute_alarm_info.cpp          |   2 +-
 src/attribute_dimension.cpp           |   2 +-
 src/attribute_event_info.cpp          |   2 +-
 src/attribute_info.cpp                |   2 +-
 src/attribute_info_ex.cpp             |   2 +-
 src/attribute_proxy.cpp               |   2 +-
 src/base_types.cpp                    |   2 +-
 src/callback.cpp                      |   2 +-
 src/change_event_info.cpp             |   2 +-
 src/command_info.cpp                  |   2 +-
 src/connection.cpp                    |   2 +-
 src/constants.cpp                     |   3 +-
 src/data_ready_event_data.cpp         |   2 +-
 src/database.cpp                      |   6 +-
 src/db.cpp                            |   2 +-
 src/dev_command_info.cpp              |   2 +-
 src/dev_error.cpp                     |   2 +-
 src/device_attribute.cpp              | 276 +++++------
 src/device_attribute.h                |  56 ++-
 src/device_attribute_config.cpp       |   2 +-
 src/device_attribute_history.cpp      |   2 +-
 src/device_data.cpp                   |   2 +-
 src/device_data_history.cpp           |   2 +-
 src/device_info.cpp                   |   2 +-
 src/device_proxy.cpp                  |   2 +-
 src/enums.cpp                         |   2 +-
 src/event_data.cpp                    |   2 +-
 src/exception.cpp                     |   2 +-
 src/exception.h                       |   2 +-
 src/fast_from_py.h                    |  29 +-
 src/from_py.h                         |   2 +-
 src/group.cpp                         |   2 +-
 src/group_element.cpp                 |   2 +-
 src/group_reply.cpp                   |   2 +-
 src/group_reply_list.cpp              |   2 +-
 src/locker_info.cpp                   |   2 +-
 src/locking_thread.cpp                |   2 +-
 src/periodic_event_info.cpp           |   2 +-
 src/poll_device.cpp                   |   2 +-
 src/precompiled_header.hpp            |   2 +-
 src/pytango.cpp                       |   4 +-
 src/pytgutils.cpp                     |   2 +-
 src/pytgutils.h                       |   2 +-
 src/server/attr.cpp                   |   7 +-
 src/server/attr.h                     |   2 +-
 src/server/attribute.cpp              | 118 ++---
 src/server/attribute.h                |   9 +-
 src/server/command.cpp                |   2 +-
 src/server/command.h                  |   2 +-
 src/server/device_class.cpp           |  48 +-
 src/server/device_class.h             |  18 +-
 src/server/device_impl.cpp            |  34 +-
 src/server/device_impl.h              |   5 +-
 src/server/dserver.cpp                |   2 +-
 src/server/encoded_attribute.cpp      | 844 ++++++++++++++++++++++++++++++++++
 src/server/log4tango.cpp              |   2 +-
 src/server/subdev.cpp                 |   2 +-
 src/server/tango_util.cpp             | 132 ++----
 src/server/user_default_attr_prop.cpp |   2 +-
 src/server/wattribute.cpp             |   2 +-
 src/tgutils.h                         |   2 +-
 src/time_val.cpp                      |   2 +-
 src/to_py.cpp                         |  36 +-
 src/to_py.h                           |  11 +-
 src/version.cpp                       |   2 +-
 91 files changed, 2308 insertions(+), 909 deletions(-)

diff --git a/PyTango/__init__.py b/PyTango/__init__.py
index e6233c5..271f512 100644
--- a/PyTango/__init__.py
+++ b/PyTango/__init__.py
@@ -67,4 +67,5 @@ from device_class import *
 from globals import *
 from utils import *
 from tango_numpy import *
-from exception import *
\ No newline at end of file
+from exception import *
+from encoded_attribute import *
\ No newline at end of file
diff --git a/PyTango/attribute_proxy.py b/PyTango/attribute_proxy.py
index e871750..df85992 100644
--- a/PyTango/attribute_proxy.py
+++ b/PyTango/attribute_proxy.py
@@ -164,27 +164,32 @@ def __AttributeProxy__delete_property(self, value):
     """
     delete_property(self, value) -> None
     
-            Delete a the given of properties for this attribute.
-            This method accepts the following types as value parameter:
+        Delete a the given of properties for this attribute.
+        This method accepts the following types as value parameter:
+        
             1. string [in] - single property to be deleted
             2. PyTango.DbDatum [in] - single property data to be deleted
             3. PyTango.DbData [in] - several property data to be deleted
             4. sequence<string> [in]- several property data to be deleted
             5. sequence<DbDatum> [in] - several property data to be deleted
-            6. dict<str, obj> [in] - keys are property names to be deleted (values are ignored)
-            7. dict<str, DbDatum> [in] - several DbDatum.name are property names to be
-                                        deleted (keys are ignored)
-
+            6. dict<str, obj> [in] - keys are property names to be deleted
+               (values are ignored)
+            7. dict<str, DbDatum> [in] - several DbDatum.name are property names
+               to be deleted (keys are ignored)
+        
         Parameters :
             - value : can be one of the following:
+
                 1. string [in] - single property data to be deleted
                 2. PyTango.DbDatum [in] - single property data to be deleted
                 3. PyTango.DbData [in] - several property data to be deleted
                 4. sequence<string> [in]- several property data to be deleted
                 5. sequence<DbDatum> [in] - several property data to be deleted
-                6. dict<str, obj> [in] - keys are property names to be deleted (values are ignored)
-                7. dict<str, DbDatum> [in] - several DbDatum.name are property names
-                                            to be deleted (keys are ignored)
+                6. dict<str, obj> [in] - keys are property names to be deleted
+                   (values are ignored)
+                7. dict<str, DbDatum> [in] - several DbDatum.name are property
+                   names to be deleted (keys are ignored)
+        
         Return     : None
 
         Throws     : ConnectionFailed, CommunicationFailed
@@ -311,7 +316,7 @@ def __init_AttributeProxy(doc=True):
     _AttributeProxy.get_property        = __AttributeProxy__get_property
     _AttributeProxy.put_property        = __AttributeProxy__put_property
     _AttributeProxy.delete_property     = __AttributeProxy__delete_property
-
+    
     # General methods
     #AttributeProxy.name                manually defined
     AttributeProxy.status               = _method_device('status', doc=doc)
@@ -319,16 +324,16 @@ def __init_AttributeProxy(doc=True):
     AttributeProxy.ping                 = _method_device('ping', doc=doc)
     AttributeProxy.get_transparency_reconnection=_method_device('get_transparency_reconnection', doc=doc)
     AttributeProxy.set_transparency_reconnection=_method_device('set_transparency_reconnection', doc=doc)
-
+    
     # Property methods
     AttributeProxy.get_property         = _method_attribute('get_property', doc=doc)
     AttributeProxy.put_property         = _method_attribute('put_property', doc=doc)
     AttributeProxy.delete_property      = _method_attribute('delete_property', doc=doc)
-
+    
     # Attribute methods
     AttributeProxy.get_config           = _method_dev_and_name('get_attribute_config', doc=doc)
     AttributeProxy.set_config           = _method_device('set_attribute_config', doc=doc)
-
+    
     AttributeProxy.write                = _method_dev_and_name('write_attribute', doc=doc)
     AttributeProxy.read                 = _method_dev_and_name('read_attribute', doc=doc)
     AttributeProxy.write_read           = _method_dev_and_name('write_read_attribute', doc=doc)
diff --git a/PyTango/db.py b/PyTango/db.py
index f206fdb..5215c37 100644
--- a/PyTango/db.py
+++ b/PyTango/db.py
@@ -941,21 +941,7 @@ def __doc_Database():
         Parameters : None
         Return     : True if multi tango host or False otherwise
 
-        New in PyTango 7.2.0
-    """ )
-
-    document_method("get_file_name", """
-    get_file_name(self) -> str
-
-            Returns the database file name or throws an exception
-            if not using a file database
-
-        Parameters : None
-        Return     : a string containing the database file name
-
-        Throws     : DevFailed
-        
-        New in PyTango 7.2.0
+        New in PyTango 7.1.4
     """ )
     
     document_method("get_info", """
diff --git a/PyTango/device_attribute.py b/PyTango/device_attribute.py
index ef5cb6d..94ad42e 100644
--- a/PyTango/device_attribute.py
+++ b/PyTango/device_attribute.py
@@ -38,8 +38,10 @@ def __DeviceAttribute__get_data(self):
     return self.get_data_raw().extract()
 
 def __DeviceAttribute__init(self, da=None):
-    DeviceAttribute.__init_orig(self)
-    if da is not None:
+    if da is None:
+        DeviceAttribute.__init_orig(self)
+    else:
+        DeviceAttribute.__init_orig(self, da)
         try: self.value = copy.deepcopy(da.value)
         except: pass
         try: self.w_value = copy.deepcopy(da.w_value)
diff --git a/PyTango/device_class.py b/PyTango/device_class.py
index d877f7f..48db955 100644
--- a/PyTango/device_class.py
+++ b/PyTango/device_class.py
@@ -28,6 +28,7 @@ __all__ = [ "DeviceClass" ]
 
 __docformat__ = "restructuredtext"
 
+import sys
 import types
 import operator
 
@@ -293,9 +294,13 @@ class DeviceClass(_DeviceClass):
                 self.prop_util.get_class_properties(self, self.class_property_list)
                 for prop_name in self.class_property_list.keys():
                     setattr(self, prop_name, self.prop_util.get_property_values(prop_name, self.class_property_list))
-        except DevFailed, e:
-            print "----> ", e
-    
+        except DevFailed, df:
+            print("PyDS: %s: A Tango error occured in the constructor:" % name)
+            Except.print_exception(df)
+        except Exception, e:
+            print("PyDS: %s: An error occured in the constructor:" % name)
+            print(str(e))
+            
     def __str__(self):
         return '%s(%s)' % (self.__class__.__name__, self.get_name())
     
@@ -661,7 +666,6 @@ class DeviceClass(_DeviceClass):
             raise RuntimeError("Device class '%s' is not registered" % klass_name)
 
         if klass is None:
-            print get_constructed_classes()
             raise RuntimeError("Device class '%s' as not been constructed" % klass_name)
         
         deviceClassClass, deviceImplClass, deviceImplName = info
@@ -670,10 +674,19 @@ class DeviceClass(_DeviceClass):
         tmp_dev_list = []
         for dev_name in device_list:
             device = deviceImplClass(klass, dev_name)
-            self.cpp_add_device(device)
+            self._add_device(device)
             tmp_dev_list.append(device)
 
         self.dyn_attr(tmp_dev_list)
+#        try:
+#            self.dyn_attr(tmp_dev_list)
+#        except DevFailed, df:
+#            print("PyDS: %s: A Tango error occured trying to create dynamic attributes" % name)
+#            Except.print_exception(df)
+#        except Exception, e:
+#            print("PyDS: %s: An error occured trying to create dynamic attributes" % klass_name)
+#            print(str(e))
+#            sys.exit()
 
         for dev in tmp_dev_list:
             if Util._UseDb and not Util._FileDb:
diff --git a/PyTango/device_proxy.py b/PyTango/device_proxy.py
index 44efe74..a3d0243 100644
--- a/PyTango/device_proxy.py
+++ b/PyTango/device_proxy.py
@@ -381,7 +381,7 @@ def __DeviceProxy__delete_property(self, value):
             5. sequence<DbDatum> [in] - several property data to be deleted
             6. dict<str, obj> [in] - keys are property names to be deleted (values are ignored)
             7. dict<str, DbDatum> [in] - several DbDatum.name are property names to be
-                                        deleted (keys are ignored)
+               deleted (keys are ignored)
 
         Parameters :
             - value : can be one of the following:
@@ -392,7 +392,7 @@ def __DeviceProxy__delete_property(self, value):
                 5. sequence<DbDatum> [in] - several property data to be deleted
                 6. dict<str, obj> [in] - keys are property names to be deleted (values are ignored)
                 7. dict<str, DbDatum> [in] - several DbDatum.name are property names
-                                            to be deleted (keys are ignored)
+                   to be deleted (keys are ignored)
         Return     : None
 
         Throws     : ConnectionFailed, CommunicationFailed
@@ -678,6 +678,7 @@ def __DeviceProxy__subscribe_event ( self, attr_name, event_type, cb_or_queuesiz
             event reception buffer.
             The event reception buffer is implemented as a round robin buffer. This
             way the client can set-up different ways to receive events:
+            
                 * Event reception buffer size = 1 : The client is interested only
                   in the value of the last event received. All other events that
                   have been received since the last reading are discarded.
@@ -959,7 +960,7 @@ def __doc_DeviceProxy():
 
         Parameters : None
         Return     : (int) time elapsed in milliseconds
-        Throw      : exception if device is not alive
+        Throws     : exception if device is not alive
     """ )
 
     document_method("black_box", """
@@ -998,6 +999,7 @@ def __doc_DeviceProxy():
                 print com_info.in_type_desc
                 print com_info.out_type_desc
                 print com_info.disp_level
+                
         See CommandInfo documentation string form more detail
     """ )
 
@@ -1107,8 +1109,15 @@ def __doc_DeviceProxy():
             - attr_name  : (str) The name of the attribute to read.
             - extract_as : (ExtractAs) Defaults to numpy.
         Return     : (DeviceAttribute)
-
+        
         Throws     : ConnectionFailed, CommunicationFailed, DevFailed from device
+            
+    .. versionchanged:: 7.1.4
+        For DevEncoded attributes, before it was returning a DeviceAttribute.value
+        as a tuple **(format<str>, data<str>)** no matter what was the *extract_as*
+        value was. Since 7.1.4, it returns a **(format<str>, data<buffer>)**
+        unless *extract_as* is String, in which case it returns 
+        **(format<str>, data<str>)**.
     """ )
 
     document_method("read_attributes", """
@@ -1212,7 +1221,7 @@ def __doc_DeviceProxy():
 
         Parameters : None
         Return     : (sequence<str>) One string for each polled command/attribute.
-                     Each string is multi-line string with
+                     Each string is multi-line string with:
                         - attribute/command name
                         - attribute/command polling period in milliseconds
                         - attribute/command polling ring buffer
@@ -1392,9 +1401,11 @@ def __doc_DeviceProxy():
             for the time specified in timeout. If after timeout milliseconds,
             the reply is still not there, an exception is thrown. If timeout is
             set to 0, the call waits until the reply arrived.
+            
         Parameters :
             - id      : (int) the asynchronous call identifier.
-            - timeout : (int)
+            - timeout : (int) the timeout
+            
         Return     : None
 
         Throws     : AsynCall, AsynReplyNotArrived, CommunicationFailed, DevFailed from device.
diff --git a/PyTango/device_server.py b/PyTango/device_server.py
index f76f5e6..f374d25 100644
--- a/PyTango/device_server.py
+++ b/PyTango/device_server.py
@@ -148,7 +148,7 @@ class AttributeConfig_3(object):
         self.sys_extensions = []
 
 def __Attribute__get_properties(self, attr_cfg = None):
-    """get_properties(self, attr_cfg = None) -> None
+    """get_properties(self, attr_cfg = None) -> AttributeConfig
 
                 Get attribute properties.
 
@@ -161,7 +161,7 @@ def __Attribute__get_properties(self, attr_cfg = None):
             Return     : (AttributeConfig) the config object filled with
                          attribute configuration information
 
-            New in PyTango 7.2.0
+            New in PyTango 7.1.4
     """
 
     if attr_cfg is None:
@@ -169,7 +169,7 @@ def __Attribute__get_properties(self, attr_cfg = None):
     return self._get_properties(attr_cfg)
 
 def __Attribute__get_properties_2(self, attr_cfg = None):
-    """get_properties_2(self, attr_cfg = None) -> None
+    """get_properties_2(self, attr_cfg = None) -> AttributeConfig_2
 
                 Get attribute properties.
 
@@ -182,7 +182,7 @@ def __Attribute__get_properties_2(self, attr_cfg = None):
             Return     : (AttributeConfig_2) the config object filled with
                          attribute configuration information
 
-            New in PyTango 7.2.0
+            New in PyTango 7.1.4
     """
 
     if attr_cfg is None:
@@ -190,7 +190,7 @@ def __Attribute__get_properties_2(self, attr_cfg = None):
     return self._get_properties_2(attr_cfg)
 
 def __Attribute__get_properties_3(self, attr_cfg = None):
-    """get_properties_3(self, attr_cfg = None) -> None
+    """get_properties_3(self, attr_cfg = None) -> AttributeConfig_3
 
                 Get attribute properties.
 
@@ -203,12 +203,33 @@ def __Attribute__get_properties_3(self, attr_cfg = None):
             Return     : (AttributeConfig_3) the config object filled with
                          attribute configuration information
 
-            New in PyTango 7.2.0
+            New in PyTango 7.1.4
     """
 
     if attr_cfg is None:
-        attr_cfg = AttributeConfig_2()
-    return self._get_properties_2(attr_cfg)
+        attr_cfg = AttributeConfig_3()
+    return self._get_properties_3(attr_cfg)
+
+def __Attribute__set_properties(self, attr_cfg, dev):
+    """set_properties(self, attr_cfg, dev) -> None
+
+                Set attribute properties.
+
+                This method sets the attribute properties value with the content
+                of the fileds in the AttributeConfig/ AttributeConfig_3 object
+
+            Parameters :
+                - conf : (AttributeConfig or AttributeConfig_3) the config 
+                         object.
+                - dev : (DeviceImpl) the device
+
+            New in PyTango 7.1.4
+    """
+    if isinstance(attr_cfg, AttributeConfig_3):
+        self._set_properties_3(attr_cfg, dev)
+    else:
+        self._set_properties(attr_cfg, dev)
+
 
 def __DeviceImpl__get_device_class(self):
     try:
@@ -586,6 +607,7 @@ def __init_Attribute():
     Attribute.get_properties = __Attribute__get_properties
     Attribute.get_properties_2 = __Attribute__get_properties_2
     Attribute.get_properties_3 = __Attribute__get_properties_3
+    Attribute.set_properties = __Attribute__set_properties
     
 def __init_Logger():
     Logger.log = __Logger__log
@@ -1067,39 +1089,6 @@ def __doc_DeviceImpl():
         New in PyTango 7.1.2
     """ )
 
-    document_method("get_min_poll_period", """
-    get_min_poll_period(self) -> int
-
-            Returns the min poll period
-
-        Parameters : None
-        Return     : (int) the min poll period
-        
-        New in PyTango 7.2.0
-    """ )
-
-    document_method("get_cmd_min_poll_period", """
-    get_cmd_min_poll_period(self) -> seq<str>
-
-            Returns the min command poll period
-
-        Parameters : None
-        Return     : (seq<str>) the min command poll period
-        
-        New in PyTango 7.2.0
-    """ )
-
-    document_method("get_attr_min_poll_period", """
-    get_attr_min_poll_period(self) -> seq<str>
-
-            Returns the min attribute poll period
-
-        Parameters : None
-        Return     : (seq<str>) the min attribute poll period
-        
-        New in PyTango 7.2.0
-    """ )
-    
 def __doc_extra_DeviceImpl(cls):
     def document_method(method_name, desc, append=True):
         return __document_method(cls, method_name, desc, append)
@@ -1954,29 +1943,6 @@ def __doc_Attr():
         Return     : (bool) true if a archive event criteria will be checked.
     """ )
 
-    document_method("set_data_ready_event", """
-    set_data_ready_event(self, implemented) -> None
-
-            Set a flag to indicate that the server fires data ready events.
-
-        Parameters :
-            - implemented : (bool) True when the server fires data ready events
-        Return     : None
-        
-        New in PyTango 7.2.0
-    """ )
-
-    document_method("is_data_ready_event", """
-    is_data_ready_event(self) -> bool
-
-            Check if the data ready event is fired for this attribute.
-
-        Parameters : None
-        Return     : (bool) true if firing data ready event is implemented.
-        
-        New in PyTango 7.2.0
-    """ )
-
     document_method("get_name", """
     get_name(self) -> str
 
@@ -2068,29 +2034,6 @@ def __doc_Attr():
         Return     : (bool) if it is assoc
     """ )
 
-    document_method("get_cl_name", """
-    get_cl_name(self) -> str
-
-            Returns the class name
-
-        Parameters : None
-        Return     : (str) the class name
-        
-        New in PyTango 7.2.0
-    """ )
-
-    document_method("set_cl_name", """
-    set_cl_name(self, cl) -> None
-
-            Sets the class name
-
-        Parameters :
-            - cl : (str) new class name
-        Return     : None
-        
-        New in PyTango 7.2.0
-    """ )
-
     document_method("get_class_properties", """
     get_class_properties(self) -> sequence<AttrProperty>
 
diff --git a/PyTango/encoded_attribute.py b/PyTango/encoded_attribute.py
new file mode 100644
index 0000000..38bb94e
--- /dev/null
+++ b/PyTango/encoded_attribute.py
@@ -0,0 +1,383 @@
+#############################################################################
+##
+## This file is part of PyTango, a python binding for Tango
+##
+## http://www.tango-controls.org/static/PyTango/latest/doc/html/index.html
+##
+## (copyleft) CELLS / ALBA Synchrotron, Bellaterra, Spain
+##
+## This 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.
+##
+## This software 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 this program; if not, see <http://www.gnu.org/licenses/>.
+###########################################################################
+
+"""
+This is an internal PyTango module.
+"""
+
+__all__ = []
+
+__docformat__ = "restructuredtext"
+
+import types
+import operator
+
+from _PyTango import Except
+from _PyTango import EncodedAttribute
+from _PyTango import ExtractAs
+from utils import document_method as __document_method
+
+try:
+    import numpy
+except:
+    numpy = None
+
+_allowed_extract = ExtractAs.Numpy, ExtractAs.String, ExtractAs.Tuple, \
+                   ExtractAs.List, ExtractAs.PyTango3
+
+def __EncodedAttribute_encode_gray8(self, gray8, width=0, height=0):
+    """Encode a 8 bit grayscale image (no compression)
+    
+           :param gray8: an object containning image information
+           :type gray8: :py:obj:`str` or :class:`numpy.ndarray` or seq< seq<element> >
+           :param width: image width. **MUST** be given if gray8 is a string or
+                         if it is a :class:`numpy.ndarray` with ndims != 2.
+                         Otherwise it is calculated internally.
+           :param height: image height. **MUST** be given if gray8 is a string
+                          or if it is a :class:`numpy.ndarray` with ndims != 2.
+                          Otherwise it is calculated internally.
+    
+       .. note::
+           When :class:`numpy.ndarray` is given:
+        
+               - gray8 **MUST** be CONTIGUOUS, ALIGNED
+               - if gray8.ndims != 2, width and height **MUST** be given and
+                 gray8.nbytes **MUST** match width*height
+               - if gray8.ndims == 2, gray8.itemsize **MUST** be 1 (typically,
+                 gray8.dtype is one of `numpy.dtype.byte`, `numpy.dtype.ubyte`,
+                 `numpy.dtype.int8` or `numpy.dtype.uint8`)
+    
+       Example::
+           
+           def read_myattr(self, attr):
+               enc = PyTango.EncodedAttribute()
+               data = numpy.arange(100, dtype=numpy.byte)
+               data = numpy.array((data,data,data))
+               enc.encode_gray8(data)
+               attr.set_value(data)
+    """
+    if not operator.isSequenceType(gray8):
+        raise TypeError("Expected sequence (str, numpy.ndarray, list, tuple "
+                        "or bytearray) as first argument")
+    
+    is_str = type(gray8) in types.StringTypes
+    if is_str:
+        if not width or not height:
+            raise ValueError("When giving a string as data, you must also "
+                             "supply width and height")
+    
+    if numpy and isinstance(gray8, numpy.ndarray):
+        if gray8.ndim != 2:
+            if not width or not height:
+                raise ValueError("When giving a non 2D numpy array, width and "
+                                 "height must be supplied")
+            if gray8.nbytes != width*height:
+                raise ValueError("numpy array size mismatch")
+        else:
+            if gray8.itemsize != 1:
+                raise TypeError("Expected numpy array with itemsize == 1")
+        if gray8.flags.c_contiguous != True:
+            raise TypeError("Currently, only contiguous, aligned numpy arrays "
+                            "are supported")
+        if gray8.flags.aligned != True:
+            raise TypeError("Currently, only contiguous, aligned numpy arrays "
+                            "are supported")
+
+    if not is_str and (not width or not height):
+        height = len(gray8)
+        if height < 1:
+            raise IndexError("Expected sequence with at least one row")
+        
+        row0 = gray8[0]
+        if not operator.isSequenceType(row0):
+            raise IndexError("Expected sequence (str, numpy.ndarray, list, tuple or "
+                             "bytearray) inside a sequence")
+        width = len(row0)
+
+    self._encode_gray8(gray8, width, height)
+
+def __EncodedAttribute_encode_gray16(self, gray16, width=0, height=0):
+    """Encode a 16 bit grayscale image (no compression)
+    
+           :param gray16: an object containning image information
+           :type gray16: :py:obj:`str` or :class:`numpy.ndarray` or seq< seq<element> >
+           :param width: image width. **MUST** be given if gray16 is a string or
+                         if it is a :class:`numpy.ndarray` with ndims != 2.
+                         Otherwise it is calculated internally.
+           :param height: image height. **MUST** be given if gray16 is a string
+                          or if it is a :class:`numpy.ndarray` with ndims != 2.
+                          Otherwise it is calculated internally.
+    
+       .. note::
+           When :class:`numpy.ndarray` is given:
+        
+               - gray16 **MUST** be CONTIGUOUS, ALIGNED
+               - if gray16.ndims != 2, width and height **MUST** be given and
+                 gray16.nbytes/2 **MUST** match width*height
+               - if gray16.ndims == 2, gray16.itemsize **MUST** be 2 (typically,
+                 gray8.dtype is one of `numpy.dtype.int16`, `numpy.dtype.uint16`,
+                 `numpy.dtype.short` or `numpy.dtype.ushort`)
+    
+       Example::
+           
+           def read_myattr(self, attr):
+               enc = PyTango.EncodedAttribute()
+               data = numpy.arange(100, dtype=numpy.int16)
+               data = numpy.array((data,data,data))
+               enc.encode_gray16(data)
+               attr.set_value(data)
+    """
+    if not operator.isSequenceType(gray16):
+        raise TypeError("Expected sequence (str, numpy.ndarray, list, tuple "
+                        "or bytearray) as first argument")
+    
+    is_str = type(gray16) in types.StringTypes
+    if is_str:
+        if not width or not height:
+            raise ValueError("When giving a string as data, you must also "
+                             "supply width and height")
+    
+    if numpy and isinstance(gray16, numpy.ndarray):
+        if gray16.ndim != 2:
+            if not width or not height:
+                raise ValueError("When giving a non 2D numpy array, width and "
+                                 "height must be supplied")
+            if gray16.nbytes/2 != width*height:
+                raise ValueError("numpy array size mismatch")
+        else:
+            if gray16.itemsize != 2:
+                raise TypeError("Expected numpy array with itemsize == 2")
+        if gray16.flags.c_contiguous != True:
+            raise TypeError("Currently, only contiguous, aligned numpy arrays "
+                            "are supported")
+        if gray16.flags.aligned != True:
+            raise TypeError("Currently, only contiguous, aligned numpy arrays "
+                            "are supported")
+
+    if not is_str and (not width or not height):
+        height = len(gray16)
+        if height < 1:
+            raise IndexError("Expected sequence with at least one row")
+        
+        row0 = gray16[0]
+        if not operator.isSequenceType(row0):
+            raise IndexError("Expected sequence (str, numpy.ndarray, list, tuple or "
+                             "bytearray) inside a sequence")
+        width = len(row0)
+        if type(row0) in types.StringTypes or type(row0) == bytearray:
+            width /= 2
+
+    self._encode_gray16(gray16, width, height)
+
+def __EncodedAttribute_encode_rgb24(self, rgb24, width=0, height=0):
+    """Encode a 8 bit grayscale image (no compression)
+    
+           :param rgb24: an object containning image information
+           :type rgb24: :py:obj:`str` or :class:`numpy.ndarray` or seq< seq<element> >
+           :param width: image width. **MUST** be given if rgb24 is a string or
+                         if it is a :class:`numpy.ndarray` with ndims != 3.
+                         Otherwise it is calculated internally.
+           :param height: image height. **MUST** be given if rgb24 is a string
+                          or if it is a :class:`numpy.ndarray` with ndims != 3.
+                          Otherwise it is calculated internally.
+    
+       .. note::
+           When :class:`numpy.ndarray` is given:
+        
+               - rgb24 **MUST** be CONTIGUOUS, ALIGNED
+               - if rgb24.ndims != 3, width and height **MUST** be given and
+                 rgb24.nbytes/3 **MUST** match width*height
+               - if rgb24.ndims == 3, rgb24.itemsize **MUST** be 1 (typically,
+                 gray8.dtype is one of `numpy.dtype.byte`, `numpy.dtype.ubyte`,
+                 `numpy.dtype.int8` or `numpy.dtype.uint8`) and shape **MUST** be
+                 (height, width, 3)
+       
+       Example::
+           
+           def read_myattr(self, attr):
+               enc = PyTango.EncodedAttribute()
+               # create an 'image' where each pixel is R=0x01, G=0x01, B=0x01
+               arr = numpy.ones((10,10,3), dtype=numpy.uint8)
+               enc.encode_rgb24(data)
+               attr.set_value(data)
+    """
+    if not operator.isSequenceType(rgb24):
+        raise TypeError("Expected sequence (str, numpy.ndarray, list, tuple "
+                        "or bytearray) as first argument")
+    
+    is_str = type(rgb24) in types.StringTypes
+    if is_str:
+        if not width or not height:
+            raise ValueError("When giving a string as data, you must also "
+                             "supply width and height")
+    
+    if numpy and isinstance(rgb24, numpy.ndarray):
+        if rgb24.ndim != 3:
+            if not width or not height:
+                raise ValueError("When giving a non 2D numpy array, width and "
+                                 "height must be supplied")
+            if rgb24.nbytes/3 != width*height:
+                raise ValueError("numpy array size mismatch")
+        else:
+            if rgb24.itemsize != 1:
+                raise TypeError("Expected numpy array with itemsize == 1")
+        if rgb24.flags.c_contiguous != True:
+            raise TypeError("Currently, only contiguous, aligned numpy arrays "
+                            "are supported")
+        if rgb24.flags.aligned != True:
+            raise TypeError("Currently, only contiguous, aligned numpy arrays "
+                            "are supported")
+    
+    if not is_str and (not width or not height):
+        height = len(rgb24)
+        if height < 1:
+            raise IndexError("Expected sequence with at least one row")
+        
+        row0 = rgb24[0]
+        if not operator.isSequenceType(row0):
+            raise IndexError("Expected sequence (str, numpy.ndarray, list, tuple or "
+                             "bytearray) inside a sequence")
+        width = len(row0)
+        if type(row0) in types.StringTypes or type(row0) == bytearray:
+            width /= 3
+    self._encode_rgb24(rgb24, width, height)
+
+def __EncodedAttribute_decode_gray8(self, da, extract_as=ExtractAs.Numpy):
+    """Decode a 8 bits grayscale image (JPEG_GRAY8 or GRAY8) and returns a 8 bits gray scale image.
+    
+        :param da: :class:`DeviceAttribute` that contains the image
+        :type da: :class:`DeviceAttribute`
+        :param extract_as: defaults to ExtractAs.Numpy
+        :type extract_as: ExtractAs
+        :return: the decoded data
+        
+        - In case String string is choosen as extract method, a tuple is returned:
+            width<int>, height<int>, buffer<str>
+        - In case Numpy is choosen as extract method, a :class:`numpy.ndarray` is
+          returned with ndim=2, shape=(height, width) and dtype=numpy.uint8.
+        - In case Tuple or List are choosen, a tuple<tuple<int>> or list<list<int>>
+          is returned.
+        
+       .. warning::
+           The PyTango calls that return a :class:`DeviceAttribute` 
+           (like :meth:`DeviceProxy.read_attribute` or :meth:`DeviceProxy.command_inout`)
+           automatically extract the contents by default. This method requires 
+           that the given :class:`DeviceAttribute` is obtained from a 
+           call which **DOESN'T** extract the contents. Example::
+               
+               dev = PyTango.DeviceProxy("a/b/c")
+               da = dev.read_attribute("my_attr", extract_as=PyTango.ExtractAs.Nothing)
+               enc = PyTango.EncodedAttribute()
+               data = enc.decode_gray8(da)
+    """
+    if hasattr(da, 'value'):
+        raise TypeError("DeviceAttribute argument must have been obtained from "
+                        "a call which doesn't extract the contents")
+    if extract_as not in _allowed_extract:
+        raise TypeError("extract_as must be one of Numpy, String, Tuple, List, PyTango3")
+    return self._decode_gray8(da, extract_as)
+
+def __EncodedAttribute_decode_gray16(self, da, extract_as=ExtractAs.Numpy):
+    """Decode a 16 bits grayscale image (GRAY16) and returns a 16 bits gray scale image.
+    
+        :param da: :class:`DeviceAttribute` that contains the image
+        :type da: :class:`DeviceAttribute`
+        :param extract_as: defaults to ExtractAs.Numpy
+        :type extract_as: ExtractAs
+        :return: the decoded data
+
+        - In case String string is choosen as extract method, a tuple is returned:
+            width<int>, height<int>, buffer<str>
+        - In case Numpy is choosen as extract method, a :class:`numpy.ndarray` is
+          returned with ndim=2, shape=(height, width) and dtype=numpy.uint16.
+        - In case Tuple or List are choosen, a tuple<tuple<int>> or list<list<int>>
+          is returned.
+
+       .. warning::
+           The PyTango calls that return a :class:`DeviceAttribute` 
+           (like :meth:`DeviceProxy.read_attribute` or :meth:`DeviceProxy.command_inout`)
+           automatically extract the contents by default. This method requires 
+           that the given :class:`DeviceAttribute` is obtained from a 
+           call which **DOESN'T** extract the contents. Example::
+               
+               dev = PyTango.DeviceProxy("a/b/c")
+               da = dev.read_attribute("my_attr", extract_as=PyTango.ExtractAs.Nothing)
+               enc = PyTango.EncodedAttribute()
+               data = enc.decode_gray16(da)
+    """
+    if hasattr(da, 'value'):
+        raise TypeError("DeviceAttribute argument must have been obtained from "
+                        "a call which doesn't extract the contents")
+    if extract_as not in _allowed_extract:
+        raise TypeError("extract_as must be one of Numpy, String, Tuple, List, PyTango3")
+    return self._decode_gray16(da, extract_as)
+
+def __EncodedAttribute_decode_rgb32(self, da, extract_as=ExtractAs.Numpy):
+    """Decode a color image (JPEG_RGB or RGB24) and returns a 32 bits RGB image.
+    
+        :param da: :class:`DeviceAttribute` that contains the image
+        :type da: :class:`DeviceAttribute`
+        :param extract_as: defaults to ExtractAs.Numpy
+        :type extract_as: ExtractAs
+        :return: the decoded data
+
+        - In case String string is choosen as extract method, a tuple is returned:
+            width<int>, height<int>, buffer<str>
+        - In case Numpy is choosen as extract method, a :class:`numpy.ndarray` is
+          returned with ndim=2, shape=(height, width) and dtype=numpy.uint32.
+        - In case Tuple or List are choosen, a tuple<tuple<int>> or list<list<int>>
+          is returned.
+        
+       .. warning::
+           The PyTango calls that return a :class:`DeviceAttribute` 
+           (like :meth:`DeviceProxy.read_attribute` or :meth:`DeviceProxy.command_inout`)
+           automatically extract the contents by default. This method requires 
+           that the given :class:`DeviceAttribute` is obtained from a 
+           call which **DOESN'T** extract the contents. Example::
+               
+               dev = PyTango.DeviceProxy("a/b/c")
+               da = dev.read_attribute("my_attr", extract_as=PyTango.ExtractAs.Nothing)
+               enc = PyTango.EncodedAttribute()
+               data = enc.decode_rgb32(da)
+    """
+    if hasattr(da, 'value'):
+        raise TypeError("DeviceAttribute argument must have been obtained from "
+                        "a call which doesn't extract the contents")
+    if extract_as not in _allowed_extract:
+        raise TypeError("extract_as must be one of Numpy, String, Tuple, List, PyTango3")
+    return self._decode_rgb32(da, extract_as)
+
+def __init_EncodedAttribute():
+    EncodedAttribute.encode_gray8 = __EncodedAttribute_encode_gray8
+    EncodedAttribute.encode_gray16 = __EncodedAttribute_encode_gray16
+    EncodedAttribute.encode_rgb24 = __EncodedAttribute_encode_rgb24
+    EncodedAttribute.decode_gray8 = __EncodedAttribute_decode_gray8
+    EncodedAttribute.decode_gray16 = __EncodedAttribute_decode_gray16
+    EncodedAttribute.decode_rgb32 = __EncodedAttribute_decode_rgb32
+    
+def __doc_EncodedAttribute():
+    pass
+
+def init(doc=True):
+    __init_EncodedAttribute()
+    if doc:
+        __doc_EncodedAttribute()
diff --git a/PyTango/group_element.py b/PyTango/group_element.py
index cd4a6ef..c07b49d 100644
--- a/PyTango/group_element.py
+++ b/PyTango/group_element.py
@@ -153,8 +153,6 @@ def __doc_GroupElement():
         Throws     : TypeError, ArgumentError
     """ )
 
-
-
     document_method("remove", """
     remove(self, patterns, forward=True) -> None
         
@@ -328,7 +326,7 @@ def __doc_GroupElement():
                             only applied to the local set of devices.
                 
         Return     : (bool) This method returns true if all devices in
-        the group are alive, false otherwise.
+                     the group are alive, false otherwise.
         
         Throws     : 
     """ )
diff --git a/PyTango/ipython/ipython_00_10.py b/PyTango/ipython/ipython_00_10.py
index 1ca455c..7e1c25f 100644
--- a/PyTango/ipython/ipython_00_10.py
+++ b/PyTango/ipython/ipython_00_10.py
@@ -901,7 +901,7 @@ def init_console(ip):
     o = ip.options
 
     so = IPython.ipstruct.Struct(
-        spock_banner = """{Blue}hint: Try typing: mydev = Device("{LightBlue}<tab>{Normal}\n""")
+        spock_banner = """%(Blue)shint: Try typing: mydev = Device("%(LightBlue)s<tab>%(Normal)s\n""")
 
     so = ip.user_ns.get("spock_options", so)
     
@@ -909,15 +909,17 @@ def init_console(ip):
     o.prompt_in1 = "Spock <$DB_NAME> [\\#]: "
     o.prompt_out = "Result [\\#]: "
     banner = """
-{LightPurple}Spock {version}{Normal} -- An interactive {Purple}Tango{Normal} client.
+%(Purple)sSpock %(version)s%(Normal)s -- An interactive %(Purple)sTango%(Normal)s client.
 
-Running on top of Python {pyver}, IPython {ipyver} and PyTango {pytangover}
+Running on top of Python %(pyver)s, IPython %(ipyver)s and PyTango %(pytangover)s
 
 help      -> Spock's help system.
 object?   -> Details about 'object'. ?object also works, ?? prints more.
 
 """ + so.spock_banner
-    o.banner = banner.format(**d)
+    o.banner = banner % d
+    if hasattr(o.banner, "format"):
+        o.banner = o.banner.format(**d)
     
 def init_magic(ip):
     __expose_magic(ip, "refreshdb", magic_refreshdb)
diff --git a/PyTango/pytango_init.py b/PyTango/pytango_init.py
index c56d977..9ac87ab 100644
--- a/PyTango/pytango_init.py
+++ b/PyTango/pytango_init.py
@@ -33,6 +33,7 @@ import base_types
 import exception
 import callback
 import api_util
+import encoded_attribute
 import connection
 import db
 import device_attribute
@@ -61,6 +62,7 @@ def __init():
     exception.init(doc=doc)
     callback.init(doc=doc)
     api_util.init(doc=doc)
+    encoded_attribute.init(doc=doc)
     connection.init(doc=doc)
     db.init(doc=doc)
     device_attribute.init(doc=doc)
diff --git a/PyTango/release.py b/PyTango/release.py
index 29cf4bc..751f43c 100644
--- a/PyTango/release.py
+++ b/PyTango/release.py
@@ -46,10 +46,10 @@ class Release:
             - keywords : (seq<str>) list of keywords
             - licence : (str) the licence"""
     name = 'PyTango'
-    version_info = (7, 2, 0, 'dev', 0)
+    version_info = (7, 1, 4, 'final', 0)
     version = '.'.join(map(str, version_info[:3]))
     version_long = version + ''.join(map(str, version_info[3:]))
-    version_description = 'This version implements the C++ Tango 7.2 API.'
+    version_description = 'This version implements the C++ Tango 7.1 API.'
     version_number = int(version.replace('.',''))
     description = 'A python binding for the Tango control system'
     long_description = 'This module implements the Python Tango Device API mapping'
diff --git a/PyTango/utils.py b/PyTango/utils.py
index debd77a..2ff96e9 100644
--- a/PyTango/utils.py
+++ b/PyTango/utils.py
@@ -29,7 +29,7 @@ from __future__ import with_statement
 __all__ = [ "is_scalar_type", "is_array_type", "is_numerical_type", 
             "is_int_type", "is_float_type", "obj_2_str", "seqStr_2_obj",
             "document_method", "document_static_method", "document_enum",
-            "CaselessList", "CaselessDict" ]
+            "CaselessList", "CaselessDict", "EventCallBack", "get_home" ]
 
 __docformat__ = "restructuredtext"
 
@@ -87,18 +87,46 @@ _scalar_to_array_type = {
 }
 
 def is_scalar(tg_type):
+    """Tells if the given tango type is a scalar
+    
+    :param tg_type: tango type
+    :type tg_type: :class:`PyTango.CmdArgType`
+    
+    :return: True if the given tango type is a scalar or False otherwise
+    :rtype: :py:obj:`bool`
+    """
+    
     global _scalar_types
     return tg_type in _scalar_types
 
 is_scalar_type = is_scalar
 
 def is_array(tg_type):
+    """Tells if the given tango type is an array type
+    
+    :param tg_type: tango type
+    :type tg_type: :class:`PyTango.CmdArgType`
+    
+    :return: True if the given tango type is an array type or False otherwise
+    :rtype: :py:obj:`bool`
+    """
     global _array_types
     return tg_type in _array_types
 
 is_array_type = is_array
 
 def is_numerical(tg_type, inc_array=False):
+    """Tells if the given tango type is numerical
+    
+    :param tg_type: tango type
+    :type tg_type: :class:`PyTango.CmdArgType`
+    :param inc_array: (optional, default is False) determines if include array 
+                      in the list of checked types
+    :type inc_array: :py:obj:`bool`
+    
+    :return: True if the given tango type is a numerical or False otherwise
+    :rtype: :py:obj:`bool`
+    """
     global _scalar_numerical_types, _array_numerical_types
     if tg_type in _scalar_numerical_types:
         return True
@@ -109,6 +137,17 @@ def is_numerical(tg_type, inc_array=False):
 is_numerical_type = is_numerical
 
 def is_int(tg_type, inc_array=False):
+    """Tells if the given tango type is integer
+    
+    :param tg_type: tango type
+    :type tg_type: :class:`PyTango.CmdArgType`
+    :param inc_array: (optional, default is False) determines if include array 
+                      in the list of checked types
+    :type inc_array: :py:obj:`bool`
+    
+    :return: True if the given tango type is integer or False otherwise
+    :rtype: :py:obj:`bool`
+    """
     global _scalar_int_types, _array_int_types
     if tg_type in _scalar_int_types:
         return True
@@ -119,6 +158,17 @@ def is_int(tg_type, inc_array=False):
 is_int_type = is_int
 
 def is_float(tg_type, inc_array=False):
+    """Tells if the given tango type is float
+    
+    :param tg_type: tango type
+    :type tg_type: :class:`PyTango.CmdArgType`
+    :param inc_array: (optional, default is False) determines if include array 
+                      in the list of checked types
+    :type inc_array: :py:obj:`bool`
+    
+    :return: True if the given tango type is float or False otherwise
+    :rtype: :py:obj:`bool`
+    """
     global _scalar_float_types, _array_float_types
     if tg_type in _scalar_float_types:
         return True
@@ -129,6 +179,16 @@ def is_float(tg_type, inc_array=False):
 is_float_type = is_float
 
 def seq_2_StdStringVector(seq, vec=None):
+    """Converts a python sequence<str> object to a :class:`PyTango.StdStringVector`
+        
+        :param seq: the sequence of strings
+        :type seq: sequence<:py:obj:`str`>
+        :param vec: (optional, default is None) an :class:`PyTango.StdStringVector`
+                    to be filled. If None is given, a new :class:`PyTango.StdStringVector`
+                    is created
+        :return: a :class:`PyTango.StdStringVector` filled with the same contents as seq
+        :rtype: :class:`PyTango.StdStringVector`
+    """
     if vec is None:
         if isinstance(seq, StdStringVector): return seq
         vec = StdStringVector()
@@ -138,6 +198,15 @@ def seq_2_StdStringVector(seq, vec=None):
     return vec
 
 def StdStringVector_2_seq(vec, seq=None):
+    """Converts a :class:`PyTango.StdStringVector` to a python sequence<str>
+        
+        :param seq: the :class:`PyTango.StdStringVector`
+        :type seq: :class:`PyTango.StdStringVector`
+        :param vec: (optional, default is None) a python sequence to be filled.
+                     If None is given, a new list is created
+        :return: a python sequence filled with the same contents as seq
+        :rtype: sequence<str>
+    """
     if seq is None: seq = []
     if not isinstance(vec, StdStringVector):
         raise TypeError('vec must be a PyTango.StdStringVector')
@@ -145,6 +214,16 @@ def StdStringVector_2_seq(vec, seq=None):
     return seq
 
 def seq_2_StdDoubleVector(seq, vec=None):
+    """Converts a python sequence<float> object to a :class:`PyTango.StdDoubleVector`
+        
+        :param seq: the sequence of floats
+        :type seq: sequence<:py:obj:`float`>
+        :param vec: (optional, default is None) an :class:`PyTango.StdDoubleVector`
+                    to be filled. If None is given, a new :class:`PyTango.StdDoubleVector`
+                    is created
+        :return: a :class:`PyTango.StdDoubleVector` filled with the same contents as seq
+        :rtype: :class:`PyTango.StdDoubleVector`
+    """
     if vec is None:
         if isinstance(seq, StdDoubleVector): return seq
         vec = StdDoubleVector()
@@ -154,6 +233,15 @@ def seq_2_StdDoubleVector(seq, vec=None):
     return vec
 
 def StdDoubleVector_2_seq(vec, seq=None):
+    """Converts a :class:`PyTango.StdDoubleVector` to a python sequence<float>
+        
+        :param seq: the :class:`PyTango.StdDoubleVector`
+        :type seq: :class:`PyTango.StdDoubleVector`
+        :param vec: (optional, default is None) a python sequence to be filled.
+                     If None is given, a new list is created
+        :return: a python sequence filled with the same contents as seq
+        :rtype: sequence<float>
+    """
     if seq is None: seq = []
     if not isinstance(vec, StdDoubleVector):
         raise TypeError('vec must be a PyTango.StdDoubleVector')
@@ -161,6 +249,16 @@ def StdDoubleVector_2_seq(vec, seq=None):
     return seq
 
 def seq_2_DbDevInfos(seq, vec=None):
+    """Converts a python sequence<DbDevInfo> object to a :class:`PyTango.DbDevInfos`
+        
+        :param seq: the sequence of DbDevInfo
+        :type seq: sequence<DbDevInfo>
+        :param vec: (optional, default is None) an :class:`PyTango.DbDevInfos`
+                    to be filled. If None is given, a new :class:`PyTango.DbDevInfos`
+                    is created
+        :return: a :class:`PyTango.DbDevInfos` filled with the same contents as seq
+        :rtype: :class:`PyTango.DbDevInfos`
+    """
     if vec is None:
         if isinstance(seq, DbDevInfos): return seq
         vec = DbDevInfos()
@@ -170,6 +268,16 @@ def seq_2_DbDevInfos(seq, vec=None):
     return vec
 
 def seq_2_DbDevExportInfos(seq, vec=None):
+    """Converts a python sequence<DbDevExportInfo> object to a :class:`PyTango.DbDevExportInfos`
+        
+        :param seq: the sequence of DbDevExportInfo
+        :type seq: sequence<DbDevExportInfo>
+        :param vec: (optional, default is None) an :class:`PyTango.DbDevExportInfos`
+                    to be filled. If None is given, a new :class:`PyTango.DbDevExportInfos`
+                    is created
+        :return: a :class:`PyTango.DbDevExportInfos` filled with the same contents as seq
+        :rtype: :class:`PyTango.DbDevExportInfos`
+    """
     if vec is None:
         if isinstance(seq, DbDevExportInfos): return seq
         vec = DbDevExportInfos()
@@ -179,6 +287,16 @@ def seq_2_DbDevExportInfos(seq, vec=None):
     return vec
 
 def seq_2_DbData(seq, vec=None):
+    """Converts a python sequence<DbDatum> object to a :class:`PyTango.DbData`
+        
+        :param seq: the sequence of DbDatum
+        :type seq: sequence<DbDatum>
+        :param vec: (optional, default is None) an :class:`PyTango.DbData`
+                    to be filled. If None is given, a new :class:`PyTango.DbData`
+                    is created
+        :return: a :class:`PyTango.DbData` filled with the same contents as seq
+        :rtype: :class:`PyTango.DbData`
+    """
     if vec is None:
         if isinstance(seq, DbData): return seq
         vec = DbData()
@@ -196,6 +314,17 @@ def DbData_2_dict(db_data, d=None):
     return d
 
 def seqStr_2_obj(seq, tg_type, tg_format=None):
+    """Translates a sequence<str> to a sequence of objects of give type and format
+    
+        :param seq: the sequence
+        :type seq: sequence<str>
+        :param tg_type: tango type
+        :type tg_type: :class:`PyTango.CmdArgType`
+        :param tg_format: (optional, default is None, meaning SCALAR) tango format
+        :type tg_format: :class:`PyTango.AttrDataFormat`
+        
+        :return: a new sequence
+    """
     if tg_format:
         return _seqStr_2_obj_from_type_format(seq, tg_type, tg_format)
     return _seqStr_2_obj_from_type(seq, tg_type)
@@ -280,15 +409,15 @@ def _seqStr_2_obj_from_type_format(seq, tg_type, tg_format):
     return _seqStr_2_obj_from_type(tg_type, seq)
 
 def obj_2_str(obj, tg_type):
+    """Converts a python object into a string according to the given tango type
+    
+           :param obj: the object to be converted
+           :type obj: :py:obj:`object`
+           :param tg_type: tango type
+           :type tg_type: :class:`PyTango.CmdArgType`
+           :return: a string representation of the given object
+           :rtype: :py:obj:`str`
     """
-        obj_2_str(obj, tg_type) -> str
-
-                Converts a python object into a string according to the given tango type
-
-            Parameters :
-                - obj : (object) the object to be converted
-                - tg_type : (CmdArgType) tango type
-            Return     : (str) a string representation of the given object"""
     ret = ""
     if tg_type in _scalar_types:
         # scalar cases
@@ -650,16 +779,17 @@ def _notifd2db_real_db(ior_string, host=None, out=sys.stdout):
                      "to TANGO database"
 
 
-class evt_cb(object):
+class EventCallBack(object):
     """
     Useful event callback for test purposes
     
     Usage::
     
-        dev = PyTango.DeviceProxy(dev_name)
-        cb = PyTango.utils.evt_cb()
-        id = dev.subscribe_event("state", PyTango.EventType.CHANGE_EVENT, cb, [])
-    
+        >>> dev = PyTango.DeviceProxy(dev_name)
+        >>> cb = PyTango.utils.EventCallBack()
+        >>> id = dev.subscribe_event("state", PyTango.EventType.CHANGE_EVENT, cb, [])
+        2011-04-06 15:33:18.910474 sys/tg_test/1 STATE CHANGE [ATTR_VALID] ON
+        
     Allowed format keys are:
         
         - date (event timestamp)
@@ -669,7 +799,7 @@ class evt_cb(object):
         - name (attribute name)
         - value (event value)
         
-    New in PyTango 7.2.0
+    New in PyTango 7.1.4
     """
 
     def __init__(self, format="{date} {dev_name} {name} {type} {value}",
@@ -680,13 +810,23 @@ class evt_cb(object):
         self._evts = []
         self._max_buf = max_buf
     
+    def get_events(self):
+        """Returns the list of events received by this callback
+           
+           :return: the list of events received by this callback
+           :rtype: sequence<obj>
+        """
+        return self._evts
+        
     def push_event(self, evt):
+        """Internal usage only"""
         try:
             self._push_event(evt)
         except Exception, e:
             print >>self._fd, "Unexpected error in callback: %s" % str(e)
     
     def _push_event(self, evt):
+        """Internal usage only"""
         self._append(evt)
         d = { "date" : evt.get_date().todatetime(),
               "reception_date" : evt.reception_date.todatetime(),
@@ -697,12 +837,14 @@ class evt_cb(object):
         print >>self._fd, self._msg.format(**d)
 
     def _append(self, evt):
+        """Internal usage only"""
         evts = self._evts
         if len(evts) == self._max_buf:
             evts.pop(0)
         evts.append(evt)
         
     def _get_value(self, evt):
+        """Internal usage only"""
         if evt.err:
             e = evt.errors[0]
             return "[%s] %s" % (e.reason, e.desc)
@@ -720,9 +862,9 @@ def get_home():
     Find user's home directory if possible. Otherwise raise error.
     
     :return: user's home directory
-    :rtype: str
+    :rtype: :py:obj:`str`
     
-    New in PyTango 7.2.0
+    New in PyTango 7.1.4
     """
     path=''
     try:
@@ -756,7 +898,7 @@ def _get_env_var(env_var_name):
     :return: the value for the given environment name
     :rtype: str
     
-    New in PyTango 7.2.0
+    New in PyTango 7.1.4
     """
     
     if env_var_name in os.environ:
diff --git a/doc/_templates/layout.html b/doc/_templates/layout.html
index 30d38e0..0b93d3b 100644
--- a/doc/_templates/layout.html
+++ b/doc/_templates/layout.html
@@ -22,8 +22,3 @@
     <li><a href="{{ pathto('quicktour') }}">quick tour</a>| </li>
     <li><a href="{{ pathto('contents') }}">documentation </a> »</li>
 {% endblock %}
-
-
-{% block relbaritems %}
-    <li>:: <a id="open_terminal" href="">open terminal</a> ::<div id="dialog"/></li>
-{% endblock %}
\ No newline at end of file
diff --git a/doc/api.rst b/doc/api.rst
index e964fa1..dec2d01 100644
--- a/doc/api.rst
+++ b/doc/api.rst
@@ -13,4 +13,6 @@ PyTango API
     client/index
     database
     server/index
+    encoded
+    utilities
     exception
diff --git a/doc/client/miscellaneous.rst b/doc/client/miscellaneous.rst
index 18870a6..55cd8c2 100644
--- a/doc/client/miscellaneous.rst
+++ b/doc/client/miscellaneous.rst
@@ -132,7 +132,7 @@ History classes
 ---------------
 
 .. autoclass:: PyTango.DeviceAttributeHistory
-    :show-inheritance:    
+    :show-inheritance:
     :members:
 
 See :class:`DeviceAttribute`.
diff --git a/doc/conf.py b/doc/conf.py
index a8ea3aa..914799c 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -49,6 +49,7 @@ extensions = ['sphinx.ext.pngmath',
               'sphinx.ext.autodoc',
               'sphinx.ext.doctest',
               'sphinx.ext.graphviz',
+              'sphinx.ext.intersphinx',
               'ipython_console_highlighting',
               'spock_console_highlighting']
 
diff --git a/doc/encoded.rst b/doc/encoded.rst
new file mode 100644
index 0000000..f85b137
--- /dev/null
+++ b/doc/encoded.rst
@@ -0,0 +1,12 @@
+
+.. _encoded:
+
+The Tango Encoded Python API
+============================
+
+*This feature is only possible since PyTango 7.1.4*
+
+.. currentmodule:: PyTango
+
+.. autoclass:: PyTango.EncodedAttribute
+    :members:
\ No newline at end of file
diff --git a/doc/index.rst b/doc/index.rst
index 0bb9bc8..ab3f22a 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -13,19 +13,15 @@ Welcome to PyTango 7.1 documentation!
 
 .. sidebar:: Latest news
 
+    2011-04-08:
+        PyTango 7.1.4 is out!
+
     2010-11-05:
         PyTango 7.1.3 is out!
 
     2010-08-19:
         :ref:`Tango logging <logging>` updated
 
-    2010-08-06:
-        PyTango 7.1.2 is out!
-
-    2010-08-02:
-          Checkout the new PyTango companion: 
-          :ref:`spock` (an IPython_ based tango CLI)
-
 PyTango is a python module that exposes to Python_ the complete Tango_ C++ API.
 This includes both client and server API.
 
diff --git a/doc/revision.rst b/doc/revision.rst
index efedee1..377a6f6 100644
--- a/doc/revision.rst
+++ b/doc/revision.rst
@@ -53,7 +53,7 @@ History of modifications:
 +----------+----------------------------------------------------------------------------------+-----------------------------------------------------+-----------------------+
 | 05/11/10 | `8.7 <http://www.tango-controls.org/static/PyTango/v713/doc/html/index.html>`_   | Update to PyTango 7.1.3                             | T\. Coutinho          |
 +----------+----------------------------------------------------------------------------------+-----------------------------------------------------+-----------------------+
-| ??/01/11 | `8.8 <http://www.tango-controls.org/static/PyTango/v720/doc/html/index.html>`_   | Update to PyTango 7.2.0                             | T\. Coutinho          |
+| 05/04/11 | `8.8 <http://www.tango-controls.org/static/PyTango/v714/doc/html/index.html>`_   | Update to PyTango 7.1.4                             | T\. Coutinho          |
 +----------+----------------------------------------------------------------------------------+-----------------------------------------------------+-----------------------+
 
 .. _version-history:
@@ -64,12 +64,30 @@ Version history
 +------------+-------------------------------------------------------------------------------------+
 | version    | Changes                                                                             |
 +============+=====================================================================================+
-| 7.2.0      | Features:                                                                           |
-|            |     - None so far                                                                   |
+| 7.1.4      | Features:                                                                           |
+|            |     - from sourceforge:                                                             |
+|            |         - 3274309: Generic Callback for events                                      |
 |            |                                                                                     |
 |            | Bug fixes:                                                                          |
 |            |     - from sourceforge:                                                             |
+|            |         - 3011775: Seg Faults due to removed dynamic attributes                     |
+|            |         - 3105169: PyTango 7.1.3 does not compile with Tango 7.2.X                  |
+|            |         - 3107243: spock profile does not work with python 2.5                      |
 |            |         - 3124427: PyTango.WAttribute.set_max_value() changes min value             |
+|            |         - 3170399: Missing documentation about is_<attr>_allowed method             |
+|            |         - 3189082: Missing get_properties() for Attribute class                     |
+|            |         - 3196068: delete_device() not called after server_admin.Kill()             |
+|            |         - 3257286: Binding crashes when reading a WRITE string attribute            |
+|            |         - 3267628: DP.read_attribute(, extract=List/tuple) write value is wrong     |
+|            |         - 3274262: Database.is_multi_tango_host missing                             |
+|            |         - 3274319: EncodedAttribute is missing in PyTango (<= 7.1.3)                |
+|            |         - 3277269: read_attribute(DevEncoded) is not numpy as expected              |
+|            |         - 3278946: DeviceAttribute copy constructor is not working                  |
+|            |                                                                                     |
+|            | Documentation:                                                                      |
+|            |     - Added :ref:`utilities` chapter                                                |
+|            |     - Added :ref:`encoded` chapter                                                  |
+|            |     - Improved :ref:`server` chapter                                                |
 +------------+-------------------------------------------------------------------------------------+
 | 7.1.3      | Features:                                                                           |
 |            |     - tango logging with print statement                                            |
diff --git a/doc/server/index.rst b/doc/server/index.rst
index e4bd210..483bbe0 100644
--- a/doc/server/index.rst
+++ b/doc/server/index.rst
@@ -4,15 +4,18 @@
 .. highlight:: python
    :linenothreshold: 3
    
+.. _server:
+   
 The Tango Device Server Python API
 ==================================
 
-This chapter does not explain what a Tango device or a device server is. 
-This is explained in details in "The Tango control system manual" available at 
+This chapter does not explain what a Tango device or a device server is.
+This is explained in details in "The Tango control system manual" available at
 http://www.tango-controls.org/TangoKernel.
-The device server we will detailed in the following example is a Tango device 
-server with one Tango class called PyDsExp. This class has two commands called 
-IOLong and IOStringArray and two attributes called Long_attr and Short_attr_rw.
+The device server described in the following example is a Tango device server
+with one Tango class called *PyDsExp*. This class has two commands called
+*IOLong* and *IOStringArray* and two attributes called *Long_attr* and
+*Short_attr_rw*.
 
 Importing python modules
 ------------------------
@@ -21,7 +24,7 @@ To write a Python script which is a Tango device server, you need to import
 two modules which are:
 
 1. The :mod:`PyTango` module which is the Python to C++ interface
-2. The Python classical sys module
+2. The Python classical :mod:`sys` module
 
 This could be done with code like (supposing the PYTHONPATH environment variable
 is correctly set)::
@@ -33,8 +36,11 @@ The main part of a Python device server
 ---------------------------------------
 
 The rule of this part of a Tango device server is to:
-    - Create the :class:`Util` object passing it the Python interpreter command line arguments
-    - Add to this object the list of Tango class(es) which have to be hosted by this interpreter
+
+    - Create the :class:`Util` object passing it the Python interpreter command
+      line arguments
+    - Add to this object the list of Tango class(es) which have to be hosted by
+      this interpreter
     - Initialize the device server
     - Run the device server loop
 
@@ -42,7 +48,6 @@ The following is a typical code for this main function::
 
     if __name__ == '__main__':
         util = PyTango.Util(sys.argv)
-        #Deprecated : util.add_TgClass(PyDsExpClass, PyDsExp, 'PyDsExp')
         util.add_class(PyDsExpClass, PyDsExp)
         
         U = PyTango.Util.instance()
@@ -51,7 +56,7 @@ The following is a typical code for this main function::
 
 **Line 2**
     Create the Util object passing it the interpreter command line arguments
-**Line 4**
+**Line 3**
     Add the Tango class *PyDsExp* to the device server. The :meth:`Util.add_class`
     method of the Util class has two arguments which are the Tango class 
     PyDsExpClass instance and the Tango PyDsExp instance.
@@ -67,9 +72,11 @@ The PyDsExpClass class in Python
 --------------------------------
 
 The rule of this class is to :
-- Host and manage data you have only once for the Tango class whatever devices of this class will be created
-- Define Tango class command(s)
-- Define Tango class attribute(s)
+
+    - Host and manage data you have only once for the Tango class whatever
+      devices of this class will be created
+    - Define Tango class command(s)
+    - Define Tango class attribute(s)
 
 In our example, the code of this Python class looks like::
 
@@ -94,15 +101,16 @@ In our example, the code of this Python class looks like::
         
 
 **Line 1** 
-    The PyDsExpClass class has to inherit from the PyTango.PyDeviceClass class
+    The PyDsExpClass class has to inherit from the :class:`DeviceClass` class
     
 **Line 3 to 7**
-    Definition of the cmd_list dictionnary defining commands. The IOLong command 
-    is defined at lines 3 and 4. The IOStringArray command is defined in line 5 and 6
-**Line 10 to 16**
-    Definition of the attr_list dictionnary defining attributes. The Long_attr 
-    attribute is defined at lines 8 to 11 and the Short_attr_rw attribute is 
-    defined at lines 13 to 15
+    Definition of the cmd_list :class:`dict` defining commands. The *IOLong* command 
+    is defined at lines 3 and 4. The *IOStringArray* command is defined in 
+    lines 5 and 6
+**Line 9 to 17**
+    Definition of the attr_list :class:`dict` defining attributes. The *Long_attr*
+    attribute is defined at lines 9 to 12 and the *Short_attr_rw* attribute is 
+    defined at lines 14 to 16
     
 If you have something specific to do in the class constructor like
 initializing some specific data member, you will have to code a class 
@@ -117,19 +125,22 @@ The device type is set at line 3.
 Defining commands
 -----------------
 
-As shown in the previous example, commands have to be defined in a dictionary called *cmd_list* as a data
-member of the xxxClass class of the Tango class. This dictionary has one element per command. The element
-key is the command name. The element value is a Python list which defines the command. The generic form
-of a command definition is:
+As shown in the previous example, commands have to be defined in a :class:`dict`
+called *cmd_list* as a data member of the xxxClass class of the Tango class.
+This :class:`dict` has one element per command. The element key is the command
+name. The element value is a python list which defines the command. The generic
+form of a command definition is:
     
     ``'cmd_name' : [ [in_type, <"In desc">], [out_type, <"Out desc">], <{opt parameters}>]``
 
-The first element of the value list is itself a list with the command input data type (one of the PyTango.ArgType
-pseudo enumeration value) and optionally a string describing this input argument. The second element of the
-value list is also a list with the command output data type (one of the PyTango.ArgType pseudo enumeration
-value) and optionally a string describing it.        These two elements are mandatory.   The third list element is
-optional and allows additional command definition. The authorized element for this dictionary are summarized
-in the following array:
+The first element of the value list is itself a list with the command input
+data type (one of the :class:`PyTango.ArgType` pseudo enumeration value) and
+optionally a string describing this input argument. The second element of the
+value list is also a list with the command output data type (one of the
+:class:`PyTango.ArgType` pseudo enumeration value) and optionaly a string
+describing it. These two elements are mandatory. The third list element is
+optional and allows additional command definition. The authorized element for
+this :class:`dict` are summarized in the following array:
 
     +-------------------+----------------------+------------------------------------------+
     |      key          |        Value         |             Definition                   |
@@ -144,11 +155,12 @@ in the following array:
 Defining attributes
 -------------------
 
-                                                                                         
-As shown in the previous example, attributes have to be defined in a dictionary called **attr_list** as a data
-member of the xxxClass class of the Tango class. This dictionary has one element per attribute. The element
-key is the attribute name. The element value is a Python list which defines the attribute. The generic form of
-an attribute definition is:
+As shown in the previous example, attributes have to be defined in a :class:`dict`
+called **attr_list** as a data
+member of the xxxClass class of the Tango class. This :class:`dict` has one element
+per attribute. The element key is the attribute name. The element value is a
+python :class:`list` which defines the attribute. The generic form of an 
+attribute definition is:
 
     ``'attr_name' : [ [mandatory parameters], <{opt parameters}>]``
 
@@ -156,50 +168,53 @@ For any kind of attributes, the mandatory parameters are:
 
     ``[attr data type, attr data format, attr data R/W type]``
     
-The attribute data type is one of the possible value for attributes of the PyTango.ArgType pseudo enunmeration.
-The attribute data format is one of the possible value of the PyTango.AttrDataFormat pseudo enumeration and
-the attribute R/W type is one of the possible value of the PyTango.AttrWriteType pseudo enumeration. For
-spectrum attribute, you have to add the maximum X size (a number). For image attribute, you have to add
-the maximun X and Y dimension (two numbers). The authorized elements for the dictionnary defining optional
-parameters are summarized in the following array
-
-+-------------------+-----------------------------------+------------------------------------------+
-|       key         |              value                |            definition                    |
-+===================+===================================+==========================================+
-| "display level"   | PyTango.DispLevel enum value      |   The attribute display level            |
-+-------------------+-----------------------------------+------------------------------------------+
-|"polling period"   |          Any number               | The attribute polling period (mS)        |
-+-------------------+-----------------------------------+------------------------------------------+
-|  "memorized"      | True or True_without_hard_applied | Define if and how the att. is memorized  |
-+-------------------+-----------------------------------+------------------------------------------+
-|     "label"       |            A string               |       The attribute label                |
-+-------------------+-----------------------------------+------------------------------------------+
-|  "description"    |            A string               |   The attribute description              |
-+-------------------+-----------------------------------+------------------------------------------+
-|     "unit"        |            A string               |       The attribute unit                 |
-+-------------------+-----------------------------------+------------------------------------------+
-|"standard unit"    |           A number                |  The attribute standard unit             |
-+-------------------+-----------------------------------+------------------------------------------+
-| "display unit"    |            A string               |   The attribute display unit             |
-+-------------------+-----------------------------------+------------------------------------------+
-|    "format"       |            A string               | The attribute display format             |
-+-------------------+-----------------------------------+------------------------------------------+
-|  "max value"      |          A number                 |   The attribute max value                |
-+-------------------+-----------------------------------+------------------------------------------+
-|   "min value"     |           A number                |    The attribute min value               |
-+-------------------+-----------------------------------+------------------------------------------+
-|  "max alarm"      |           A number                |    The attribute max alarm               |
-+-------------------+-----------------------------------+------------------------------------------+
-|  "min alarm"      |           A number                |    The attribute min alarm               |
-+-------------------+-----------------------------------+------------------------------------------+
-| "min warning"     |           A number                |  The attribute min warning               |
-+-------------------+-----------------------------------+------------------------------------------+
-|"max warning"      |           A number                |  The attribute max warning               |
-+-------------------+-----------------------------------+------------------------------------------+
-|  "delta time"     |           A number                | The attribute RDS alarm delta time       |
-+-------------------+-----------------------------------+------------------------------------------+
-|   "delta val"     |           A number                | The attribute RDS alarm delta val        |
-+-------------------+-----------------------------------+------------------------------------------+
+The attribute data type is one of the possible value for attributes of the
+:class:`PyTango.ArgType` pseudo enunmeration. The attribute data format is one
+of the possible value of the :class:`PyTango.AttrDataFormat` pseudo enumeration
+and the attribute R/W type is one of the possible value of the
+:class:`PyTango.AttrWriteType` pseudo enumeration. For spectrum attribute,
+you have to add the maximum X size (a number). For image attribute, you have
+to add the maximun X and Y dimension (two numbers). The authorized elements for
+the :class:`dict` defining optional parameters are summarized in the following
+array:
+
+    +-------------------+-----------------------------------+------------------------------------------+
+    |       key         |              value                |            definition                    |
+    +===================+===================================+==========================================+
+    | "display level"   | PyTango.DispLevel enum value      |   The attribute display level            |
+    +-------------------+-----------------------------------+------------------------------------------+
+    |"polling period"   |          Any number               | The attribute polling period (mS)        |
+    +-------------------+-----------------------------------+------------------------------------------+
+    |  "memorized"      | True or True_without_hard_applied | Define if and how the att. is memorized  |
+    +-------------------+-----------------------------------+------------------------------------------+
+    |     "label"       |            A string               |       The attribute label                |
+    +-------------------+-----------------------------------+------------------------------------------+
+    |  "description"    |            A string               |   The attribute description              |
+    +-------------------+-----------------------------------+------------------------------------------+
+    |     "unit"        |            A string               |       The attribute unit                 |
+    +-------------------+-----------------------------------+------------------------------------------+
+    |"standard unit"    |           A number                |  The attribute standard unit             |
+    +-------------------+-----------------------------------+------------------------------------------+
+    | "display unit"    |            A string               |   The attribute display unit             |
+    +-------------------+-----------------------------------+------------------------------------------+
+    |    "format"       |            A string               | The attribute display format             |
+    +-------------------+-----------------------------------+------------------------------------------+
+    |  "max value"      |          A number                 |   The attribute max value                |
+    +-------------------+-----------------------------------+------------------------------------------+
+    |   "min value"     |           A number                |    The attribute min value               |
+    +-------------------+-----------------------------------+------------------------------------------+
+    |  "max alarm"      |           A number                |    The attribute max alarm               |
+    +-------------------+-----------------------------------+------------------------------------------+
+    |  "min alarm"      |           A number                |    The attribute min alarm               |
+    +-------------------+-----------------------------------+------------------------------------------+
+    | "min warning"     |           A number                |  The attribute min warning               |
+    +-------------------+-----------------------------------+------------------------------------------+
+    |"max warning"      |           A number                |  The attribute max warning               |
+    +-------------------+-----------------------------------+------------------------------------------+
+    |  "delta time"     |           A number                | The attribute RDS alarm delta time       |
+    +-------------------+-----------------------------------+------------------------------------------+
+    |   "delta val"     |           A number                | The attribute RDS alarm delta val        |
+    +-------------------+-----------------------------------+------------------------------------------+
 
 The PyDsExp class in Python
 ---------------------------
@@ -262,66 +277,79 @@ In our example, the code of this class looks like::
         def read_attr_hardware(self, data):
             self.info_stream('In read_attr_hardware')
 
-        #------------------------------------------------------------------
-
         def read_Long_attr(self, the_att):
             self.info_stream("read_Long_attr")
 
             the_att.set_value(self.attr_long)
 
-        #------------------------------------------------------------------
+        def is_Long_attr_allowed(self, req_type):
+            return self.get_state() in (PyTango.DevState.ON,)
 
         def read_Short_attr_rw(self, the_att):
             self.info_stream("read_Short_attr_rw")
 
             the_att.set_value(self.attr_short_rw)
 
-        #------------------------------------------------------------------
-
         def write_Short_attr_rw(self, the_att):
             self.info_stream("write_Short_attr_rw")
 
             self.attr_short_rw = the_att.get_write_value()
 
+        def is_Short_attr_rw_allowed(self, req_type):
+            return self.get_state() in (PyTango.DevState.ON,)
+
 **Line 1**
     The PyDsExp class has to inherit from the PyTango.Device_4Impl
 **Line 3 to 6**
-    PyDsExp class constructor. Note that at line 6, it calls the *init_device()* 
+    PyDsExp class constructor. Note that at line 6, it calls the *init_device()*
     method
 **Line 8 to 12**
-    The init_device() method. It sets the device state (line 9) and initialises 
+    The init_device() method. It sets the device state (line 9) and initialises
     some data members
 **Line 16 to 17**
-    The delete_device() method. This method is not mandatory. You define it 
+    The delete_device() method. This method is not mandatory. You define it
     only if you have to do something specific before the device is destroyed
 **Line 23 to 30**
-    The two methods for the IOLong command. The first method is called 
-    *is_IOLong_allowed()* and it is the command is_allowed method (line 23 to 24). 
-    The second method has the same name than the command name. It is the method 
+    The two methods for the *IOLong* command. The first method is called
+    *is_IOLong_allowed()* and it is the command is_allowed method (line 23 to 24).
+    The second method has the same name than the command name. It is the method
     which executes the command. The command input data type is a Tango long
-    and therefore, this method receives a Python integer.
+    and therefore, this method receives a python integer.
 **Line 34 to 47**
-    The two methods for the IOStringArray command. The first method is its 
-    is_allowed method (Line 34 to 35). The second one is the command 
-    execution method (Line 37 to 47). The command input data type is a String 
-    array. Therefore, the method receives the array in a Python list of Python
+    The two methods for the *IOStringArray* command. The first method is its
+    is_allowed method (Line 34 to 35). The second one is the command
+    execution method (Line 37 to 47). The command input data type is a string
+    array. Therefore, the method receives the array in a python list of python
     strings.
 **Line 53 to 54**
-    The *read_attr_hardware()* method. Its argument is a Python sequence of 
+    The *read_attr_hardware()* method. Its argument is a Python sequence of
     Python integer.
-**Line 58 to 61**
-    The method executed when the Long_attr attribute is read. Note that before
+**Line 56 to 59**
+    The method executed when the *Long_attr* attribute is read. Note that before
     PyTango 7 it sets the attribute value with the PyTango.set_attribute_value
     function. Now the same can be done using the set_value of the attribute
     object
-**Line 65 to 68**
-    The method executed when the Short_attr_rw attribute is read.
-**Line 72 to 75**
-    The method executed when the Short_attr_rw attribute is written. 
-    Note that before PyTango 7 it gets the attribute value with a call to the 
-    Attribute method *get_write_value* with a list as argument. Now the write 
+**Line 61 to 62**
+    The is_allowed method for the *Long_attr* attribute. This is an optional
+    method that is called when the attribute is read or written. Not defining it
+    has the same effect as always returning True. The parameter req_type is of
+    type :class:`AttReqtype` which tells if the method is called due to a read
+    or write request. Since this is a read-only attribute, the method will only
+    be called for read requests, obviously.
+**Line 64 to 67**
+    The method executed when the *Short_attr_rw* attribute is read.
+**Line 69 to 72**
+    The method executed when the Short_attr_rw attribute is written.
+    Note that before PyTango 7 it gets the attribute value with a call to the
+    Attribute method *get_write_value* with a list as argument. Now the write
     value can be obtained as the return value of the *get_write_value* call. And
     in case it is a scalar there is no more the need to extract it from the list.
+**Line 74 to 75**
+    The is_allowed method for the *Short_attr_rw* attribute. This is an optional
+    method that is called when the attribute is read or written. Not defining it
+    has the same effect as always returning True. The parameter req_type is of
+    type :class:`AttReqtype` which tells if the method is called due to a read
+    or write request.
 
 General methods
 ###############
@@ -338,9 +366,9 @@ device server are implemented in Python.
 +----------------------+-------------------------+-------------+-----------+
 | always_executed_hook |        None             |   None      |  No       |
 +----------------------+-------------------------+-------------+-----------+
-|    signal_handler    |   Python integer        |   None      |  No       |
+|    signal_handler    |   :py:obj:`int`         |   None      |  No       |
 +----------------------+-------------------------+-------------+-----------+
-| read_attr_hardware   | Python list of integer  |   None      |  No       |
+| read_attr_hardware   | sequence<:py:obj:`int`> |   None      |  No       |
 +----------------------+-------------------------+-------------+-----------+
 
 Implementing a command
@@ -350,10 +378,11 @@ Commands are defined as described above. Nevertheless, some methods implementing
 them have to be written. These methods names are fixed and depend on command 
 name. They have to be called:
 
-    ``is_<Cmd_name>_allowed`` and ``<Cmd_name>``
+    - ``is_<Cmd_name>_allowed(self)``
+    - ``<Cmd_name>(self, arg)``
 
-For instance, with a command called MyCmd, its is_allowed method has to be 
-called is_MyCmd_allowed and its execution method has to be called simply MyCmd. 
+For instance, with a command called *MyCmd*, its is_allowed method has to be 
+called `is_MyCmd_allowed` and its execution method has to be called simply *MyCmd*.
 The following array gives some more info on these methods.
 
 +-----------------------+-------------------------+--------------------+-----------+
@@ -366,78 +395,79 @@ The following array gives some more info on these methods.
 
 Tango has more data types than Python which is more dynamic. The input and
 output values of the commands are translated according to the array below.
-Not that if PyTango is compiled with numpy support the numpy type will be
-the used for the input arguments. Also, it is recomended to use numpy arrays
-of the appropiate type for output arguments as well, as it is much more efficient.
-
-+-------------------------+-------------------------------------------+
-|   Tango data type       |              Python type                  |
-+=========================+===========================================+
-|          DEV_VOID       |                    No data                |
-+-------------------------+-------------------------------------------+
-|       DEV_BOOLEAN       | bool                                      |
-+-------------------------+-------------------------------------------+
-|         DEV_SHORT       | int                                       |
-+-------------------------+-------------------------------------------+
-|         DEV_LONG        | int                                       |
-+-------------------------+-------------------------------------------+
-|        DEV_LONG64       | long (on a 32 bits computer) or           |
-|                         | int (on a 64 bits computer)               |
-+-------------------------+-------------------------------------------+
-|         DEV_FLOAT       | float                                     |
-+-------------------------+-------------------------------------------+
-|       DEV_DOUBLE        | float                                     |
-+-------------------------+-------------------------------------------+
-|        DEV_USHORT       | int                                       |
-+-------------------------+-------------------------------------------+
-|        DEV_ULONG        | int                                       |
-+-------------------------+-------------------------------------------+
-|        DEV_ULONG64      | long (on a 32 bits computer) or           |
-|                         | int (on a 64 bits computer)               |
-+-------------------------+-------------------------------------------+
-|        DEV_STRING       | str                                       |
-+-------------------------+-------------------------------------------+
-|    DEVVAR_CHARARRAY     | numpy.ndarray(dtype=numpy.uint8) or       |
-|                         | sequence<int>                             |
-+-------------------------+-------------------------------------------+
-|    DEVVAR_SHORTARRAY    | numpy.ndarray(dtype=numpy.int16) or       |
-|                         | sequence<int>                             |
-+-------------------------+-------------------------------------------+
-|    DEVVAR_LONGARRAY     | numpy.ndarray(dtype=numpy.int32) or       |
-|                         | sequence<int>                             |
-+-------------------------+-------------------------------------------+
-|   DEVVAR_LONG64ARRAY    | numpy.ndarray(dtype=numpy.int64) or       |
-|                         | sequence<long> (on a 32 bits computer) or |
-|                         | sequence<int> (on a 64 bits computer)     |
-+-------------------------+-------------------------------------------+
-|    DEVVAR_FLOATARRAY    | numpy.ndarray(dtype=numpy.float32) or     |
-|                         | sequence<float>                           |
-+-------------------------+-------------------------------------------+
-|   DEVVAR_DOUBLEARRAY    | numpy.ndarray(dtype=numpy.float64) or     |
-|                         | sequence<float>                           |
-+-------------------------+-------------------------------------------+
-|   DEVVAR_USHORTARRAY    | numpy.ndarray(dtype=numpy.uint16) or      |
-|                         | sequence<int>                             |
-+-------------------------+-------------------------------------------+
-|   DEVVAR_ULONGARRAY     | numpy.ndarray(dtype=numpy.uint32) or      |
-|                         | sequence<int>                             |
-+-------------------------+-------------------------------------------+
-|  DEVVAR_ULONG64ARRAY    | numpy.ndarray(dtype=numpy.uint64) or      |
-|                         | sequence<long> (on a 32 bits computer) or |
-|                         | sequence<int> (on a 64 bits computer)     |
-+-------------------------+-------------------------------------------+
-|   DEVVAR_STRINGARRAY    | sequence<str>                             |
-+-------------------------+-------------------------------------------+
-|                         | A sequence with two elements:             |
-| DEVVAR_LONGSTRINGARRAY  |  1. numpy.ndarray(dtype=numpy.int32) or   |
-|                         |     sequence<int>                         |
-|                         |  2. sequence<str>                         |
-+-------------------------+-------------------------------------------+
-|                         | A sequence with two elements:             |
-|DEVVAR_DOUBLESTRINGARRAY |  1. numpy.ndarray(dtype=numpy.float64) or |
-|                         |     sequence<float>                       |
-|                         |  2. sequence<str>                         |
-+-------------------------+-------------------------------------------+
+Note that if PyTango is compiled with :py:mod:`numpy` support the numpy type
+will be the used for the input arguments. Also, it is recomended to use numpy
+arrays of the appropiate type for output arguments as well, as it is much more
+efficient.
+
++-------------------------+-------------------------------------------------------------------+
+|   Tango data type       |              Python type                                          |
++=========================+===================================================================+
+|          DEV_VOID       |                    No data                                        |
++-------------------------+-------------------------------------------------------------------+
+|       DEV_BOOLEAN       | :py:obj:`bool`                                                    |
++-------------------------+-------------------------------------------------------------------+
+|         DEV_SHORT       | :py:obj:`int`                                                     |
++-------------------------+-------------------------------------------------------------------+
+|         DEV_LONG        | :py:obj:`int`                                                     |
++-------------------------+-------------------------------------------------------------------+
+|        DEV_LONG64       | :py:obj:`long` (on a 32 bits computer) or                         |
+|                         | :py:obj:`int` (on a 64 bits computer)                             |
++-------------------------+-------------------------------------------------------------------+
+|         DEV_FLOAT       | :py:obj:`float`                                                   |
++-------------------------+-------------------------------------------------------------------+
+|       DEV_DOUBLE        | :py:obj:`float`                                                   |
++-------------------------+-------------------------------------------------------------------+
+|        DEV_USHORT       | :py:obj:`int`                                                     |
++-------------------------+-------------------------------------------------------------------+
+|        DEV_ULONG        | :py:obj:`int`                                                     |
++-------------------------+-------------------------------------------------------------------+
+|        DEV_ULONG64      | :py:obj:`long` (on a 32 bits computer) or                         |
+|                         | :py:obj:`int` (on a 64 bits computer)                             |
++-------------------------+-------------------------------------------------------------------+
+|        DEV_STRING       | :py:obj:`str`                                                     |
++-------------------------+-------------------------------------------------------------------+
+|    DEVVAR_CHARARRAY     | :py:class:`numpy.ndarray` (dtype= :py:obj:`numpy.uint8`) or       |
+|                         | sequence<:py:obj:`int`>                                           |
++-------------------------+-------------------------------------------------------------------+
+|    DEVVAR_SHORTARRAY    | :py:class:`numpy.ndarray` (dtype=:py:obj:`numpy.int16`) or        |
+|                         | sequence<:py:obj:`int`>                                           |
++-------------------------+-------------------------------------------------------------------+
+|    DEVVAR_LONGARRAY     | :py:class:`numpy.ndarray` (dtype= :py:obj:`numpy.int32`) or       |
+|                         | sequence<:py:obj:`int`>                                           |
++-------------------------+-------------------------------------------------------------------+
+|   DEVVAR_LONG64ARRAY    | :py:class:`numpy.ndarray` (dtype= :py:obj:`numpy.int64`) or       |
+|                         | sequence<:py:obj:`long`> (on a 32 bits computer) or               |
+|                         | sequence<:py:obj:`int`> (on a 64 bits computer)                   |
++-------------------------+-------------------------------------------------------------------+
+|    DEVVAR_FLOATARRAY    | :py:class:`numpy.ndarray` (dtype= :py:obj:`numpy.float32`) or     |
+|                         | sequence<:py:obj:`float`>                                         |
++-------------------------+-------------------------------------------------------------------+
+|   DEVVAR_DOUBLEARRAY    | :py:class:`numpy.ndarray` (dtype= :py:obj:`numpy.float64`) or     |
+|                         | sequence<:py:obj:`float`>                                         |
++-------------------------+-------------------------------------------------------------------+
+|   DEVVAR_USHORTARRAY    | :py:class:`numpy.ndarray` (dtype= :py:obj:`numpy.uint16`) or      |
+|                         | sequence<:py:obj:`int`>                                           |
++-------------------------+-------------------------------------------------------------------+
+|   DEVVAR_ULONGARRAY     | numpy.ndarray(dtype= :py:obj:`numpy.uint32`) or                   |
+|                         | sequence<:py:obj:`int`>                                           |
++-------------------------+-------------------------------------------------------------------+
+|  DEVVAR_ULONG64ARRAY    | :py:class:`numpy.ndarray` (dtype= :py:obj:`numpy.uint64`) or      |
+|                         | sequence<:py:obj:`long`> (on a 32 bits computer) or               |
+|                         | sequence<:py:obj:`int`> (on a 64 bits computer)                   |
++-------------------------+-------------------------------------------------------------------+
+|   DEVVAR_STRINGARRAY    | sequence<:py:obj:`str`>                                           |
++-------------------------+-------------------------------------------------------------------+
+|                         | A sequence with two elements:                                     |
+| DEVVAR_LONGSTRINGARRAY  |  1. :py:class:`numpy.ndarray` (dtype= :py:obj:`numpy.int32`) or   |
+|                         |     sequence<:py:obj:`int`>                                       |
+|                         |  2. sequence<:py:obj:`str`>                                       |
++-------------------------+-------------------------------------------------------------------+
+|                         | A sequence with two elements:                                     |
+|DEVVAR_DOUBLESTRINGARRAY |  1. :py:class:`numpy.ndarray` (dtype= :py:obj:`numpy.float64`) or |
+|                         |     sequence<:py:obj:`float`>                                     |
+|                         |  2. sequence<:py:obj:`str`>                                       |
++-------------------------+-------------------------------------------------------------------+
 
 The following code is an example of how you write code executed when a client
 calls a command named IOLong::
@@ -474,76 +504,80 @@ Attributes are defined as described in chapter 5.3.2. Nevertheless, some methods
 implementing them have to be written. These methods names are fixed and depend 
 on attribute name. They have to be called:
 
-    ``is_<Attr_name>_allowed`` and ``read_<Attr_name>`` or/and ``write_<Attr_name>``
-
-For instance, with an attribute called MyAttr, its is_allowed method has to be 
-called is_MyAttr_allowed, its read method has to be called read_MyAttr and 
-its write method has to be called write_MyAttr. The following array gives some 
-more info on these methods.
-
-+-------------+-------------+-------------------------------------------+
-| data format | data type   |  python type                              |
-+=============+=============+===========================================+
-| SCALAR      | DEV_BOOLEAN | bool                                      |
-|             +-------------+-------------------------------------------+
-|             | DEV_UCHAR   | int                                       |
-|             +-------------+-------------------------------------------+
-|             | DEV_SHORT   | int                                       |
-|             +-------------+-------------------------------------------+
-|             | DEV_USHORT  | int                                       |
-|             +-------------+-------------------------------------------+
-|             | DEV_LONG    | int                                       |
-|             +-------------+-------------------------------------------+
-|             | DEV_ULONG   | int                                       |
-|             +-------------+-------------------------------------------+
-|             | DEV_LONG64  | int/long                                  |
-|             +-------------+-------------------------------------------+
-|             | DEV_ULONG64 | int/long                                  |
-|             +-------------+-------------------------------------------+
-|             | DEV_FLOAT   | float                                     |
-|             +-------------+-------------------------------------------+
-|             | DEV_DOUBLE  | float                                     |
-|             +-------------+-------------------------------------------+
-|             | DEV_STRING  | str                                       |
-+-------------+-------------+-------------------------------------------+
-| SPECTRUM    | DEV_BOOLEAN | numpy.ndarray(dtype=numpy.bool) or        |
-| or          |             | sequence<bool>                            |
-| IMAGE       +-------------+-------------------------------------------+
-|             | DEV_UCHAR   | numpy.ndarray(dtype=numpy.uint8) or       |
-|             |             | sequence<int>                             |
-|             +-------------+-------------------------------------------+
-|             | DEV_SHORT   | numpy.ndarray(dtype=numpy.int16) or       |
-|             |             | sequence<int>                             |
-|             +-------------+-------------------------------------------+
-|             | DEV_USHORT  | numpy.ndarray(dtype=numpy.uint16) or      |
-|             |             | sequence<int>                             |
-|             +-------------+-------------------------------------------+
-|             | DEV_LONG    | numpy.ndarray(dtype=numpy.int32) or       |
-|             |             | sequence<int>                             |
-|             +-------------+-------------------------------------------+
-|             | DEV_ULONG   | numpy.ndarray(dtype=numpy.uint32) or      |
-|             |             | sequence<int>                             |
-|             +-------------+-------------------------------------------+
-|             | DEV_LONG64  | numpy.ndarray(dtype=numpy.int64) or       |
-|             |             | sequence<int>                             |
-|             +-------------+-------------------------------------------+
-|             | DEV_ULONG64 | numpy.ndarray(dtype=numpy.uint64) or      |
-|             |             | sequence<int>                             |
-|             +-------------+-------------------------------------------+
-|             | DEV_FLOAT   | numpy.ndarray(dtype=numpy.float32) or     |
-|             |             | sequence<float>                           |
-|             +-------------+-------------------------------------------+
-|             | DEV_DOUBLE  | numpy.ndarray(dtype=numpy.float64) or     |
-|             |             | sequence<float>                           |
-|             +-------------+-------------------------------------------+
-|             | DEV_STRING  | sequence<str>                             |
-+-------------+-------------+-------------------------------------------+
+    - ``is_<Attr_name>_allowed(self, req_type)``
+    - ``read_<Attr_name>(self, attr)``
+    - ``write_<Attr_name>(self, attr)``
+
+For instance, with an attribute called *MyAttr*, its is_allowed method has to be 
+called *is_MyAttr_allowed*, its read method has to be called *read_MyAttr* and 
+its write method has to be called *write_MyAttr*.
+The *attr* parameter is an instance of :class:`Attr`.
+Unlike the commands, the is_allowed method for attributes receives a parameter
+of type :class:`AttReqtype`.
+The following table gives some more info on these methods:
+
+    +-------------+-------------+--------------------------------------------------------------+
+    | data format | data type   |  python type                                                 |
+    +=============+=============+==============================================================+
+    | SCALAR      | DEV_BOOLEAN | :py:obj:`bool`                                               |
+    |             +-------------+--------------------------------------------------------------+
+    |             | DEV_UCHAR   | :py:obj:`int`                                                |
+    |             +-------------+--------------------------------------------------------------+
+    |             | DEV_SHORT   | :py:obj:`int`                                                |
+    |             +-------------+--------------------------------------------------------------+
+    |             | DEV_USHORT  | :py:obj:`int`                                                |
+    |             +-------------+--------------------------------------------------------------+
+    |             | DEV_LONG    | :py:obj:`int`                                                |
+    |             +-------------+--------------------------------------------------------------+
+    |             | DEV_ULONG   | :py:obj:`int`                                                |
+    |             +-------------+--------------------------------------------------------------+
+    |             | DEV_LONG64  | :py:obj:`int`/ :py:obj:`long`                                |
+    |             +-------------+--------------------------------------------------------------+
+    |             | DEV_ULONG64 | :py:obj:`int`/ :py:obj:`long`                                |
+    |             +-------------+--------------------------------------------------------------+
+    |             | DEV_FLOAT   | :py:obj:`float`                                              |
+    |             +-------------+--------------------------------------------------------------+
+    |             | DEV_DOUBLE  | :py:obj:`float`                                              |
+    |             +-------------+--------------------------------------------------------------+
+    |             | DEV_STRING  | :py:obj:`str`                                                |
+    +-------------+-------------+--------------------------------------------------------------+
+    | SPECTRUM    | DEV_BOOLEAN | :py:class:`numpy.ndarray` (dtype= :py:obj:`numpy.bool`)      |
+    | or          |             | or sequence<:py:obj:`bool`>                                  |
+    | IMAGE       +-------------+--------------------------------------------------------------+
+    |             | DEV_UCHAR   | :py:class:`numpy.ndarray` (dtype= :py:obj:`numpy.uint8`)     |
+    |             |             | or sequence<:py:obj:`int`>                                   |
+    |             +-------------+--------------------------------------------------------------+
+    |             | DEV_SHORT   | :py:class:`numpy.ndarray` (dtype= :py:obj:`numpy.int16`)     |
+    |             |             | or sequence<:py:obj:`int`>                                   |
+    |             +-------------+--------------------------------------------------------------+
+    |             | DEV_USHORT  | :py:class:`numpy.ndarray` (dtype= :py:obj:`numpy.uint16`)    |
+    |             |             | or sequence<:py:obj:`int`>                                   |
+    |             +-------------+--------------------------------------------------------------+
+    |             | DEV_LONG    | :py:class:`numpy.ndarray` (dtype= :py:obj:`numpy.int32`)     |
+    |             |             | or sequence<:py:obj:`int`>                                   |
+    |             +-------------+--------------------------------------------------------------+
+    |             | DEV_ULONG   | :py:class:`numpy.ndarray` (dtype= :py:obj:`numpy.uint32`)    |
+    |             |             | or sequence<:py:obj:`int`>                                   |
+    |             +-------------+--------------------------------------------------------------+
+    |             | DEV_LONG64  | :py:class:`numpy.ndarray` (dtype= :py:obj:`numpy.int64`)     |
+    |             |             | or sequence<:py:obj:`int`>                                   |
+    |             +-------------+--------------------------------------------------------------+
+    |             | DEV_ULONG64 | :py:class:`numpy.ndarray` (dtype= :py:obj:`numpy.uint64`)    |
+    |             |             | or sequence<:py:obj:`int`>                                   |
+    |             +-------------+--------------------------------------------------------------+
+    |             | DEV_FLOAT   | :py:class:`numpy.ndarray` (dtype= :py:obj:`numpy.float32`)   |
+    |             |             | or sequence<:py:obj:`float`>                                 |
+    |             +-------------+--------------------------------------------------------------+
+    |             | DEV_DOUBLE  | :py:class:`numpy.ndarray` (dtype= :py:obj:`numpy.float64`)   |
+    |             |             | or sequence<:py:obj:`float`>                                 |
+    |             +-------------+--------------------------------------------------------------+
+    |             | DEV_STRING  | sequence<:py:obj:`str`>                                      |
+    +-------------+-------------+--------------------------------------------------------------+
 
 For SPECTRUM and IMAGES the actual sequence object used depends on the context 
-where the tango data is used, and the availability of ``numpy``.
+where the tango data is used, and the availability of :py:mod:`numpy`.
 
-1. for properties the sequence is always a ``list``
-    Example:
+1. for properties the sequence is always a :py:class:`list`. Example:
     
     >>> import PyTango
     >>> db = PyTango.Database()
@@ -552,11 +586,12 @@ where the tango data is used, and the availability of ``numpy``.
     <type 'list'>
 
 2. for attribute/command values
-    - ``numpy.ndarray`` if PyTango was compiled with numpy support (default) and ``numpy`` is installed.
-    - ``list`` otherwise
+    - :py:class:`numpy.ndarray` if PyTango was compiled with :py:mod:`numpy`
+      support (default) and :py:mod:`numpy` is installed.
+    - :py:class:`list` otherwise
     
-The following code is an example of how you write code executed when a client read an attribute which is
-called Long_attr::
+The following code is an example of how you write code executed when a client
+read an attribute which is called *Long_attr*::
     
     def read_Long_attr(self, the_att):
         self.info_stream("read attribute name Long_attr")
@@ -566,8 +601,8 @@ called Long_attr::
     Method declaration with "the_att" being an instance of the Attribute
     class representing the Long_attr attribute
 **Line 2**
-    write a log message to the tango INFO stream (click :ref:`here <logging>` for
-    more information about PyTango log system).
+    write a log message to the tango INFO stream (click :ref:`here <logging>`
+    for more information about PyTango log system).
 **Line 3**
     Set the attribute value using the method set_value() with the attribute 
     value as parameter.
@@ -768,7 +803,8 @@ tango command called Clone::
             klass = self.get_device_class()
             klass.delete_device(dev_name)
             
-Note that the cb parameter is optional. In the example it is given for demonstration purposes only.
+Note that the cb parameter is optional. In the example it is given for
+demonstration purposes only.
 
 Dynamic attributes
 ##################
@@ -791,9 +827,10 @@ attribute within this method:
 
 There is another point to be noted regarding dynamic attribute within Python 
 device server. The Tango Python device server core checks that for each 
-attribute it exists methods named <attribute_name>_read and/or <attribute_name>_write and/or 
-is_<attribute_name>_allowed. Using dynamic attribute, it is not possible to 
-define these methods because attributes name and number are known only at run-time. 
+attribute it exists methods named <attribute_name>_read and/or
+<attribute_name>_write and/or is_<attribute_name>_allowed. Using dynamic
+attribute, it is not possible to define these methods because attributes name
+and number are known only at run-time.
 To address this issue, the Device_3Impl::add_attribute() method has a diferent
 signature for Python device server which is:
 
@@ -822,8 +859,6 @@ called IRMiror and PLC::
 
     if __name__ == '__main__':
         util = PyTango.Util(sys.argv)
-        # Deprecated: util.add_TgClass(PLCClass, PLC, 'PLC')
-        # Deprecated: util.add_TgClass(IRMirrorClass, IRMirror, 'IRMirror')
         util.add_class(PLCClass, PLC, 'PLC')
         util.add_class(IRMirrorClass, IRMirror, 'IRMirror')
         
@@ -831,8 +866,8 @@ called IRMiror and PLC::
         U.server_init()
         U.server_run()
 
-:Line 8: The Tango class PLC is registered in the device server
-:Line 9: The Tango class IRMirror is registered in the device server
+:Line 6: The Tango class PLC is registered in the device server
+:Line 7: The Tango class IRMirror is registered in the device server
 
 It is also possible to add C++ Tango class in a Python device server as soon as:
     1. The Tango class is in a shared library
@@ -850,9 +885,6 @@ device server than before but with one C++ Tango class called SerialLine::
     
     if __name__ == '__main__':
         py = PyTango.Util(sys.argv)
-        # Deprecated: py.add_Cpp_TgClass('SerialLine', 'SerialLine')
-        # Deprecated: py.add_TgClass(PLCClass, PLC, 'PLC')
-        # Deprecated: py.add_TgClass(IRMirrorClass, IRMirror, 'IRMirror')
         util.add_class('SerialLine', 'SerialLine', language="c++")
         util.add_class(PLCClass, PLC, 'PLC')
         util.add_class(IRMirrorClass, IRMirror, 'IRMirror')
@@ -861,8 +893,8 @@ device server than before but with one C++ Tango class called SerialLine::
         U.server_init()
         U.server_run()
 
-:Line 9: The C++ class is registered in the device server
-:Line 10 and 11: The two Python classes are registered in the device server
+:Line 6: The C++ class is registered in the device server
+:Line 7 and 8: The two Python classes are registered in the device server
 
 Server API
 ----------
diff --git a/doc/utilities.rst b/doc/utilities.rst
new file mode 100644
index 0000000..26152c9
--- /dev/null
+++ b/doc/utilities.rst
@@ -0,0 +1,27 @@
+.. _utilities:
+
+The Utilities API
+=================
+
+.. currentmodule:: PyTango.utils
+
+.. autoclass:: PyTango.utils.EventCallBack
+    :members:
+    :undoc-members:
+
+.. autofunction:: PyTango.utils.is_scalar_type
+    
+.. autofunction:: PyTango.utils.is_array_type
+
+.. autofunction:: PyTango.utils.is_numerical_type
+
+.. autofunction:: PyTango.utils.is_int_type
+
+.. autofunction:: PyTango.utils.is_float_type
+
+.. autofunction:: PyTango.utils.obj_2_str
+
+.. autofunction:: PyTango.utils.seqStr_2_obj
+
+.. autofunction:: PyTango.utils.get_home
+
diff --git a/setup.py b/setup.py
index ac054c6..c1808a2 100644
--- a/setup.py
+++ b/setup.py
@@ -142,6 +142,14 @@ include_dirs = [ os.path.abspath('src') ]
 
 _tango_root_inc = os.path.join(TANGO_ROOT, 'include')
 include_dirs.append(_tango_root_inc)
+
+# $TANGO_ROOT/include/tango exists since tango 7.2.0
+# we changed the PyTango code include statements from:
+# #include <tango.h> to:
+# #include <tango/tango.h>
+# However tango itself complains that it doesn't know his own header files
+# if we don't add the $TANGO_ROOT/include/tango directory to the path. So we do it
+# here
 _tango_root_inc = os.path.join(_tango_root_inc, 'tango')
 if os.path.isdir(_tango_root_inc):
     include_dirs.append(_tango_root_inc)
@@ -252,7 +260,7 @@ else:
     # and then uncommenting this line. Someday maybe this will be
     # automated...
     extra_compile_args += [
-        '-includesrc/precompiled_header.hpp',
+#        '-includesrc/precompiled_header.hpp',
     ]
 
     #if not please_debug:
diff --git a/src/api_util.cpp b/src/api_util.cpp
index 91bce4b..7f6dfc8 100644
--- a/src/api_util.cpp
+++ b/src/api_util.cpp
@@ -23,25 +23,12 @@
 
 #include <boost/python.hpp>
 #include <boost/python/return_value_policy.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 #include "pyutils.h"
 
 using namespace boost::python;
 
-namespace PyApiUtil
-{
-    inline object get_env_var(const char *name)
-    {
-        std::string value;
-        if (Tango::ApiUtil::get_env_var(name, value) == 0)
-        {
-            return str(value);
-        }
-        return object();
-    }
-};
-
 void (Tango::ApiUtil::*get_asynch_replies1)() = &Tango::ApiUtil::get_asynch_replies;
 void (Tango::ApiUtil::*get_asynch_replies2)(long) = &Tango::ApiUtil::get_asynch_replies;
 
@@ -63,12 +50,5 @@ void export_api_util()
         
         .def("set_asynch_cb_sub_model", &Tango::ApiUtil::set_asynch_cb_sub_model)
         .def("get_asynch_cb_sub_model", &Tango::ApiUtil::get_asynch_cb_sub_model)
-        
-        .def("get_env_var", &PyApiUtil::get_env_var)
-        .staticmethod("get_env_var")
-        
-        .def("is_event_consumer_created", &Tango::ApiUtil::is_event_consumer_created)
-        .def("get_user_connect_timeout", &Tango::ApiUtil::get_user_connect_timeout)
-        
     ;
 }
\ No newline at end of file
diff --git a/src/archive_event_info.cpp b/src/archive_event_info.cpp
index 6c75a35..45c99b8 100644
--- a/src/archive_event_info.cpp
+++ b/src/archive_event_info.cpp
@@ -22,7 +22,7 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 using namespace boost::python;
 
diff --git a/src/attr_conf_event_data.cpp b/src/attr_conf_event_data.cpp
index a90b14d..d938c9d 100644
--- a/src/attr_conf_event_data.cpp
+++ b/src/attr_conf_event_data.cpp
@@ -22,7 +22,7 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 using namespace boost::python;
 
diff --git a/src/attribute_alarm_info.cpp b/src/attribute_alarm_info.cpp
index a8873b5..ef5a18e 100644
--- a/src/attribute_alarm_info.cpp
+++ b/src/attribute_alarm_info.cpp
@@ -22,7 +22,7 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 using namespace boost::python;
 
diff --git a/src/attribute_dimension.cpp b/src/attribute_dimension.cpp
index 765acda..d180094 100644
--- a/src/attribute_dimension.cpp
+++ b/src/attribute_dimension.cpp
@@ -22,7 +22,7 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 using namespace boost::python;
 
diff --git a/src/attribute_event_info.cpp b/src/attribute_event_info.cpp
index 5b730b6..d51da67 100644
--- a/src/attribute_event_info.cpp
+++ b/src/attribute_event_info.cpp
@@ -22,7 +22,7 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 using namespace boost::python;
 
diff --git a/src/attribute_info.cpp b/src/attribute_info.cpp
index 2f09b03..5e77cf7 100644
--- a/src/attribute_info.cpp
+++ b/src/attribute_info.cpp
@@ -22,7 +22,7 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 using namespace boost::python;
 
diff --git a/src/attribute_info_ex.cpp b/src/attribute_info_ex.cpp
index f97d41a..e8cf698 100644
--- a/src/attribute_info_ex.cpp
+++ b/src/attribute_info_ex.cpp
@@ -22,7 +22,7 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 using namespace boost::python;
 
diff --git a/src/attribute_proxy.cpp b/src/attribute_proxy.cpp
index bb28532..dc3f3e4 100644
--- a/src/attribute_proxy.cpp
+++ b/src/attribute_proxy.cpp
@@ -23,7 +23,7 @@
 
 #include <boost/python.hpp>
 #include <boost/python/return_value_policy.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 #include <string>
 
 #include "defs.h"
diff --git a/src/base_types.cpp b/src/base_types.cpp
index 0e4a51e..b384de0 100644
--- a/src/base_types.cpp
+++ b/src/base_types.cpp
@@ -23,7 +23,7 @@
 
 #include <boost/python.hpp>
 #include <boost/python/suite/indexing/vector_indexing_suite.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 #include "defs.h"
 #include "pytgutils.h"
diff --git a/src/callback.cpp b/src/callback.cpp
index 12dc2e0..36c3421 100644
--- a/src/callback.cpp
+++ b/src/callback.cpp
@@ -22,7 +22,7 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 #include "pytgutils.h"
 #include "callback.h"
 #include "device_attribute.h"
diff --git a/src/change_event_info.cpp b/src/change_event_info.cpp
index 0b551f0..dbdd364 100644
--- a/src/change_event_info.cpp
+++ b/src/change_event_info.cpp
@@ -22,7 +22,7 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 using namespace boost::python;
 
diff --git a/src/command_info.cpp b/src/command_info.cpp
index e748e42..7a0d64a 100644
--- a/src/command_info.cpp
+++ b/src/command_info.cpp
@@ -22,7 +22,7 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 using namespace boost::python;
 
diff --git a/src/connection.cpp b/src/connection.cpp
index 03c9245..18ae606 100644
--- a/src/connection.cpp
+++ b/src/connection.cpp
@@ -23,7 +23,7 @@
 
 #include <boost/python/copy_const_reference.hpp>
 #include <boost/python/copy_non_const_reference.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 #include "pytgutils.h"
 #include "callback.h"
diff --git a/src/constants.cpp b/src/constants.cpp
index 9ccdc54..638f909 100644
--- a/src/constants.cpp
+++ b/src/constants.cpp
@@ -22,7 +22,7 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 using namespace boost::python;
 
@@ -109,7 +109,6 @@ void export_constants()
 
     consts_scope.attr("CLNT_TIMEOUT_STR") = CLNT_TIMEOUT_STR;
     consts_scope.attr("CLNT_TIMEOUT") = CLNT_TIMEOUT;
-    consts_scope.attr("NARROW_CLNT_TIMEOUT") = NARROW_CLNT_TIMEOUT;
 
     //
     // Connection and call timeout for database device
diff --git a/src/data_ready_event_data.cpp b/src/data_ready_event_data.cpp
index 2378e15..a45cce3 100644
--- a/src/data_ready_event_data.cpp
+++ b/src/data_ready_event_data.cpp
@@ -22,7 +22,7 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 using namespace boost::python;
 
diff --git a/src/database.cpp b/src/database.cpp
index b22aaeb..c45c657 100644
--- a/src/database.cpp
+++ b/src/database.cpp
@@ -23,7 +23,7 @@
 
 #include <boost/python.hpp>
 #include <boost/python/return_value_policy.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 #include <string>
 
 #include "defs.h"
@@ -256,10 +256,6 @@ void export_database()
             return_internal_reference<1>())
         .def("is_multi_tango_host", &Tango::Database::is_multi_tango_host)
         
-        //.def("get_file_name", &PyDatabase::get_file_name)
-        .def("get_file_name", &Tango::Database::get_file_name,
-            return_value_policy<copy_const_reference>())
-        
         //
         // General methods
         //
diff --git a/src/db.cpp b/src/db.cpp
index 547ce8f..ca7589d 100644
--- a/src/db.cpp
+++ b/src/db.cpp
@@ -22,7 +22,7 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 #include "defs.h"
 #include "pytgutils.h"
diff --git a/src/dev_command_info.cpp b/src/dev_command_info.cpp
index 620b2b6..b34735f 100644
--- a/src/dev_command_info.cpp
+++ b/src/dev_command_info.cpp
@@ -22,7 +22,7 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 using namespace boost::python;
 
diff --git a/src/dev_error.cpp b/src/dev_error.cpp
index fa693f7..50946aa 100644
--- a/src/dev_error.cpp
+++ b/src/dev_error.cpp
@@ -22,7 +22,7 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 using namespace boost::python;
 
diff --git a/src/device_attribute.cpp b/src/device_attribute.cpp
index 8985c40..021753a 100644
--- a/src/device_attribute.cpp
+++ b/src/device_attribute.cpp
@@ -22,7 +22,8 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <boost/python/handle.hpp>
+#include <tango.h>
 #include <iostream>
 #include <string>
 #include <memory>
@@ -87,19 +88,84 @@ struct python_tangocpp<Tango::DEV_STRING> {
 namespace PyDeviceAttribute {
 
     template<long tangoTypeConst>
-    static inline void _update_scalar_values(Tango::DeviceAttribute &self, object py_value)
+    static inline void _update_value_as_string(Tango::DeviceAttribute &self, object py_value)
     {
         typedef typename TANGO_const2type(tangoTypeConst) TangoScalarType;
+        typedef typename TANGO_const2arraytype(tangoTypeConst) TangoArrayType;
+
+        // Extract the actual data from Tango::DeviceAttribute (self)
+        TangoArrayType* value_ptr = 0;
+        try {
+            self >> value_ptr;
+        } catch (Tango::DevFailed &e ) {
+            if (strcmp(e.errors[0].reason.in(),"API_EmptyDeviceAttribute") != 0)
+                throw;
+        }
+        std::auto_ptr<TangoArrayType> guard_value_ptr(value_ptr);
+
+        if (value_ptr == 0) {
+            py_value.attr(value_attr_name) = boost::python::str();
+            py_value.attr(w_value_attr_name) = object();
+            return;
+        }
+
+        TangoScalarType* buffer = value_ptr->get_buffer();
+
+        const char *ch_ptr = reinterpret_cast<char *>(buffer);
+        size_t nb_bytes = value_ptr->length() * sizeof(TangoScalarType);
+
+        py_value.attr(value_attr_name) = str(ch_ptr, (size_t)nb_bytes);
+        py_value.attr(w_value_attr_name) = object();
+    }
+
+    template<>
+    inline void _update_value_as_string<Tango::DEV_ENCODED>(Tango::DeviceAttribute &self, object py_value)
+    {
+        Tango::DevVarEncodedArray* value;
+        self >> value;
+        std::auto_ptr<Tango::DevVarEncodedArray> guard(value);
+        
+        Tango::DevEncoded* buffer = value->get_buffer();
+        
+        using namespace boost::python;
+        str encoded_format(buffer[0].encoded_format);
+        str encoded_data((const char*)buffer[0].encoded_data.get_buffer(),
+                          buffer[0].encoded_data.length());
+        
+        py_value.attr(value_attr_name) = make_tuple(encoded_format, encoded_data);
 
         if (self.get_written_dim_x() > 0) {
+            bool is_write_type = self.get_written_dim_x() && (value->length() < 2);
+            if (is_write_type) {
+                object w_encoded_format(encoded_format);
+                object w_encoded_data(encoded_data);
+                py_value.attr(w_value_attr_name) = make_tuple(w_encoded_format, w_encoded_data);
+            } else {
+                str w_encoded_format(buffer[1].encoded_format);
+                str w_encoded_data((const char*)buffer[1].encoded_data.get_buffer(),
+                                   buffer[1].encoded_data.length());
+                py_value.attr(w_value_attr_name) = make_tuple(w_encoded_format, w_encoded_data);
+            }
+        } else {
+            py_value.attr(w_value_attr_name) = object();
+        }
+    }
+    
+    template<long tangoTypeConst>
+    static inline void _update_scalar_values(Tango::DeviceAttribute &self, object py_value)
+    {
+        typedef typename TANGO_const2type(tangoTypeConst) TangoScalarType;
+        
+        if (self.get_written_dim_x() > 0) {
             std::vector<TangoScalarType> val;
-            self >> val;
+            self.extract_read(val);
             // In the following lines, the cast is absolutely necessary because
             // vector<TangoScalarType> may not be a vector<TangoScalarType> at
             // compile time. For example, for vector<DevBoolean>, the compiler
             // may create a std::_Bit_reference type.
             py_value.attr(value_attr_name) = object((TangoScalarType)val[0]);
-            py_value.attr(w_value_attr_name) = object((TangoScalarType)val[1]);
+            self.extract_set(val);
+            py_value.attr(w_value_attr_name) = object((TangoScalarType)val[0]);
         } else {
             TangoScalarType rvalue;
             self >> rvalue;
@@ -113,27 +179,43 @@ namespace PyDeviceAttribute {
     {
         Tango::DevVarEncodedArray* value;
         self >> value;
-        std::auto_ptr<Tango::DevVarEncodedArray> guard(value);
-
+        std::auto_ptr<Tango::DevVarEncodedArray> guard_value(value);
+        
         Tango::DevEncoded* buffer = value->get_buffer();
-
-        /// @todo I am making a copy of encoded_data as string. This
-        /// is far from ideal, but it's what we have now...
+        
         using namespace boost::python;
-        if (self.get_written_dim_x() > 0) {
-            str encoded_format(buffer[0].encoded_format);
-            str w_encoded_format(buffer[1].encoded_format);
+        str r_encoded_format(buffer[0].encoded_format);
+
+        Tango::DevVarCharArray &encReadBuffer = buffer[0].encoded_data;
+        Py_ssize_t size = encReadBuffer.length();
+        CORBA::Octet *rawReadBuffer = encReadBuffer.get_buffer(1);
+        
+        PyObject *readArray = PyBuffer_FromReadWriteMemory(rawReadBuffer, size);
+        
+        object r_encoded_data = object(handle<>(readArray));
+        
+        py_value.attr(value_attr_name) = make_tuple(r_encoded_format, r_encoded_data);
 
-            str encoded_data((const char*)buffer[0].encoded_data.get_buffer(), buffer[0].encoded_data.length());
-            str w_encoded_data((const char*)buffer[1].encoded_data.get_buffer(), buffer[1].encoded_data.length());
-
-            py_value.attr(value_attr_name) = make_tuple(encoded_format, encoded_data);
-            py_value.attr(w_value_attr_name) = make_tuple(w_encoded_format, w_encoded_data);
+        if (self.get_written_dim_x() > 0) {
+            bool is_write_type = self.get_written_dim_x() && (value->length() < 2);
+            if (is_write_type) {
+                object w_encoded_format(r_encoded_format);
+                object w_encoded_data(r_encoded_data);
+                py_value.attr(w_value_attr_name) = make_tuple(w_encoded_format, w_encoded_data);
+            } else {
+                str w_encoded_format(buffer[1].encoded_format);
+                
+                Tango::DevVarCharArray &encWriteBuffer = buffer[1].encoded_data;
+                int size = encWriteBuffer.length();
+                CORBA::Octet *rawWriteBuffer = encWriteBuffer.get_buffer(1);
+                
+                PyObject *writeArray = PyBuffer_FromReadWriteMemory(rawWriteBuffer, size);
+                
+                object w_encoded_data = object(handle<>(writeArray));
+                
+                py_value.attr(w_value_attr_name) = make_tuple(w_encoded_format, w_encoded_data);
+            }
         } else {
-            str encoded_format(buffer[0].encoded_format);
-            str encoded_data((const char*)buffer[0].encoded_data.get_buffer(), buffer[0].encoded_data.length());
-            
-            py_value.attr(value_attr_name) = make_tuple(encoded_format, encoded_data);
             py_value.attr(w_value_attr_name) = object();
         }
     }
@@ -141,16 +223,15 @@ namespace PyDeviceAttribute {
     template<>
     inline void _update_scalar_values<Tango::DEV_STRING>(Tango::DeviceAttribute &self, object py_value)
     {
-        if (self.get_written_dim_x() > 0) { /// @todo not the same as old pytango, 'writable' missing...
+        if (self.get_written_dim_x() > 0) {
             std::vector<std::string> val;
-            self >> val;
-
+            self.extract_read(val);
             py_value.attr(value_attr_name) = object(val[0]);
-            py_value.attr(w_value_attr_name) = object(val[1]);
+            self.extract_set(val);
+            py_value.attr(w_value_attr_name) = object(val[0]);
         } else {
             std::string rvalue;
             self >> rvalue;
-
             py_value.attr(value_attr_name) = object(rvalue);
             py_value.attr(w_value_attr_name) = object();
         }
@@ -180,15 +261,32 @@ namespace PyDeviceAttribute {
         }
 
         TangoScalarType* buffer = value_ptr->get_buffer();
-
+        int total_length = value_ptr->length();
+        
+        // Determine if the attribute is AttrWriteType.WRITE
+        int read_size =0, write_size = 0;
+        if (isImage) {
+            read_size = self.get_dim_x() * self.get_dim_y();
+            write_size = self.get_written_dim_x() * self.get_written_dim_y();
+        } else {
+            read_size = self.get_dim_x();
+            write_size = self.get_written_dim_x();
+        }
+        bool is_write_type = (read_size + write_size) > total_length;
+        
         // Convert to a list of lists
         long offset = 0;
         for(int it=1; it>=0; --it) { // 2 iterations: read part/write part
+            if ((!it) && is_write_type) {
+                py_value.attr(w_value_attr_name) = py_value.attr(value_attr_name);
+                continue;
+            }
             boost::python::list result;
+            
             if (isImage) {
                 const int dim_x = it? self.get_dim_x() : self.get_written_dim_x();
                 const int dim_y = it? self.get_dim_y() : self.get_written_dim_y();
-
+                
                 for (int y=0; y < dim_y; ++y) {
                     boost::python::list row;
                     for (int x=0; x < dim_x; ++x)
@@ -199,7 +297,7 @@ namespace PyDeviceAttribute {
             } else {
                 const int dim_x = it? self.get_dim_x() : self.get_written_dim_x();
                 for (int x=0; x < dim_x; ++x)
-                    result.append(python_tangocpp<tangoTypeConst>::to_python(buffer[x]));
+                    result.append(python_tangocpp<tangoTypeConst>::to_python(buffer[offset + x]));
                 offset += dim_x;
             }
             py_value.attr(it? value_attr_name : w_value_attr_name) = result;
@@ -272,11 +370,27 @@ namespace PyDeviceAttribute {
         }
 
         TangoScalarType* buffer = value_ptr->get_buffer();
-
-        // Convert to a list of lists
+        int total_length = value_ptr->length();
+        
+        // Determine if the attribute is AttrWriteType.WRITE
+        int read_size =0, write_size = 0;
+        if (isImage) {
+            read_size = self.get_dim_x() * self.get_dim_y();
+            write_size = self.get_written_dim_x() * self.get_written_dim_y();
+        } else {
+            read_size = self.get_dim_x();
+            write_size = self.get_written_dim_x();
+        }
+        bool is_write_type = (read_size + write_size) > total_length;
+        
+        // Convert to a tuple of tuples
         long offset = 0;
         for(int it=1; it>=0; --it) { // 2 iterations: read part/write part
-            //boost::python::list result;
+            if ((!it) && is_write_type) {
+                py_value.attr(w_value_attr_name) = py_value.attr(value_attr_name);
+                continue;
+            }
+            
             object result_guard;
             if (isImage) {
                 const int dim_x = it? self.get_dim_x() : self.get_written_dim_x();
@@ -288,7 +402,6 @@ namespace PyDeviceAttribute {
                 result_guard = object(handle<>(result));
 
                 for (int y=0; y < dim_y; ++y) {
-                    //boost::python::list row;
                     PyObject * row = PyTuple_New(dim_x);
                     if (!row)
                         boost::python::throw_error_already_set();
@@ -311,7 +424,7 @@ namespace PyDeviceAttribute {
                 result_guard = object(handle<>(result));
 
                 for (int x=0; x < dim_x; ++x) {
-                    object el = python_tangocpp<tangoTypeConst>::to_python(buffer[x]);
+                    object el = python_tangocpp<tangoTypeConst>::to_python(buffer[offset +x]);
                     PyTuple_SetItem(result, x, el.ptr());
                     incref(el.ptr());
                 }
@@ -321,37 +434,6 @@ namespace PyDeviceAttribute {
         }
     }
 
-    template<long tangoTypeConst>
-    static inline void _update_value_as_string(Tango::DeviceAttribute &self, object py_value)
-    {
-        typedef typename TANGO_const2type(tangoTypeConst) TangoScalarType;
-        typedef typename TANGO_const2arraytype(tangoTypeConst) TangoArrayType;
-
-        // Extract the actual data from Tango::DeviceAttribute (self)
-        TangoArrayType* value_ptr = 0;
-        try {
-            self >> value_ptr;
-        } catch (Tango::DevFailed &e ) {
-            if (strcmp(e.errors[0].reason.in(),"API_EmptyDeviceAttribute") != 0)
-                throw;
-        }
-        std::auto_ptr<TangoArrayType> guard_value_ptr(value_ptr);
-
-        if (value_ptr == 0) {
-            py_value.attr(value_attr_name) = boost::python::str();
-            py_value.attr(w_value_attr_name) = object();
-            return;
-        }
-
-        TangoScalarType* buffer = value_ptr->get_buffer();
-
-        const char *ch_ptr = reinterpret_cast<char *>(buffer);
-        size_t nb_bytes = value_ptr->length() * sizeof(TangoScalarType);
-
-        py_value.attr(value_attr_name) = str(ch_ptr, (size_t)nb_bytes);
-        py_value.attr(w_value_attr_name) = object();
-    }
-
     void update_values(Tango::DeviceAttribute &self, object& py_value, PyTango::ExtractAs extract_as/*=ExtractAsNumpy*/)
     {
         // We do not want is_empty to launch an exception!!
@@ -435,55 +517,6 @@ namespace PyDeviceAttribute {
     }
 
     template<long tangoTypeConst>
-    static inline void _fill_scalar_attribute(Tango::DeviceAttribute & dev_attr, const object & py_value)
-    {
-        typedef typename TANGO_const2type(tangoTypeConst) TangoScalarType;
-
-    TangoScalarType value;
-    from_py<tangoTypeConst>::convert(py_value.ptr(), value);
-        dev_attr << const_cast<TangoScalarType&>(value);
-    }
-
-    template<>
-    inline void _fill_scalar_attribute<Tango::DEV_STRING>(Tango::DeviceAttribute & dev_attr, const object & py_value)
-    {
-        std::string value = extract<std::string>(py_value);
-        dev_attr << value;
-    }
-
-    template<>
-    inline void _fill_scalar_attribute<Tango::DEV_ENCODED>(Tango::DeviceAttribute & dev_attr, const object & py_value)
-    {
-        static const long tangoTypeConst = Tango::DEV_ENCODED;
-        typedef TANGO_const2type(tangoTypeConst) TangoScalarType;
-        typedef TANGO_const2arraytype(tangoTypeConst) TangoArrayType;
-
-        /// @todo test it!!
-
-        /// @todo Now I am accepting 2 strings: encoded_format, encoded_data. This
-        /// is far from a good solution, but its something...
-
-        if (boost::python::len(py_value) != 2) {
-            raise_(PyExc_TypeError, "Expecting a tuple of strings: encoded_format, encoded_data");
-        }
-
-        boost::python::object encoded_format_str = py_value[0];
-        boost::python::object encoded_data_str = py_value[1];
-
-        /// @todo not sure... second parameter of insert is a reference, does it
-        /// mean anything? Does he pretend to take ownership of the pointer or
-        /// is he making another copy? what should I do?
-        char* encoded_format = const_cast<char*>((extract<const char*>(encoded_format_str)()));
-        unsigned int encoded_data_len = boost::python::len(encoded_data_str);
-        unsigned char* encoded_data = reinterpret_cast<unsigned char*>(const_cast<char*>((extract<const char*>(encoded_data_str)())));
-        // void insert(char *&,unsigned char *&,unsigned int);
-        dev_attr.insert(encoded_format, encoded_data, encoded_data_len);
-
-        std::string value = extract<std::string>(py_value);
-        dev_attr << value;
-    }
-
-    template<long tangoTypeConst>
     static inline void _fill_list_attribute(Tango::DeviceAttribute & dev_attr, const bool isImage, const object & py_value)
     {
         typedef typename TANGO_const2type(tangoTypeConst) TangoScalarType;
@@ -621,36 +654,21 @@ void export_device_attribute()
 
     DeviceAttribute
         .def(init<const Tango::DeviceAttribute &>())
-
         .def_readwrite("name", &Tango::DeviceAttribute::name)
-
         .def_readwrite("quality", &Tango::DeviceAttribute::quality)
-
         .def_readwrite("time", &Tango::DeviceAttribute::time)
-
         .add_property("dim_x", &Tango::DeviceAttribute::get_dim_x)
-
         .add_property("dim_y", &Tango::DeviceAttribute::get_dim_y)
-
         .add_property("w_dim_x", &Tango::DeviceAttribute::get_written_dim_x)
-
         .add_property("w_dim_y", &Tango::DeviceAttribute::get_written_dim_y)
-
         .add_property("r_dimension", &Tango::DeviceAttribute::get_r_dimension)
-
         .add_property("w_dimension", &Tango::DeviceAttribute::get_w_dimension)
-
         .add_property("nb_read", &Tango::DeviceAttribute::get_nb_read)
-
         .add_property("nb_written", &Tango::DeviceAttribute::get_nb_written)
-
         .add_property("data_format", &Tango::DeviceAttribute::get_data_format)
-            
         .def("get_date", &Tango::DeviceAttribute::get_date,
             return_internal_reference<>())
-
         .def("get_err_stack", &Tango::DeviceAttribute::get_err_stack,
             return_value_policy<copy_const_reference>())
-
     ;
 }
diff --git a/src/device_attribute.h b/src/device_attribute.h
index c3fccb2..e7e129c 100644
--- a/src/device_attribute.h
+++ b/src/device_attribute.h
@@ -24,12 +24,15 @@
 #pragma once
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 #include <iostream>
 #include <string>
 
 #include "pyutils.h"
 #include "defs.h"
+#include "pytgutils.h"
+#include "tango_numpy.h"
+#include "fast_from_py.h"
 
 namespace PyDeviceAttribute {
 
@@ -156,4 +159,55 @@ namespace PyDeviceAttribute {
         update_data_format(dev_proxy, dev_attr, 1);
         return convert_to_python(dev_attr, extract_as);
     }
+    
+
+    template<long tangoTypeConst>
+    static inline void _fill_scalar_attribute(Tango::DeviceAttribute & dev_attr, const boost::python::object & py_value)
+    {
+        typedef typename TANGO_const2type(tangoTypeConst) TangoScalarType;
+
+    TangoScalarType value;
+    from_py<tangoTypeConst>::convert(py_value.ptr(), value);
+        dev_attr << const_cast<TangoScalarType&>(value);
+    }
+
+    template<>
+    inline void _fill_scalar_attribute<Tango::DEV_STRING>(Tango::DeviceAttribute & dev_attr, const boost::python::object & py_value)
+    {
+        std::string value = boost::python::extract<std::string>(py_value);
+        dev_attr << value;
+    }
+
+    template<>
+    inline void _fill_scalar_attribute<Tango::DEV_ENCODED>(Tango::DeviceAttribute & dev_attr, const boost::python::object & py_value)
+    {
+        static const long tangoTypeConst = Tango::DEV_ENCODED;
+        typedef TANGO_const2type(tangoTypeConst) TangoScalarType;
+        typedef TANGO_const2arraytype(tangoTypeConst) TangoArrayType;
+
+        /// @todo test it!!
+
+        /// @todo Now I am accepting 2 strings: encoded_format, encoded_data. This
+        /// is far from a good solution, but its something...
+
+        if (boost::python::len(py_value) != 2) {
+            raise_(PyExc_TypeError, "Expecting a tuple of strings: encoded_format, encoded_data");
+        }
+
+        boost::python::object encoded_format_str = py_value[0];
+        boost::python::object encoded_data_str = py_value[1];
+
+        /// @todo not sure... second parameter of insert is a reference, does it
+        /// mean anything? Does he pretend to take ownership of the pointer or
+        /// is he making another copy? what should I do?
+        char* encoded_format = const_cast<char*>((boost::python::extract<const char*>(encoded_format_str)()));
+        unsigned int encoded_data_len = boost::python::len(encoded_data_str);
+        unsigned char* encoded_data = reinterpret_cast<unsigned char*>(const_cast<char*>((boost::python::extract<const char*>(encoded_data_str)())));
+        // void insert(char *&,unsigned char *&,unsigned int);
+        dev_attr.insert(encoded_format, encoded_data, encoded_data_len);
+
+        std::string value = boost::python::extract<std::string>(py_value);
+        dev_attr << value;
+    }
+
 }
diff --git a/src/device_attribute_config.cpp b/src/device_attribute_config.cpp
index 87b18bc..dd07798 100644
--- a/src/device_attribute_config.cpp
+++ b/src/device_attribute_config.cpp
@@ -22,7 +22,7 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 using namespace boost::python;
 
diff --git a/src/device_attribute_history.cpp b/src/device_attribute_history.cpp
index f094e27..4089909 100644
--- a/src/device_attribute_history.cpp
+++ b/src/device_attribute_history.cpp
@@ -22,7 +22,7 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 using namespace boost::python;
 
diff --git a/src/device_data.cpp b/src/device_data.cpp
index 2265ca4..8757a8d 100644
--- a/src/device_data.cpp
+++ b/src/device_data.cpp
@@ -23,7 +23,7 @@
 
 #include <boost/python.hpp>
 #include <boost/mpl/if.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 #include <iostream>
 #include <string>
 
diff --git a/src/device_data_history.cpp b/src/device_data_history.cpp
index a4ef60e..ffcbe30 100644
--- a/src/device_data_history.cpp
+++ b/src/device_data_history.cpp
@@ -22,7 +22,7 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 using namespace boost::python;
 
diff --git a/src/device_info.cpp b/src/device_info.cpp
index 9db5ced..ee16d18 100644
--- a/src/device_info.cpp
+++ b/src/device_info.cpp
@@ -22,7 +22,7 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 using namespace boost::python;
 
diff --git a/src/device_proxy.cpp b/src/device_proxy.cpp
index 56999fa..654e887 100644
--- a/src/device_proxy.cpp
+++ b/src/device_proxy.cpp
@@ -23,7 +23,7 @@
 
 #include <boost/python.hpp>
 #include <boost/python/return_value_policy.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 #include <string>
 #include <memory>
 
diff --git a/src/enums.cpp b/src/enums.cpp
index c1123df..4ae21cf 100644
--- a/src/enums.cpp
+++ b/src/enums.cpp
@@ -22,7 +22,7 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 using namespace boost::python;
 
diff --git a/src/event_data.cpp b/src/event_data.cpp
index d317fb8..b0fb084 100644
--- a/src/event_data.cpp
+++ b/src/event_data.cpp
@@ -22,7 +22,7 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 using namespace boost::python;
 
diff --git a/src/exception.cpp b/src/exception.cpp
index 009879e..0090959 100644
--- a/src/exception.cpp
+++ b/src/exception.cpp
@@ -23,7 +23,7 @@
 
 #include <boost/python.hpp>
 #include <boost/python/suite/indexing/vector_indexing_suite.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 #include <iostream>
 #include <string>
 
diff --git a/src/exception.h b/src/exception.h
index cfd94d4..cad258c 100644
--- a/src/exception.h
+++ b/src/exception.h
@@ -24,7 +24,7 @@
 #pragma once
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 /**
  * Translates a seq<DevError> into a C++ DevErrorList
diff --git a/src/fast_from_py.h b/src/fast_from_py.h
index 6e66ccb..357ba71 100644
--- a/src/fast_from_py.h
+++ b/src/fast_from_py.h
@@ -209,6 +209,28 @@ struct array_element_from_py<Tango::DEVVAR_CHARARRAY>
         convert(o.ptr(), tg);
     }
 
+#ifdef DISABLE_PYTANGO_NUMPY
+    static inline void convert(PyObject *o, TangoScalarType &tg)
+    {
+        long cpy_value = PyLong_AsLong(o);
+        if(PyErr_Occurred()) {
+            PyErr_SetString(PyExc_TypeError, "Expecting a numeric type,"
+                " but it is not");
+            boost::python::throw_error_already_set(); 
+        }
+        if (TangoScalarTypeLimits::is_integer) {
+            if (cpy_value > TangoScalarTypeLimits::max()) {
+                PyErr_SetString(PyExc_OverflowError, "Value is too large.");
+                boost::python::throw_error_already_set();
+            }
+            if (cpy_value < TangoScalarTypeLimits::min()) {
+                PyErr_SetString(PyExc_OverflowError, "Value is too small.");
+                boost::python::throw_error_already_set();
+            }
+        }
+        tg = static_cast<TangoScalarType>(cpy_value);
+    }
+#else
     static inline void convert(PyObject *o, TangoScalarType &tg)
     {
         long cpy_value = PyLong_AsLong(o);
@@ -219,12 +241,13 @@ struct array_element_from_py<Tango::DEVVAR_CHARARRAY>
             {
                 PyArray_ScalarAsCtype(o, reinterpret_cast<void*>(&tg));
                 return;
-            } else
+            } else {
                 PyErr_SetString(PyExc_TypeError, "Expecting a numeric type,"
                     " but it is not. If you use a numpy type instead of"
                     " python core types, then it must exactly match (ex:"
                     " numpy.int32 for PyTango.DevLong)");
-                boost::python::throw_error_already_set(); 
+                boost::python::throw_error_already_set();
+            }
         }
         if (TangoScalarTypeLimits::is_integer) {
             if (cpy_value > TangoScalarTypeLimits::max()) {
@@ -238,6 +261,8 @@ struct array_element_from_py<Tango::DEVVAR_CHARARRAY>
         }
         tg = static_cast<TangoScalarType>(cpy_value);
     }
+#endif // DISABLE_PYTANGO_NUMPY
+
 };
 
 
diff --git a/src/from_py.h b/src/from_py.h
index 74cbe1a..3a40e1a 100644
--- a/src/from_py.h
+++ b/src/from_py.h
@@ -28,7 +28,7 @@
 #if BOOST_VERSION < 103400
 #include <boost/python/detail/api_placeholder.hpp>
 #endif
-#include <tango/tango.h>
+#include <tango.h>
 
 #include "defs.h"
 #include "tgutils.h"
diff --git a/src/group.cpp b/src/group.cpp
index 104520c..fa4438c 100644
--- a/src/group.cpp
+++ b/src/group.cpp
@@ -24,7 +24,7 @@
 #include <boost/python/copy_const_reference.hpp>
 #include <boost/python/copy_non_const_reference.hpp>
 #include <boost/python/suite/indexing/vector_indexing_suite.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 #include <memory>
 
 #include "pytgutils.h"
diff --git a/src/group_element.cpp b/src/group_element.cpp
index 2749b32..ccf4099 100644
--- a/src/group_element.cpp
+++ b/src/group_element.cpp
@@ -24,7 +24,7 @@
 #include <boost/python/copy_const_reference.hpp>
 #include <boost/python/copy_non_const_reference.hpp>
 #include <boost/python/suite/indexing/vector_indexing_suite.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 #include "pytgutils.h"
 #include "device_attribute.h"
diff --git a/src/group_reply.cpp b/src/group_reply.cpp
index 1aee356..ce3765f 100644
--- a/src/group_reply.cpp
+++ b/src/group_reply.cpp
@@ -24,7 +24,7 @@
 #include <boost/python/copy_const_reference.hpp>
 #include <boost/python/copy_non_const_reference.hpp>
 #include <boost/python/suite/indexing/vector_indexing_suite.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 #include "pytgutils.h"
 #include "device_attribute.h"
diff --git a/src/group_reply_list.cpp b/src/group_reply_list.cpp
index 27b8e4e..83ee745 100644
--- a/src/group_reply_list.cpp
+++ b/src/group_reply_list.cpp
@@ -24,7 +24,7 @@
 #include <boost/python/copy_const_reference.hpp>
 #include <boost/python/copy_non_const_reference.hpp>
 #include <boost/python/suite/indexing/vector_indexing_suite.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 #include "pytgutils.h"
 #include "device_attribute.h"
diff --git a/src/locker_info.cpp b/src/locker_info.cpp
index 08c3895..7b32ae8 100644
--- a/src/locker_info.cpp
+++ b/src/locker_info.cpp
@@ -22,7 +22,7 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 using namespace boost::python;
 
diff --git a/src/locking_thread.cpp b/src/locking_thread.cpp
index 7224ae5..de19964 100644
--- a/src/locking_thread.cpp
+++ b/src/locking_thread.cpp
@@ -22,7 +22,7 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 using namespace boost::python;
 
diff --git a/src/periodic_event_info.cpp b/src/periodic_event_info.cpp
index e59ca84..e1767b5 100644
--- a/src/periodic_event_info.cpp
+++ b/src/periodic_event_info.cpp
@@ -22,7 +22,7 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 using namespace boost::python;
 
diff --git a/src/poll_device.cpp b/src/poll_device.cpp
index cbc83ed..388f936 100644
--- a/src/poll_device.cpp
+++ b/src/poll_device.cpp
@@ -22,7 +22,7 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 using namespace boost::python;
 
diff --git a/src/precompiled_header.hpp b/src/precompiled_header.hpp
index 78ccb6c..e45e56f 100644
--- a/src/precompiled_header.hpp
+++ b/src/precompiled_header.hpp
@@ -28,4 +28,4 @@
 // We don't want to waste those seconds for each cpp file, so we
 // use this precompiled header.
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
diff --git a/src/pytango.cpp b/src/pytango.cpp
index e905c78..c2b9ac6 100644
--- a/src/pytango.cpp
+++ b/src/pytango.cpp
@@ -32,7 +32,7 @@
 #   include <numpy/arrayobject.h>
 #endif
 
-#include <tango/tango.h>
+#include <tango.h>
 #include <iostream>
 #include <string>
 
@@ -55,6 +55,7 @@ void export_callback(); /// @todo not sure were to put it...
 void export_util();
 void export_attr();
 void export_attribute();
+void export_encoded_attribute();
 void export_wattribute();
 void export_multi_attribute();
 void export_user_default_attr_prop();
@@ -105,6 +106,7 @@ BOOST_PYTHON_MODULE(_PyTango)
     export_util();
     export_attr();
     export_attribute();
+    export_encoded_attribute();
     export_wattribute();
     export_multi_attribute();
     export_user_default_attr_prop();
diff --git a/src/pytgutils.cpp b/src/pytgutils.cpp
index 6319c68..a9c1c82 100644
--- a/src/pytgutils.cpp
+++ b/src/pytgutils.cpp
@@ -22,7 +22,7 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 #include "defs.h"
 #include "pytgutils.h"
diff --git a/src/pytgutils.h b/src/pytgutils.h
index 80e1803..4029f13 100644
--- a/src/pytgutils.h
+++ b/src/pytgutils.h
@@ -24,7 +24,7 @@
 #pragma once
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 #include "defs.h"
 #include "pyutils.h"
diff --git a/src/server/attr.cpp b/src/server/attr.cpp
index 31e5d07..c3fbc4c 100644
--- a/src/server/attr.cpp
+++ b/src/server/attr.cpp
@@ -1,5 +1,5 @@
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 #include "server/attr.h"
 
@@ -82,8 +82,6 @@ void export_attr()
         .def("set_archive_event", &Tango::Attr::set_archive_event)
         .def("is_archive_event", &Tango::Attr::is_archive_event)
         .def("is_check_archive_criteria", &Tango::Attr::is_check_archive_criteria)
-        .def("set_data_ready_event", &Tango::Attr::set_data_ready_event)
-        .def("is_data_ready_event", &Tango::Attr::is_data_ready_event)
         .def("get_name", &Tango::Attr::get_name,
             return_value_policy<copy_non_const_reference>())
         .def("get_format", &Tango::Attr::get_format)
@@ -96,9 +94,6 @@ void export_attr()
         .def("get_assoc", &Tango::Attr::get_assoc,
             return_value_policy<copy_non_const_reference>())
         .def("is_assoc", &Tango::Attr::is_assoc)
-        .def("get_cl_name", &Tango::Attr::get_cl_name,
-            return_value_policy<copy_const_reference>())
-        .def("set_cl_name", &Tango::Attr::set_cl_name)
         .def("get_class_properties", &Tango::Attr::get_class_properties,
             return_internal_reference<>())
         .def("get_user_default_properties", &Tango::Attr::get_user_default_properties,
diff --git a/src/server/attr.h b/src/server/attr.h
index 6281363..5a430aa 100644
--- a/src/server/attr.h
+++ b/src/server/attr.h
@@ -2,7 +2,7 @@
 #define _ATTR_H_
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 #include "exception.h"
 #include "pytgutils.h"
diff --git a/src/server/attribute.cpp b/src/server/attribute.cpp
index 8a9479e..b51b5fb 100644
--- a/src/server/attribute.cpp
+++ b/src/server/attribute.cpp
@@ -1,7 +1,7 @@
 #include <boost/python.hpp>
 #include <boost/python/return_value_policy.hpp>
 #include <string>
-#include <tango/tango.h>
+#include <tango.h>
 
 #include "defs.h"
 #include "pytgutils.h"
@@ -329,6 +329,9 @@ namespace PyAttribute
     inline void set_value(Tango::Attribute &att, boost::python::object &value)
     { __set_value("set_value", att, value, 0, 0); }
 
+    inline void set_value(Tango::Attribute &att, Tango::EncodedAttribute *data)
+    { att.set_value(data); }
+
     inline void set_value(Tango::Attribute &att, boost::python::str &data_str, boost::python::str &data)
     { __set_value("set_value", att, data_str, data); }
 
@@ -367,25 +370,7 @@ namespace PyAttribute
     {
         Tango::AttributeConfig tg_attr_cfg;
         att.get_properties(tg_attr_cfg);
-        attr_cfg.attr("writable") = tg_attr_cfg.writable;
-        attr_cfg.attr("data_format") = tg_attr_cfg.data_format;
-        attr_cfg.attr("max_dim_x") = tg_attr_cfg.max_dim_x;
-        attr_cfg.attr("max_dim_y") = tg_attr_cfg.max_dim_y;
-        attr_cfg.attr("data_type") = tg_attr_cfg.data_type;
-        attr_cfg.attr("name") = tg_attr_cfg.name;
-        attr_cfg.attr("label") = tg_attr_cfg.label;
-        attr_cfg.attr("description") = tg_attr_cfg.description;
-        attr_cfg.attr("unit") = tg_attr_cfg.unit;
-        attr_cfg.attr("standard_unit") = tg_attr_cfg.standard_unit;
-        attr_cfg.attr("display_unit") = tg_attr_cfg.display_unit;
-        attr_cfg.attr("format") = tg_attr_cfg.format;
-        attr_cfg.attr("writable_attr_name") = tg_attr_cfg.writable_attr_name;
-        attr_cfg.attr("min_alarm") = tg_attr_cfg.min_alarm;
-        attr_cfg.attr("max_alarm") = tg_attr_cfg.max_alarm;
-        attr_cfg.attr("min_value") = tg_attr_cfg.min_value;
-        attr_cfg.attr("max_value") = tg_attr_cfg.max_value;
-        
-        return attr_cfg;
+        return to_py(tg_attr_cfg, attr_cfg);
     }
     
     inline boost::python::object get_properties_2(Tango::Attribute &att,
@@ -393,26 +378,7 @@ namespace PyAttribute
     {
         Tango::AttributeConfig_2 tg_attr_cfg;
         att.get_properties_2(tg_attr_cfg);
-        attr_cfg.attr("writable") = tg_attr_cfg.writable;
-        attr_cfg.attr("data_format") = tg_attr_cfg.data_format;
-        attr_cfg.attr("max_dim_x") = tg_attr_cfg.max_dim_x;
-        attr_cfg.attr("max_dim_y") = tg_attr_cfg.max_dim_y;
-        attr_cfg.attr("data_type") = tg_attr_cfg.data_type;
-        attr_cfg.attr("name") = tg_attr_cfg.name;
-        attr_cfg.attr("label") = tg_attr_cfg.label;
-        attr_cfg.attr("description") = tg_attr_cfg.description;
-        attr_cfg.attr("unit") = tg_attr_cfg.unit;
-        attr_cfg.attr("standard_unit") = tg_attr_cfg.standard_unit;
-        attr_cfg.attr("display_unit") = tg_attr_cfg.display_unit;
-        attr_cfg.attr("format") = tg_attr_cfg.format;
-        attr_cfg.attr("writable_attr_name") = tg_attr_cfg.writable_attr_name;
-        attr_cfg.attr("min_alarm") = tg_attr_cfg.min_alarm;
-        attr_cfg.attr("max_alarm") = tg_attr_cfg.max_alarm;
-        attr_cfg.attr("min_value") = tg_attr_cfg.min_value;
-        attr_cfg.attr("max_value") = tg_attr_cfg.max_value;
-        attr_cfg.attr("level") = tg_attr_cfg.level;
-        
-        return attr_cfg;
+        return to_py(tg_attr_cfg, attr_cfg);
     }
 
     inline boost::python::object get_properties_3(Tango::Attribute &att,
@@ -420,51 +386,25 @@ namespace PyAttribute
     {
         Tango::AttributeConfig_3 tg_attr_cfg;
         att.get_properties_3(tg_attr_cfg);
-        attr_cfg.attr("writable") = tg_attr_cfg.writable;
-        attr_cfg.attr("data_format") = tg_attr_cfg.data_format;
-        attr_cfg.attr("max_dim_x") = tg_attr_cfg.max_dim_x;
-        attr_cfg.attr("max_dim_y") = tg_attr_cfg.max_dim_y;
-        attr_cfg.attr("data_type") = tg_attr_cfg.data_type;
-        attr_cfg.attr("name") = tg_attr_cfg.name;
-        attr_cfg.attr("label") = tg_attr_cfg.label;
-        attr_cfg.attr("description") = tg_attr_cfg.description;
-        attr_cfg.attr("unit") = tg_attr_cfg.unit;
-        attr_cfg.attr("standard_unit") = tg_attr_cfg.standard_unit;
-        attr_cfg.attr("display_unit") = tg_attr_cfg.display_unit;
-        attr_cfg.attr("format") = tg_attr_cfg.format;
-        attr_cfg.attr("writable_attr_name") = tg_attr_cfg.writable_attr_name;
-        attr_cfg.attr("min_value") = tg_attr_cfg.min_value;
-        attr_cfg.attr("max_value") = tg_attr_cfg.max_value;
-        attr_cfg.attr("level") = tg_attr_cfg.level;
-
-        // Copy alarm properties
-        object att_alarm = attr_cfg.attr("att_alarm");
-        att_alarm.attr("min_alarm") = tg_attr_cfg.att_alarm.min_alarm;
-        att_alarm.attr("max_alarm") = tg_attr_cfg.att_alarm.max_alarm;
-        att_alarm.attr("min_warning") = tg_attr_cfg.att_alarm.min_warning;
-        att_alarm.attr("max_warning") = tg_attr_cfg.att_alarm.max_warning;
-        att_alarm.attr("delta_t") = tg_attr_cfg.att_alarm.delta_t;
-        att_alarm.attr("delta_val") = tg_attr_cfg.att_alarm.delta_val;
-        
-        object event_prop = attr_cfg.attr("event_prop");
-        
-        // Copy periodic event property
-        object per_event = event_prop.attr("per_event");
-        per_event.attr("period") = tg_attr_cfg.event_prop.per_event.period;
-        
-        // Copy change event properties
-        object ch_event = event_prop.attr("ch_event");
-        ch_event.attr("rel_change") = tg_attr_cfg.event_prop.ch_event.rel_change;
-        ch_event.attr("abs_change") = tg_attr_cfg.event_prop.ch_event.abs_change;
-        
-        // Copy archive event properties
-        object arch_event = event_prop.attr("arch_event");
-        arch_event.attr("rel_change") = tg_attr_cfg.event_prop.arch_event.rel_change;
-        arch_event.attr("abs_change") = tg_attr_cfg.event_prop.arch_event.abs_change;
-        arch_event.attr("period") = tg_attr_cfg.event_prop.arch_event.period;
-        arch_event.attr("period") = tg_attr_cfg.event_prop.arch_event.period;
-        
-        return attr_cfg;
+        return to_py(tg_attr_cfg, attr_cfg);
+    }
+    
+    void set_properties(Tango::Attribute &att, boost::python::object &attr_cfg,
+                        boost::python::object &dev)
+    {
+        Tango::AttributeConfig tg_attr_cfg;
+        from_py_object(attr_cfg, tg_attr_cfg);
+        Tango::DeviceImpl *dev_ptr = extract<Tango::DeviceImpl*>(dev);
+        att.set_properties(tg_attr_cfg, dev_ptr);
+    }
+
+    void set_properties_3(Tango::Attribute &att, boost::python::object &attr_cfg,
+                          boost::python::object &dev)
+    {
+        Tango::AttributeConfig_3 tg_attr_cfg;
+        from_py_object(attr_cfg, tg_attr_cfg);
+        Tango::DeviceImpl *dev_ptr = extract<Tango::DeviceImpl*>(dev);
+        att.set_properties(tg_attr_cfg, dev_ptr);
     }
 };
 
@@ -487,7 +427,7 @@ void export_attribute()
         .value("max_warn", Tango::Attribute::max_warn)
         .value("numFlags", Tango::Attribute::numFlags)
     ;
-
+    
     class_<Tango::Attribute>("Attribute", no_init)
         .def("is_write_associated", &Tango::Attribute::is_writ_associated)
         .def("is_min_alarm", &Tango::Attribute::is_min_alarm)
@@ -534,6 +474,9 @@ void export_attribute()
             (void (*) (Tango::Attribute &, boost::python::str &, boost::python::str &))
             &PyAttribute::set_value)
         .def("set_value",
+            (void (*) (Tango::Attribute &, Tango::EncodedAttribute *))
+            &PyAttribute::set_value)
+        .def("set_value",
             (void (*) (Tango::Attribute &, boost::python::object &, long))
             &PyAttribute::set_value)
         .def("set_value",
@@ -566,7 +509,8 @@ void export_attribute()
         .def("_get_properties", &PyAttribute::get_properties)
         .def("_get_properties_2", &PyAttribute::get_properties_2)
         .def("_get_properties_3", &PyAttribute::get_properties_3)
-
         
+        .def("_set_properties", &PyAttribute::set_properties)
+        .def("_set_properties_3", &PyAttribute::set_properties_3)
     ;
 }
diff --git a/src/server/attribute.h b/src/server/attribute.h
index 0c2ef3f..a38615d 100644
--- a/src/server/attribute.h
+++ b/src/server/attribute.h
@@ -2,7 +2,7 @@
 #define _ATTRIBUTE_H_
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 namespace PyAttribute
 {
@@ -37,8 +37,11 @@ namespace PyAttribute
     boost::python::object get_properties_3(Tango::Attribute &,
                                            boost::python::object &);
 
-    boost::python::object set_properties(Tango::Attribute &,
-                                         boost::python::object &);
+    void set_properties(Tango::Attribute &, boost::python::object &,
+                        boost::python::object &);
+    
+    void set_properties_3(Tango::Attribute &, boost::python::object &,
+                          boost::python::object &);
 };
 
 
diff --git a/src/server/command.cpp b/src/server/command.cpp
index 46e2366..ffdfe9a 100644
--- a/src/server/command.cpp
+++ b/src/server/command.cpp
@@ -1,6 +1,6 @@
 #include <boost/python.hpp>
 #include <boost/python/return_value_policy.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 #include "exception.h"
 #include "pytgutils.h"
diff --git a/src/server/command.h b/src/server/command.h
index 3deb82b..f82f62c 100644
--- a/src/server/command.h
+++ b/src/server/command.h
@@ -2,7 +2,7 @@
 #define _COMMAND_H_
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 class PyCmd : public Tango::Command
 {
diff --git a/src/server/device_class.cpp b/src/server/device_class.cpp
index d664214..0757271 100644
--- a/src/server/device_class.cpp
+++ b/src/server/device_class.cpp
@@ -25,6 +25,13 @@ using namespace boost::python;
     try { boost::python::call_method<void>(m_self, #name, __VA_ARGS__); } \
     __AUX_CATCH_PY_EXCEPTION
 
+CppDeviceClass::CppDeviceClass(const string &name)
+    :Tango::DeviceClass(const_cast<string&>(name))
+{}
+
+CppDeviceClass::~CppDeviceClass()
+{}
+
 void CppDeviceClass::create_command(const std::string &cmd_name,
                                     Tango::CmdArgType param_type,
                                     Tango::CmdArgType result_type,
@@ -128,12 +135,24 @@ void CppDeviceClass::create_attribute(vector<Tango::Attr *> &att_list,
     att_list.push_back(attr_ptr);
 }
 
+CppDeviceClassWrap::CppDeviceClassWrap(PyObject *self, const std::string &name)
+    : CppDeviceClass(name), m_self(self)
+{
+    init_class();
+}
+
+/**
+ * Destructor
+ */
+CppDeviceClassWrap::~CppDeviceClassWrap()
+{}
+
 void CppDeviceClassWrap::init_class()
 {
     AutoPythonGIL python_guard;
     
     //@TODO remove this line when Tango C++ is cleaned up
-    set_py_class(true);
+    //set_py_class(true);
 
     signal_handler_defined = is_method_defined(m_self, "signal_handler");
 }
@@ -218,6 +237,23 @@ namespace PyDeviceClass
         }
         return py_dev_list;
     }
+    
+    /*
+    void add_device(CppDeviceClass &self, auto_ptr<Tango::DeviceImpl> dev)
+    {
+        self.add_device(dev.get());
+        dev.release();
+    }
+
+    void add_device(CppDeviceClass &self, auto_ptr<Tango::Device_4Impl> dev)
+    {
+        self.add_device(dev.get());
+        dev.release();
+    }
+
+    void (*add_device1)(CppDeviceClass &, auto_ptr<Tango::DeviceImpl>) = &add_device;
+    void (*add_device2)(CppDeviceClass &, auto_ptr<Tango::Device_4Impl>) = &add_device;
+    */
 }
 
 BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS (export_device_overload,
@@ -231,6 +267,7 @@ BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS (register_signal_overload,
                                         Tango::DeviceClass::register_signal, 1, 2)
 #endif
 
+
 void export_device_class()
 {
     void (Tango::DeviceClass::*add_wiz_dev_prop_)(string &,string &) =
@@ -242,13 +279,15 @@ void export_device_class()
     void (Tango::DeviceClass::*add_wiz_class_prop__)(string &,string &,string &) =
         &Tango::DeviceClass::add_wiz_class_prop;
 
-    class_<CppDeviceClass, CppDeviceClassWrap, boost::noncopyable>("_DeviceClass",
+    class_<CppDeviceClass, auto_ptr<CppDeviceClassWrap>, boost::noncopyable>("_DeviceClass",
         init<const std::string &>())
 
         .def("device_factory", &CppDeviceClassWrap::device_factory)
         .def("export_device", &CppDeviceClass::export_device,
             export_device_overload())
-        .def("cpp_add_device", &CppDeviceClass::add_device)
+        //.def("_add_device", PyDeviceClass::add_device1)
+        //.def("_add_device", PyDeviceClass::add_device2)
+        .def("_add_device", &CppDeviceClass::add_device)
         .def("register_signal",&Tango::DeviceClass::register_signal,
             register_signal_overload())
         .def("unregister_signal", &Tango::DeviceClass::unregister_signal)
@@ -283,9 +322,10 @@ void export_device_class()
         .def("_device_destroyer",
             (void (Tango::DeviceClass::*) (const char *))
             &Tango::DeviceClass::device_destroyer)
-
+        .def("is_py_class", &Tango::DeviceClass::is_py_class)
         .def("_create_attribute", &CppDeviceClass::create_attribute)
         .def("_create_command", &CppDeviceClass::create_command)
     ;
+    implicitly_convertible<auto_ptr<CppDeviceClassWrap>, auto_ptr<CppDeviceClass> >();
 }
 
diff --git a/src/server/device_class.h b/src/server/device_class.h
index 995ec6c..6d5daed 100644
--- a/src/server/device_class.h
+++ b/src/server/device_class.h
@@ -2,17 +2,14 @@
 #define _DEVICE_CLASS_H_
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 class CppDeviceClass: public Tango::DeviceClass
 {
 public:
-    CppDeviceClass(const string &name)
-        :Tango::DeviceClass(const_cast<string&>(name))
-    {}
+    CppDeviceClass(const string &);
 
-    virtual ~CppDeviceClass()
-    {}
+    virtual ~CppDeviceClass();
 
     /**
      * Export a device.
@@ -101,17 +98,12 @@ public:
      * @param[in] self A reference to the python device class object
      * @param[in] name the class name
      */
-    CppDeviceClassWrap(PyObject *self, const std::string &name)
-        : CppDeviceClass(name), m_self(self)
-    {
-        init_class();
-    }
+    CppDeviceClassWrap(PyObject *self, const std::string &name);
 
     /**
      * Destructor
      */
-    virtual ~CppDeviceClassWrap()
-    {}
+    virtual ~CppDeviceClassWrap();
 
     /**
      * This method forward a C++ call to the device_factory method to the
diff --git a/src/server/device_impl.cpp b/src/server/device_impl.cpp
index 0bad65b..a4d6ff4 100644
--- a/src/server/device_impl.cpp
+++ b/src/server/device_impl.cpp
@@ -1,7 +1,7 @@
 #include <boost/python.hpp>
 #include <boost/python/return_value_policy.hpp>
 #include <string>
-#include <tango/tango.h>
+#include <tango.h>
 
 #include "defs.h"
 #include "pytgutils.h"
@@ -656,16 +656,7 @@ PyDeviceImplBase::~PyDeviceImplBase()
 {}
 
 void PyDeviceImplBase::py_delete_dev()
-{
-    try
-    {
-        Py_DECREF(the_self);
-    }
-    catch(error_already_set &eas)
-    {
-        handle_python_exception(eas);
-    }
-}
+{}
 
 Device_3ImplWrap::Device_3ImplWrap(PyObject *self, CppDeviceClass *cl,
                                    std::string &st)
@@ -694,7 +685,7 @@ void Device_3ImplWrap::_init()
 
     // Tell Tango that this is a Python device.
     // Humm, we should try to avoid this in the future
-    this->set_py_device(true);
+    //this->set_py_device(true);
 
     Tango::Device_3ImplExt *tmp_ptr = ext_3;
     Py_Device_3ImplExt *new_ext = new Py_Device_3ImplExt(this);
@@ -854,6 +845,11 @@ Device_4ImplWrap::Device_4ImplWrap(PyObject *self, CppDeviceClass *cl,
     _init();
 }
 
+Device_4ImplWrap::~Device_4ImplWrap()
+{
+    cout << "-----------------------------------------------------hello" <<endl;
+}
+
 void Device_4ImplWrap::_init()
 {
     // Make sure the wrapper contains a valid pointer to the self
@@ -1045,7 +1041,7 @@ void export_device_impl()
     void (Tango::DeviceImpl::*stop_polling1)() = &Tango::DeviceImpl::stop_polling;
     void (Tango::DeviceImpl::*stop_polling2)(bool) = &Tango::DeviceImpl::stop_polling;
     
-    class_<Tango::DeviceImpl, DeviceImplWrap, boost::noncopyable>("DeviceImpl",
+    class_<Tango::DeviceImpl, auto_ptr<DeviceImplWrap>, boost::noncopyable>("DeviceImpl",
         init<CppDeviceClass *, const char *,
              optional<const char *, Tango::DevState, const char *> >())
 
@@ -1232,15 +1228,8 @@ void export_device_impl()
         .def("__warn_stream", &PyDeviceImpl::warn)
         .def("__error_stream", &PyDeviceImpl::error)
         .def("__fatal_stream", &PyDeviceImpl::fatal)
-        
-        .def("get_min_poll_period", &Tango::DeviceImpl::get_min_poll_period)
-        .def("get_cmd_min_poll_period", 
-            &Tango::DeviceImpl::get_cmd_min_poll_period,
-            return_internal_reference<>())
-        .def("get_attr_min_poll_period", 
-            &Tango::DeviceImpl::get_attr_min_poll_period,
-            return_internal_reference<>())
     ;
+    implicitly_convertible<auto_ptr<DeviceImplWrap>, auto_ptr<Tango::DeviceImpl> >();
     
     class_<Tango::Device_2Impl, Device_2ImplWrap,
            bases<Tango::DeviceImpl>,
@@ -1277,7 +1266,7 @@ void export_device_impl()
         .def("set_attribute_config_3", &PyDevice_3Impl::set_attribute_config_3)
     ;
 
-    class_<Tango::Device_4Impl, Device_4ImplWrap,
+    class_<Tango::Device_4Impl, auto_ptr<Device_4ImplWrap>,
            bases<Tango::Device_3Impl>,
            boost::noncopyable>
            ("Device_4Impl",
@@ -1299,4 +1288,5 @@ void export_device_impl()
         .def("signal_handler", &Tango::Device_4Impl::signal_handler,
             &Device_4ImplWrap::default_signal_handler)
     ;
+    implicitly_convertible<auto_ptr<Device_4ImplWrap>, auto_ptr<Tango::Device_4Impl> >();
 }
diff --git a/src/server/device_impl.h b/src/server/device_impl.h
index f52bc24..b3a078f 100644
--- a/src/server/device_impl.h
+++ b/src/server/device_impl.h
@@ -2,7 +2,7 @@
 #define _DEVICE_IMPL_H
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 #include <server/device_class.h>
 
@@ -289,8 +289,7 @@ public:
     /**
      * Destructor
      */
-    virtual ~Device_4ImplWrap()
-    {}
+    virtual ~Device_4ImplWrap();
 
     /**
      * A wrapper around the add_attribute in order to process some
diff --git a/src/server/dserver.cpp b/src/server/dserver.cpp
index 9bf22e5..7478783 100644
--- a/src/server/dserver.cpp
+++ b/src/server/dserver.cpp
@@ -1,5 +1,5 @@
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 #include "to_py.h"
 #include "from_py.h"
diff --git a/src/server/encoded_attribute.cpp b/src/server/encoded_attribute.cpp
new file mode 100644
index 0000000..f44e222
--- /dev/null
+++ b/src/server/encoded_attribute.cpp
@@ -0,0 +1,844 @@
+/*******************************************************************************
+
+   This file is part of PyTango, a python binding for Tango
+
+   http://www.tango-controls.org/static/PyTango/latest/doc/html/index.html
+
+   (copyleft) CELLS / ALBA Synchrotron, Bellaterra, Spain
+  
+   This 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.
+  
+   This software 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 this program; if not, see <http://www.gnu.org/licenses/>.
+   
+*******************************************************************************/
+
+#include <boost/python.hpp>
+#include <tango.h>
+#include "tango_numpy.h"
+#include "device_attribute.h"
+
+using namespace boost::python;
+
+namespace PyEncodedAttribute
+{
+    /// This callback is run to delete char* objects.
+    /// It is called by python. The array was associated with an attribute
+    /// value object that is not being used anymore.
+    /// @param ptr_ The array object.
+    /// @param type_ The type of data. We don't need it for now
+
+    static void __ptr_deleter(void * ptr_, void *type_)
+    {
+        long t = reinterpret_cast<long>(type_);
+        if (1 == t)
+            delete [] (static_cast<unsigned char*>(ptr_));
+        else if (2 == t)
+            delete [] (static_cast<unsigned short*>(ptr_));
+        else if (4 == t)
+            delete [] (static_cast<uint32_t*>(ptr_));
+    }
+    
+    void encode_gray8(Tango::EncodedAttribute &self, object py_value, int w, int h)
+    {
+        PyObject *py_value_ptr = py_value.ptr();
+        unsigned char *buffer = NULL;
+        if (PyString_Check(py_value_ptr))
+        {
+            buffer = reinterpret_cast<unsigned char*>(PyString_AsString(py_value_ptr));
+            self.encode_gray8(buffer, w, h);
+            return;
+        }
+        else if (PyArray_Check(py_value_ptr))
+        {
+            w = PyArray_DIM(py_value_ptr, 1);
+            h = PyArray_DIM(py_value_ptr, 0);
+            
+            buffer = static_cast<unsigned char*>(PyArray_DATA(py_value_ptr));
+            self.encode_gray8(buffer, w, h);
+            return;
+        }
+        // It must be a py sequence
+        // we are sure that w and h are given by python (see encoded_attribute.py)
+        unsigned char b[w*h];
+        buffer = b;
+        unsigned char *p = b;
+        int w_bytes = w;
+        for (long y=0; y<h; ++y)
+        {
+            PyObject *row = PySequence_GetItem(py_value_ptr, y);
+            if (!row) boost::python::throw_error_already_set();
+            if (!PySequence_Check(row))
+            {
+                Py_DECREF(row);
+                PyErr_SetString(PyExc_TypeError,
+                    "Expected sequence (str, numpy.ndarray, list, tuple or "
+                    "bytearray) inside a sequence");
+                boost::python::throw_error_already_set();
+            }
+            // The given object is a sequence of strings were each string is the entire row
+            if (PyString_Check(row))
+            {
+                if (PyString_Size(row) != w_bytes)
+                {
+                    Py_DECREF(row);
+                    PyErr_SetString(PyExc_TypeError,
+                        "All sequences inside a sequence must have same size");
+                    boost::python::throw_error_already_set();
+                }
+                memcpy(p, PyString_AsString(row), w_bytes);
+                p += w;
+            }
+            else
+            {
+                if (PySequence_Size(row) != w)
+                {
+                    Py_DECREF(row);
+                    PyErr_SetString(PyExc_TypeError,
+                        "All sequences inside a sequence must have same size");
+                    boost::python::throw_error_already_set();
+                }
+                
+                for (long x=0; x<w; ++x)
+                {
+                    PyObject *cell = PySequence_GetItem(row, x);
+                    if (!cell)
+                    {
+                        Py_DECREF(row);
+                        boost::python::throw_error_already_set();
+                    }
+                    if (PyString_Check(cell))
+                    {
+                        if (PyString_Size(cell) != 1)
+                        {
+                            Py_DECREF(row);
+                            Py_DECREF(cell);
+                            PyErr_SetString(PyExc_TypeError,
+                                "All string items must have length one");
+                            boost::python::throw_error_already_set();
+                        }
+                        char byte = PyString_AsString(cell)[0];
+                        *p = byte;
+                    }
+                    else if (PyInt_Check(cell) || PyLong_Check(cell))
+                    {
+                        long byte = PyLong_AsLong(cell);
+                        if (byte==-1 and PyErr_Occurred())
+                        {
+                            Py_DECREF(row);
+                            Py_DECREF(cell);
+                            boost::python::throw_error_already_set();
+                        }
+                        if (byte < 0 || byte > 255)
+                        {
+                            Py_DECREF(row);
+                            Py_DECREF(cell);
+                            PyErr_SetString(PyExc_TypeError,
+                                "int item not in range(256)");
+                            boost::python::throw_error_already_set();
+                        }
+                        *p = (unsigned char)byte;
+                        
+                    }
+                    Py_DECREF(cell);
+                    p++;
+                }
+            }
+            Py_DECREF(row);
+        }
+        self.encode_gray8(buffer, w, h);
+    }
+
+    void encode_gray16(Tango::EncodedAttribute &self, object py_value, int w, int h)
+    {
+        PyObject *py_value_ptr = py_value.ptr();
+        unsigned short *buffer = NULL;
+        if (PyString_Check(py_value_ptr))
+        {
+            buffer = reinterpret_cast<unsigned short*>(PyString_AsString(py_value_ptr));
+            self.encode_gray16(buffer, w, h);
+            return;
+        }
+        else if (PyArray_Check(py_value_ptr))
+        {
+            w = PyArray_DIM(py_value_ptr, 1);
+            h = PyArray_DIM(py_value_ptr, 0);
+            
+            buffer = static_cast<unsigned short*>(PyArray_DATA(py_value_ptr));
+            self.encode_gray16(buffer, w, h);
+            return;
+        }
+        // It must be a py sequence
+        // we are sure that w and h are given by python (see encoded_attribute.py)
+        unsigned short b[w*h];
+        buffer = b;
+        unsigned short *p = b;
+        int w_bytes = 2*w;
+        for (long y=0; y<h; ++y)
+        {
+            PyObject *row = PySequence_GetItem(py_value_ptr, y);
+            if (!row) boost::python::throw_error_already_set();
+            if (!PySequence_Check(row))
+            {
+                Py_DECREF(row);
+                PyErr_SetString(PyExc_TypeError,
+                    "Expected sequence (str, numpy.ndarray, list, tuple or "
+                    "bytearray) inside a sequence");
+                boost::python::throw_error_already_set();
+            }
+            // The given object is a sequence of strings were each string is the entire row
+            if (PyString_Check(row))
+            {
+                if (PyString_Size(row) != w_bytes)
+                {
+                    Py_DECREF(row);
+                    PyErr_SetString(PyExc_TypeError,
+                        "All sequences inside a sequence must have same size");
+                    boost::python::throw_error_already_set();
+                }
+                memcpy(p, PyString_AsString(row), w_bytes);
+                p += w;
+            }
+            else
+            {
+                if (PySequence_Size(row) != w)
+                {
+                    Py_DECREF(row);
+                    PyErr_SetString(PyExc_TypeError,
+                        "All sequences inside a sequence must have same size");
+                    boost::python::throw_error_already_set();
+                }
+                
+                for (long x=0; x<w; ++x)
+                {
+                    PyObject *cell = PySequence_GetItem(row, x);
+                    if (!cell)
+                    {
+                        Py_DECREF(row);
+                        boost::python::throw_error_already_set();
+                    }
+                    if (PyString_Check(cell))
+                    {
+                        if (PyString_Size(cell) != 2)
+                        {
+                            Py_DECREF(row);
+                            Py_DECREF(cell);
+                            PyErr_SetString(PyExc_TypeError,
+                                "All string items must have length two");
+                            boost::python::throw_error_already_set();
+                        }
+                        unsigned short *word = reinterpret_cast<unsigned short *>(PyString_AsString(cell));
+                        *p = *word;
+                    }
+                    else if (PyInt_Check(cell) || PyLong_Check(cell))
+                    {
+                        unsigned short word = PyLong_AsUnsignedLong(cell);
+                        if (PyErr_Occurred())
+                        {
+                            Py_DECREF(row);
+                            Py_DECREF(cell);
+                            boost::python::throw_error_already_set();
+                        }
+                        *p = word;
+                    }
+                    else
+                    {
+                            Py_DECREF(row);
+                            Py_DECREF(cell);
+                            PyErr_SetString(PyExc_TypeError,
+                                "Unsupported data type in array element");
+                            boost::python::throw_error_already_set();
+                    }
+                    Py_DECREF(cell);
+                    p++;
+                }
+            }
+            Py_DECREF(row);
+        }
+        self.encode_gray16(buffer, w, h);
+    }
+    
+    void encode_rgb24(Tango::EncodedAttribute &self, object py_value, int w, int h)
+    {
+        PyObject *py_value_ptr = py_value.ptr();
+        unsigned char *buffer = NULL;
+        if (PyString_Check(py_value_ptr))
+        {
+            buffer = reinterpret_cast<unsigned char*>(PyString_AsString(py_value_ptr));
+            self.encode_rgb24(buffer, w, h);
+            return;
+        }
+        else if (PyArray_Check(py_value_ptr))
+        {
+            buffer = static_cast<unsigned char*>(PyArray_DATA(py_value_ptr));
+            self.encode_rgb24(buffer, w, h);
+            return;
+        }
+        // It must be a py sequence
+        // we are sure that w and h are given by python (see encoded_attribute.py)
+        unsigned char b[w*h];
+        buffer = b;
+        unsigned char *p = b;
+        int w_bytes = 3*w;
+        for (long y=0; y<h; ++y)
+        {
+            PyObject *row = PySequence_GetItem(py_value_ptr, y);
+            if (!row) boost::python::throw_error_already_set();
+            if (!PySequence_Check(row))
+            {
+                Py_DECREF(row);
+                PyErr_SetString(PyExc_TypeError,
+                    "Expected sequence (str, numpy.ndarray, list, tuple or "
+                    "bytearray) inside a sequence");
+                boost::python::throw_error_already_set();
+            }
+            // The given object is a sequence of strings were each string is the entire row
+            if (PyString_Check(row))
+            {
+                if (PyString_Size(row) != w_bytes)
+                {
+                    Py_DECREF(row);
+                    PyErr_SetString(PyExc_TypeError,
+                        "All sequences inside a sequence must have same size");
+                    boost::python::throw_error_already_set();
+                }
+                memcpy(p, PyString_AsString(row), w_bytes);
+                p += w;
+            }
+            else
+            {
+                if (PySequence_Size(row) != w)
+                {
+                    Py_DECREF(row);
+                    PyErr_SetString(PyExc_TypeError,
+                        "All sequences inside a sequence must have same size");
+                    boost::python::throw_error_already_set();
+                }
+                
+                for (long x=0; x<w; ++x)
+                {
+                    PyObject *cell = PySequence_GetItem(row, x);
+                    if (!cell)
+                    {
+                        Py_DECREF(row);
+                        boost::python::throw_error_already_set();
+                    }
+                    if (PyString_Check(cell))
+                    {
+                        if (PyString_Size(cell) != 3)
+                        {
+                            Py_DECREF(row);
+                            Py_DECREF(cell);
+                            PyErr_SetString(PyExc_TypeError,
+                                "All string items must have length one");
+                            boost::python::throw_error_already_set();
+                        }
+                        char *byte = PyString_AsString(cell);
+                        *p = *byte; p++; byte++;
+                        *p = *byte; p++; byte++;
+                        *p = *byte; p++;
+                    }
+                    else if (PyInt_Check(cell) || PyLong_Check(cell))
+                    {
+                        long byte = PyLong_AsLong(cell);
+                        if (byte==-1 and PyErr_Occurred())
+                        {
+                            Py_DECREF(row);
+                            Py_DECREF(cell);
+                            boost::python::throw_error_already_set();
+                        }
+                        if (BYTE_ORDER == LITTLE_ENDIAN)
+                        {
+                            *p = (byte) & 0xFF; p++;
+                            *p = (byte >>  8) & 0xFF; p++;
+                            *p = (byte >> 16) & 0xFF; p++;
+                        }
+                        else
+                        {
+                            *p = (byte >> 16) & 0xFF; p++;
+                            *p = (byte >>  8) & 0xFF; p++;
+                            *p = (byte) & 0xFF; p++;
+                        }
+                    }
+                    Py_DECREF(cell);
+                }
+            }
+            Py_DECREF(row);
+        }
+        self.encode_rgb24(buffer, w, h);
+    }
+    
+    PyObject *decode_gray8(Tango::EncodedAttribute &self, Tango::DeviceAttribute *attr, PyTango::ExtractAs extract_as)
+    {
+        unsigned char *buffer;
+        int width, height;
+
+        self.decode_gray8(attr, &width, &height, &buffer);
+        
+        char *ch_ptr = reinterpret_cast<char *>(buffer);
+        PyObject *ret = NULL;
+        switch (extract_as)
+        {
+            case PyTango::ExtractAsNumpy:
+#ifndef DISABLE_PYTANGO_NUMPY
+            {
+                npy_intp dims[2] = { height, width };
+                ret = PyArray_SimpleNewFromData(2, dims, NPY_UBYTE, ch_ptr);
+                if (!ret)
+                {
+                    delete [] buffer;
+                    throw_error_already_set();
+                }
+                // numpy.ndarray() does not own it's memory, so we need to manage it.
+                // We can assign a 'base' object that will be informed (decref'd) when
+                // the last copy of numpy.ndarray() disappears.
+                // PyCObject is intended for that kind of things. It's seen as a
+                // black box object from python. We assign him a function to be called
+                // when it is deleted -> the function deletes de data.
+                PyObject* guard = PyCObject_FromVoidPtrAndDesc(
+                    static_cast<void*>(ch_ptr),
+                    reinterpret_cast<void*>(1),
+                    __ptr_deleter);
+                    
+                if (!guard)
+                {
+                    Py_XDECREF(ret);
+                    delete [] buffer;
+                    throw_error_already_set();
+                }
+                
+                PyArray_BASE(ret) = guard;
+                break;
+            }
+#endif
+            case PyTango::ExtractAsString:
+            {
+                ret = PyTuple_New(3);
+                if (!ret)
+                {
+                    delete [] buffer;
+                    throw_error_already_set();
+                }
+                size_t nb_bytes = width*height*sizeof(char);
+                PyObject *buffer_str = PyString_FromStringAndSize(ch_ptr, nb_bytes);
+                if (!buffer_str)
+                {
+                    Py_XDECREF(ret);
+                    delete [] buffer;
+                    throw_error_already_set();
+                }
+                
+                PyTuple_SetItem(ret, 0, PyLong_FromLong(width));
+                PyTuple_SetItem(ret, 1, PyLong_FromLong(height));
+                PyTuple_SetItem(ret, 2, buffer_str);
+                delete [] buffer;
+                break;
+            }
+            case PyTango::ExtractAsTuple:
+            {
+                ret = PyTuple_New(height);
+                if (!ret)
+                {
+                    delete [] buffer;
+                    throw_error_already_set();
+                }
+                
+                for (long y=0; y < height; ++y) 
+                {
+                    PyObject *row = PyTuple_New(width);
+                    if (!row)
+                    {
+                        Py_XDECREF(ret);
+                        delete [] buffer;
+                        throw_error_already_set();
+                    }
+                    for (long x=0; x < width; ++x)
+                    {
+                        PyTuple_SetItem(row, x, PyString_FromStringAndSize(ch_ptr + y*width+x, 1));
+                    }
+                    PyTuple_SetItem(ret, y, row);
+                }
+                
+                delete [] buffer;
+                break;
+            }
+            case PyTango::ExtractAsPyTango3:
+            case PyTango::ExtractAsList:
+            {
+                ret = PyList_New(height);
+                if (!ret)
+                {
+                    delete [] buffer;
+                    throw_error_already_set();
+                }
+                
+                for (long y=0; y < height; ++y) 
+                {
+                    PyObject *row = PyList_New(width);
+                    if (!row)
+                    {
+                        Py_XDECREF(ret);
+                        delete [] buffer;
+                        throw_error_already_set();
+                    }
+                    for (long x=0; x < width; ++x)
+                    {
+                        PyList_SetItem(row, x, PyString_FromStringAndSize(ch_ptr + y*width+x, 1));
+                    }
+                    PyList_SetItem(ret, y, row);
+                }
+                
+                delete [] buffer;
+                break;
+            }
+            default:
+            {
+                delete [] buffer;
+                PyErr_SetString(PyExc_TypeError, "decode only supports "
+                    "ExtractAs Numpy, String, Tuple and List");
+                boost::python::throw_error_already_set();
+                break;
+            }
+        }
+        return ret;
+    }
+    
+    PyObject *decode_gray16(Tango::EncodedAttribute &self, Tango::DeviceAttribute *attr, PyTango::ExtractAs extract_as)
+    {
+        unsigned short *buffer;
+        int width, height;
+
+        self.decode_gray16(attr, &width, &height, &buffer);
+        
+        unsigned short *ch_ptr = buffer;
+        PyObject *ret = NULL;
+        switch (extract_as)
+        {
+            case PyTango::ExtractAsNumpy:
+            {
+                npy_intp dims[2] = { height, width };
+                ret = PyArray_SimpleNewFromData(2, dims, NPY_USHORT, ch_ptr);
+                if (!ret)
+                {
+                    delete [] buffer;
+                    throw_error_already_set();
+                }
+                // numpy.ndarray() does not own it's memory, so we need to manage it.
+                // We can assign a 'base' object that will be informed (decref'd) when
+                // the last copy of numpy.ndarray() disappears.
+                // PyCObject is intended for that kind of things. It's seen as a
+                // black box object from python. We assign him a function to be called
+                // when it is deleted -> the function deletes de data.
+                PyObject* guard = PyCObject_FromVoidPtrAndDesc(
+                    static_cast<void*>(ch_ptr),
+                    reinterpret_cast<void*>(2),
+                    __ptr_deleter);
+                    
+                if (!guard)
+                {
+                    Py_XDECREF(ret);
+                    delete [] buffer;
+                    throw_error_already_set();
+                }
+                
+                PyArray_BASE(ret) = guard;
+                break;
+            }
+            case PyTango::ExtractAsString:
+            {
+                ret = PyTuple_New(3);
+                if (!ret)
+                {
+                    delete [] buffer;
+                    throw_error_already_set();
+                }
+                size_t nb_bytes = width*height*sizeof(unsigned short);
+                
+                PyObject *buffer_str = PyString_FromStringAndSize(
+                    reinterpret_cast<char *>(ch_ptr), nb_bytes);
+                delete [] buffer;
+                
+                if (!buffer_str)
+                {
+                    Py_XDECREF(ret);
+                    throw_error_already_set();
+                }
+                
+                PyTuple_SetItem(ret, 0, PyLong_FromLong(width));
+                PyTuple_SetItem(ret, 1, PyLong_FromLong(height));
+                PyTuple_SetItem(ret, 2, buffer_str);
+                
+                break;
+            }
+            case PyTango::ExtractAsTuple:
+            {
+                ret = PyTuple_New(height);
+                if (!ret)
+                {
+                    delete [] buffer;
+                    throw_error_already_set();
+                }
+                
+                for (long y=0; y < height; ++y) 
+                {
+                    PyObject *row = PyTuple_New(width);
+                    if (!row)
+                    {
+                        Py_XDECREF(ret);
+                        delete [] buffer;
+                        throw_error_already_set();
+                    }
+                    for (long x=0; x < width; ++x)
+                    {
+                        PyTuple_SetItem(row, x, PyLong_FromUnsignedLong(ch_ptr[y*width+x]));
+                    }
+                    PyTuple_SetItem(ret, y, row);
+                }
+                
+                delete [] buffer;
+                break;
+            }
+            case PyTango::ExtractAsPyTango3:
+            case PyTango::ExtractAsList:
+            {
+                ret = PyList_New(height);
+                if (!ret)
+                {
+                    delete [] buffer;
+                    throw_error_already_set();
+                }
+                
+                for (long y=0; y < height; ++y) 
+                {
+                    PyObject *row = PyList_New(width);
+                    if (!row)
+                    {
+                        Py_XDECREF(ret);
+                        delete [] buffer;
+                        throw_error_already_set();
+                    }
+                    for (long x=0; x < width; ++x)
+                    {
+                        PyList_SetItem(row, x, PyLong_FromUnsignedLong(ch_ptr[y*width+x]));
+                    }
+                    PyList_SetItem(ret, y, row);
+                }
+                
+                delete [] buffer;
+                break;
+            }
+            default:
+            {
+                delete [] buffer;
+                PyErr_SetString(PyExc_TypeError, "decode only supports "
+                    "ExtractAs Numpy, String, Tuple and List");
+                boost::python::throw_error_already_set();
+                break;
+            }
+        }
+        return ret;
+    }
+
+    PyObject *decode_rgb32(Tango::EncodedAttribute &self, Tango::DeviceAttribute *attr, PyTango::ExtractAs extract_as)
+    {
+        unsigned char *buffer;
+        int width, height;
+
+        self.decode_rgb32(attr, &width, &height, &buffer);
+
+        unsigned char *ch_ptr = buffer;
+        PyObject *ret = NULL;
+        switch (extract_as)
+        {
+            case PyTango::ExtractAsNumpy:
+            {
+                npy_intp dims[2] = { height, width };
+                ret = PyArray_SimpleNewFromData(2, dims, NPY_UINT32, ch_ptr);
+                if (!ret)
+                {
+                    delete [] buffer;
+                    throw_error_already_set();
+                }
+                // numpy.ndarray() does not own it's memory, so we need to manage it.
+                // We can assign a 'base' object that will be informed (decref'd) when
+                // the last copy of numpy.ndarray() disappears.
+                // PyCObject is intended for that kind of things. It's seen as a
+                // black box object from python. We assign him a function to be called
+                PyObject* guard = PyCObject_FromVoidPtrAndDesc(
+                // when it is deleted -> the function deletes de data.
+                    static_cast<void*>(ch_ptr),
+                    reinterpret_cast<void*>(2),
+                    __ptr_deleter);
+                    
+                if (!guard)
+                {
+                    Py_XDECREF(ret);
+                    delete [] buffer;
+                    throw_error_already_set();
+                }
+                
+                PyArray_BASE(ret) = guard;
+                break;
+            }
+            case PyTango::ExtractAsString:
+            {
+                ret = PyTuple_New(3);
+                if (!ret)
+                {
+                    delete [] buffer;
+                    throw_error_already_set();
+                }
+                size_t nb_bytes = width*height*4;
+                
+                PyObject *buffer_str = PyString_FromStringAndSize(
+                    reinterpret_cast<char *>(ch_ptr), nb_bytes);
+                delete [] buffer;
+                
+                if (!buffer_str)
+                {
+                    Py_XDECREF(ret);
+                    throw_error_already_set();
+                }
+                
+                PyTuple_SetItem(ret, 0, PyLong_FromLong(width));
+                PyTuple_SetItem(ret, 1, PyLong_FromLong(height));
+                PyTuple_SetItem(ret, 2, buffer_str);
+                
+                break;
+            }
+            case PyTango::ExtractAsTuple:
+            {
+                ret = PyTuple_New(height);
+                if (!ret)
+                {
+                    delete [] buffer;
+                    throw_error_already_set();
+                }
+                
+                for (long y=0; y < height; ++y) 
+                {
+                    PyObject *row = PyTuple_New(width);
+                    if (!row)
+                    {
+                        Py_XDECREF(ret);
+                        delete [] buffer;
+                        throw_error_already_set();
+                    }
+                    for (long x=0; x < width; ++x)
+                    {
+                        long idx = 4*(y*width+x);
+                        // data comes in in big endian format
+                        uint32_t data;
+                        if (BYTE_ORDER == LITTLE_ENDIAN)
+                        {
+                            idx +=3;
+                            char *p = reinterpret_cast<char *>(&data);
+                            *p = ch_ptr[idx--]; ++p;
+                            *p = ch_ptr[idx--]; ++p;
+                            *p = ch_ptr[idx--]; ++p;
+                            *p = ch_ptr[idx];
+                        }
+                        else
+                        {
+                            char *p = reinterpret_cast<char *>(&data);
+                            *p = ch_ptr[idx++]; ++p;
+                            *p = ch_ptr[idx++]; ++p;
+                            *p = ch_ptr[idx++]; ++p;
+                            *p = ch_ptr[idx];
+                        }
+                        PyTuple_SetItem(row, x, PyLong_FromUnsignedLong(data));
+                    }
+                    PyTuple_SetItem(ret, y, row);
+                }
+                
+                delete [] buffer;
+                break;
+            }
+            case PyTango::ExtractAsPyTango3:
+            case PyTango::ExtractAsList:
+            {
+                ret = PyList_New(height);
+                if (!ret)
+                {
+                    delete [] buffer;
+                    throw_error_already_set();
+                }
+                
+                for (long y=0; y < height; ++y) 
+                {
+                    PyObject *row = PyList_New(width);
+                    if (!row)
+                    {
+                        Py_XDECREF(ret);
+                        delete [] buffer;
+                        throw_error_already_set();
+                    }
+                    for (long x=0; x < width; ++x)
+                    {
+                        long idx = 4*(y*width+x);
+                        // data comes in in big endian format
+                        uint32_t data;
+                        if (BYTE_ORDER == LITTLE_ENDIAN)
+                        {
+                            idx +=3;
+                            char *p = reinterpret_cast<char *>(&data);
+                            *p = ch_ptr[idx--]; ++p;
+                            *p = ch_ptr[idx--]; ++p;
+                            *p = ch_ptr[idx--]; ++p;
+                            *p = ch_ptr[idx];
+                        }
+                        else
+                        {
+                            char *p = reinterpret_cast<char *>(&data);
+                            *p = ch_ptr[idx++]; ++p;
+                            *p = ch_ptr[idx++]; ++p;
+                            *p = ch_ptr[idx++]; ++p;
+                            *p = ch_ptr[idx];
+                        }
+                        PyList_SetItem(row, x, PyLong_FromUnsignedLong(data));
+                    }
+                    PyList_SetItem(ret, y, row);
+                }
+                
+                delete [] buffer;
+                break;
+            }
+            default:
+            {
+                delete [] buffer;
+                PyErr_SetString(PyExc_TypeError, "decode only supports "
+                    "ExtractAs Numpy, String, Tuple and List");
+                boost::python::throw_error_already_set();
+                break;
+            }
+        }
+        return ret;
+    }
+    
+}
+
+void export_encoded_attribute()
+{
+    
+    class_<Tango::EncodedAttribute, boost::noncopyable> EncodedAttribute(
+        "EncodedAttribute",
+        init<>());
+    
+    EncodedAttribute
+        .def(init<int, optional<bool> >())
+        .def("_encode_gray8", &PyEncodedAttribute::encode_gray8)
+        .def("_encode_gray16", &PyEncodedAttribute::encode_gray16)
+        .def("_encode_rgb24", &PyEncodedAttribute::encode_rgb24)
+        .def("_decode_gray8", &PyEncodedAttribute::decode_gray8)
+        .def("_decode_gray16", &PyEncodedAttribute::decode_gray16)
+        .def("_decode_rgb32", &PyEncodedAttribute::decode_rgb32)
+    ;
+}
\ No newline at end of file
diff --git a/src/server/log4tango.cpp b/src/server/log4tango.cpp
index 61a8c02..7e0e6c4 100644
--- a/src/server/log4tango.cpp
+++ b/src/server/log4tango.cpp
@@ -1,5 +1,5 @@
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 #include "defs.h"
 #include "pytgutils.h"
diff --git a/src/server/subdev.cpp b/src/server/subdev.cpp
index 044e3be..08449b3 100644
--- a/src/server/subdev.cpp
+++ b/src/server/subdev.cpp
@@ -1,5 +1,5 @@
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 using namespace boost::python;
 
diff --git a/src/server/tango_util.cpp b/src/server/tango_util.cpp
index 67d80ef..0a7c6d2 100644
--- a/src/server/tango_util.cpp
+++ b/src/server/tango_util.cpp
@@ -22,7 +22,7 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 #include <iostream>
 
 #include "defs.h"
@@ -33,104 +33,21 @@
 
 using namespace boost::python;
 
-#define __OLD_TANGO__
-
-#ifdef __OLD_TANGO__
-
-#ifdef _TG_WINDOWS_
+/// @todo GET RID OF THIS!! I HATE "HERE_OLD_TANGO___"
+#ifndef WIN32
+# define HERE_OLD_TANGO___
+#endif
 
+#ifdef HERE_OLD_TANGO___
+    void Tango::DServer::class_factory()
+    {
+        Tango::DServer* dserver = this;
 #else
-#include <dlfcn.h>
-#endif /* _TG_WINDOWS_ */
-
-#endif /* __OLD_TANGO__ */
-
 namespace PyUtil
 {
-
-#ifdef __OLD_TANGO__
-    void create_cpp_class(Tango::DServer *dserver, const char *cl_name,
-                          const char *par_name)
-    {
-        std::string class_name(cl_name);
-        std::string lib_name = class_name;
-        
-#ifdef _TG_WINDOWS_
-        HMODULE mod;
-
-        if ((mod = LoadLibrary(lib_name.c_str())) == NULL)
-        {
-               char *str = 0;
-            
-            DWORD l_err = GetLastError();
-                ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,NULL,
-                      l_err,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(char *)&str,0,NULL);
-
-            cerr << "Error: " << str << endl;
-
-            TangoSys_OMemStream o;
-            o << "Trying to load shared library " << lib_name << " failed. It returns error: " << str << ends;
-            ::LocalFree((HLOCAL)str);
-
-            Tango::Except::throw_exception("API_ClassNotFound",o.str(),
-                                           "DServer::create_cpp_class");
-        }
-        
-        std::string sym_name("_create_");
-        sym_name = sym_name + class_name;
-        sym_name = sym_name + "_class";
-        
-        FARPROC proc;
-        
-        if ((proc = GetProcAddress(mod,sym_name.c_str())) == NULL)
-        {
-            TangoSys_OMemStream o;
-            o << "Class " << cl_name << " does not have the C creator function (_create_<Class name>_class)" << ends;
-
-            Tango::Except::throw_exception("API_ClassNotFound",o.str(),
-                                           "DServer::create_cpp_class");
-        }
-        
-        Cpp_creator_ptr mt = (Cpp_creator_ptr)proc;
-#else
-        void *lib_ptr;
-        lib_name = lib_name + ".so";
-        
-        lib_ptr = dlopen(lib_name.c_str(),RTLD_NOW);
-        if (lib_ptr == NULL)
-        {
-            TangoSys_OMemStream o;
-            o << "Trying to load shared library " << lib_name << " failed. It returns error: " << dlerror() << ends;
-
-            Tango::Except::throw_exception("API_ClassNotFound",o.str(),
-                                           "DServer::create_cpp_class");
-        }
-        
-        void *sym;
-
-        std::string sym_name("_create_");
-        sym_name = sym_name + class_name;
-        sym_name = sym_name + "_class";
-        
-        sym = dlsym(lib_ptr,sym_name.c_str());
-        if (sym == NULL)
-        {
-            TangoSys_OMemStream o;
-            o << "Class " << cl_name << " does not have the C creator function (_create_<Class name>_class)" << ends;
-
-            Tango::Except::throw_exception("API_ClassNotFound",o.str(),
-                                           "DServer::create_cpp_class");
-        }
-        
-        Tango::Cpp_creator_ptr mt = (Tango::Cpp_creator_ptr)sym;
-#endif /* _TG_WINDOWS_ */
-        Tango::DeviceClass *dc = (*mt)(par_name);
-        dserver->_add_class(dc);
-    }
-#endif /* __OLD_TANGO__ */
-
     void _class_factory(Tango::DServer* dserver)
     {
+#endif
         AutoPythonGIL guard;
         PYTANGO_MOD
 
@@ -143,13 +60,9 @@ namespace PyUtil
         for(int i = 0; i < cl_len; ++i)
         {
             tuple class_info = extract<tuple>(cpp_class_list[i]);
-            const char *class_name = extract<const char *>(class_info[0]);
-            const char *par_name   = extract<const char *>(class_info[1]);
-#ifdef __OLD_TANGO__
-            create_cpp_class(dserver, class_name, par_name);
-#else
-            dserver->_create_cpp_class(class_name, par_name);
-#endif /* __OLD_TANGO__ */
+            char *class_name = extract<char *>(class_info[0]);
+            char *par_name   = extract<char *>(class_info[1]);
+            dserver->create_cpp_class(class_name, par_name);
         }
 
     //
@@ -165,23 +78,33 @@ namespace PyUtil
         for(int i = 0; i < cc_len; ++i)
         {
             CppDeviceClass *cpp_dc = extract<CppDeviceClass *> (constructed_classes[i])();
-            dserver->_add_class(cpp_dc);
+            dserver->add_class(cpp_dc);
         }
     }
 
+#ifdef HERE_OLD_TANGO___
+namespace PyUtil
+{
     void server_init(Tango::Util & instance, bool with_window = false)
     {
         AutoPythonAllowThreads guard;
-        Tango::DServer::register_class_factory(_class_factory);
         instance.server_init(with_window);
     }
+#else
+    void server_init(Tango::Util & instance, bool with_window = false)
+    {
+        AutoPythonAllowThreads guard;
+        instance.set_class_factory_cb(_class_factory);
+        instance.server_init(with_window);
+    }
+#endif
 
     void server_run(Tango::Util & instance)
     {
         AutoPythonAllowThreads guard;
         instance.server_run();
     }
-
+    
     inline Tango::Util* init(boost::python::object &obj)
     {
         PyObject *obj_ptr = obj.ptr();
@@ -315,6 +238,7 @@ void export_util()
             return_value_policy<reference_existing_object>())
         .def("server_init", &PyUtil::server_init, server_init_overload())
         .def("server_run", &PyUtil::server_run)
+        .def("server_cleanup", &Tango::Util::server_cleanup)
         .def("trigger_cmd_polling", &Tango::Util::trigger_cmd_polling)
         .def("trigger_attr_polling", &Tango::Util::trigger_attr_polling)
         .def("set_polling_threads_pool_size", &Tango::Util::set_polling_threads_pool_size)
@@ -334,4 +258,4 @@ void export_util()
         .def("init_python", init_python)
         .staticmethod("init_python")
     ;
-}
+}
\ No newline at end of file
diff --git a/src/server/user_default_attr_prop.cpp b/src/server/user_default_attr_prop.cpp
index 9d16c1f..4365c09 100644
--- a/src/server/user_default_attr_prop.cpp
+++ b/src/server/user_default_attr_prop.cpp
@@ -1,5 +1,5 @@
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 using namespace boost::python;
 
diff --git a/src/server/wattribute.cpp b/src/server/wattribute.cpp
index 61350ce..1a98d22 100644
--- a/src/server/wattribute.cpp
+++ b/src/server/wattribute.cpp
@@ -1,7 +1,7 @@
 #include <boost/python.hpp>
 #include <boost/python/return_value_policy.hpp>
 #include <string>
-#include <tango/tango.h>
+#include <tango.h>
 
 #include "defs.h"
 #include "pytgutils.h"
diff --git a/src/tgutils.h b/src/tgutils.h
index b37e7ab..4070418 100644
--- a/src/tgutils.h
+++ b/src/tgutils.h
@@ -24,7 +24,7 @@
 #pragma once
 
 #include <cassert>
-#include <tango/tango.h>
+#include <tango.h>
 
 namespace Tango
 {
diff --git a/src/time_val.cpp b/src/time_val.cpp
index 5d74b93..8aa6958 100644
--- a/src/time_val.cpp
+++ b/src/time_val.cpp
@@ -22,7 +22,7 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 using namespace boost::python;
 
diff --git a/src/to_py.cpp b/src/to_py.cpp
index a7e6cc3..4de5c07 100644
--- a/src/to_py.cpp
+++ b/src/to_py.cpp
@@ -96,10 +96,13 @@ object to_py(const Tango::EventProperties &event_props)
     return py_event_props;
 }
 
-object to_py(const Tango::AttributeConfig &attr_conf)
+object to_py(const Tango::AttributeConfig &attr_conf, object py_attr_conf)
 {
-    PYTANGO_MOD
-    object py_attr_conf = pytango.attr("AttributeConfig")();
+    if(py_attr_conf.ptr() == Py_None)
+    {
+        PYTANGO_MOD
+        py_attr_conf = pytango.attr("AttributeConfig")();
+    }
     
     py_attr_conf.attr("name") = str(attr_conf.name.in());
     py_attr_conf.attr("writable") = attr_conf.writable;
@@ -124,10 +127,13 @@ object to_py(const Tango::AttributeConfig &attr_conf)
     return py_attr_conf;
 }
 
-object to_py(const Tango::AttributeConfig_2 &attr_conf)
+object to_py(const Tango::AttributeConfig_2 &attr_conf, object py_attr_conf)
 {
-    PYTANGO_MOD
-    object py_attr_conf = pytango.attr("AttributeConfig_2")();
+    if(py_attr_conf.ptr() == Py_None)
+    {
+        PYTANGO_MOD
+        py_attr_conf = pytango.attr("AttributeConfig_2")();
+    }
     
     py_attr_conf.attr("name") = str(attr_conf.name.in());
     py_attr_conf.attr("writable") = attr_conf.writable;
@@ -152,10 +158,13 @@ object to_py(const Tango::AttributeConfig_2 &attr_conf)
     return py_attr_conf;
 }
 
-object to_py(const Tango::AttributeConfig_3 &attr_conf)
+object to_py(const Tango::AttributeConfig_3 &attr_conf, object py_attr_conf)
 {
-    PYTANGO_MOD
-    object py_attr_conf = pytango.attr("AttributeConfig_3")();
+    if(py_attr_conf.ptr() == Py_None)
+    {
+        PYTANGO_MOD
+        py_attr_conf = pytango.attr("AttributeConfig_3")();
+    }
     
     py_attr_conf.attr("name") = str(attr_conf.name.in());
     py_attr_conf.attr("writable") = attr_conf.writable;
@@ -183,10 +192,11 @@ object to_py(const Tango::AttributeConfig_3 &attr_conf)
 boost::python::list to_py(const Tango::AttributeConfigList &attr_conf_list)
 {
     boost::python::list py_attr_conf_list;
+    boost::python::object none;
     for(unsigned long index = 0; index < attr_conf_list.length(); ++index)
     {
         const Tango::AttributeConfig &attr_conf = attr_conf_list[index];
-        py_attr_conf_list.append(to_py(attr_conf));
+        py_attr_conf_list.append(to_py(attr_conf, none));
     }
     return py_attr_conf_list;
 }
@@ -194,10 +204,11 @@ boost::python::list to_py(const Tango::AttributeConfigList &attr_conf_list)
 boost::python::list to_py(const Tango::AttributeConfigList_2 &attr_conf_list)
 {
     boost::python::list py_attr_conf_list;
+    boost::python::object none;
     for(unsigned long index = 0; index < attr_conf_list.length(); ++index)
     {
         const Tango::AttributeConfig_2 &attr_conf = attr_conf_list[index];
-        py_attr_conf_list.append(to_py(attr_conf));
+        py_attr_conf_list.append(to_py(attr_conf, none));
     }
     return py_attr_conf_list;
 }
@@ -205,10 +216,11 @@ boost::python::list to_py(const Tango::AttributeConfigList_2 &attr_conf_list)
 boost::python::list to_py(const Tango::AttributeConfigList_3 &attr_conf_list)
 {
     boost::python::list py_attr_conf_list;
+    boost::python::object none;
     for(unsigned long index = 0; index < attr_conf_list.length(); ++index)
     {
         const Tango::AttributeConfig_3 &attr_conf = attr_conf_list[index];
-        py_attr_conf_list.append(to_py(attr_conf));
+        py_attr_conf_list.append(to_py(attr_conf, none));
     }
     return py_attr_conf_list;
 }
\ No newline at end of file
diff --git a/src/to_py.h b/src/to_py.h
index 323862b..cea2956 100644
--- a/src/to_py.h
+++ b/src/to_py.h
@@ -24,7 +24,7 @@
 #pragma once
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 #include "defs.h"
 
@@ -290,9 +290,12 @@ boost::python::object to_py(const Tango::PeriodicEventProp &);
 boost::python::object to_py(const Tango::ArchiveEventProp &);
 boost::python::object to_py(const Tango::EventProperties &);
 
-boost::python::object to_py(const Tango::AttributeConfig &);
-boost::python::object to_py(const Tango::AttributeConfig_2 &);
-boost::python::object to_py(const Tango::AttributeConfig_3 &);
+boost::python::object to_py(const Tango::AttributeConfig &, 
+                            boost::python::object py_attr_conf);
+boost::python::object to_py(const Tango::AttributeConfig_2 &,
+                            boost::python::object py_attr_conf);
+boost::python::object to_py(const Tango::AttributeConfig_3 &,
+                            boost::python::object py_attr_conf);
 
 boost::python::list to_py(const Tango::AttributeConfigList &);
 boost::python::list to_py(const Tango::AttributeConfigList_2 &);
diff --git a/src/version.cpp b/src/version.cpp
index 1d03029..2afd411 100644
--- a/src/version.cpp
+++ b/src/version.cpp
@@ -22,7 +22,7 @@
 *******************************************************************************/
 
 #include <boost/python.hpp>
-#include <tango/tango.h>
+#include <tango.h>
 
 using namespace boost::python;
 

-- 
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