Adapt pyosaf to support python3, and be compatible with python2 --- python/pyosaf/saAis.py | 51 +++++++++++++++++++++++---- python/pyosaf/saAmf.py | 8 +++-- python/pyosaf/saImm.py | 4 ++- python/pyosaf/saLog.py | 4 ++- python/pyosaf/utils/immoi/agent.py | 2 +- python/pyosaf/utils/immom/accessor.py | 10 +++--- python/pyosaf/utils/immom/agent.py | 11 +++--- python/pyosaf/utils/immom/ccb.py | 19 +++++----- python/pyosaf/utils/immom/iterator.py | 9 ++--- python/pyosaf/utils/immom/object.py | 2 +- python/pyosaf/utils/ntf/producer.py | 24 +++++++------ src/imm/tools/immxml-merge | 32 ++++++++++++----- 12 files changed, 123 insertions(+), 53 deletions(-)
diff --git a/python/pyosaf/saAis.py b/python/pyosaf/saAis.py index 178ea554c..912523e69 100644 --- a/python/pyosaf/saAis.py +++ b/python/pyosaf/saAis.py @@ -18,13 +18,15 @@ ''' Common types and prototypes used by all modules in pyosaf ''' +import sys from os import environ - import ctypes from ctypes import pointer, POINTER, cast, byref, c_void_p, Structure, \ Union, CDLL from pyosaf.saEnumConst import Enumeration, Const +PY3 = True if sys.version_info[0] == 3 else False + SaInt8T = ctypes.c_char SaInt16T = ctypes.c_short SaInt32T = ctypes.c_int @@ -39,7 +41,21 @@ SaVoidPtr = c_void_p # Types used by the NTF/IMMS service SaFloatT = ctypes.c_float SaDoubleT = ctypes.c_double -SaStringT = ctypes.c_char_p +if PY3: + class SaStringT(ctypes.c_char_p): + def __init__(self, value=''): + if value is not None: + value = value.encode('utf-8') + super(SaStringT, self).__init__(value) + + def __str__(self): + if self.value is not None: + return self.value.decode('utf-8') + else: + return self.__repr__() +else: + SaStringT = ctypes.c_char_p + SaTimeT = SaInt64T SaInvocationT = SaUint64T @@ -177,6 +193,12 @@ if environ.get('SA_ENABLE_EXTENDED_NAMES') == '1': immdll.saAisNameLend.argtypes = [SaConstStringT, POINTER(SaNameT)] immdll.saAisNameLend.restype = None + if PY3: + # Add name_in_bytes attribute to this object as a workaround + # To keep the `name` in bytes not to be freed by garbarge + # collector when it's still refered in `_opaque` of SaNameT + self.name_in_bytes = name.encode('utf-8') + name = self.name_in_bytes immdll.saAisNameLend(name, BYREF(self)) @@ -185,7 +207,11 @@ if environ.get('SA_ENABLE_EXTENDED_NAMES') == '1': """ immdll.saAisNameBorrow.argtypes = [POINTER(SaNameT)] immdll.saAisNameBorrow.restype = SaConstStringT - return immdll.saAisNameBorrow(BYREF(self)) + name = immdll.saAisNameBorrow(BYREF(self)) + if PY3: + return name.decode('utf-8') + + return name else: class SaNameT(Structure): """Contain names. @@ -196,12 +222,17 @@ else: def __init__(self, name=''): """Construct instance with contents of 'name'. """ + if PY3: + name = name.encode('utf-8') super(SaNameT, self).__init__(len(name), name) def __str__(self): """Returns the content of SaNameT """ - return self.value + if PY3: + return self.value.decode('utf-8') + else: + return self.value class SaVersionT(Structure): @@ -211,6 +242,14 @@ class SaVersionT(Structure): ('majorVersion', SaUint8T), ('minorVersion', SaUint8T)] + def __init__(self, release='_', major=0, minor=0): + """Construct instance with contents of 'name'. + """ + if PY3: + release = release[0].encode('utf-8') + + super(SaVersionT, self).__init__(release, major, minor) + class SaLimitValueT(Union): """Contain the value of an implementation-specific limit. @@ -259,7 +298,7 @@ def unmarshalNullArray(c_array): if not c_array: return [] ctype = c_array[0].__class__ - if ctype is str: + if ctype is str or (PY3 and ctype is SaStringT): return unmarshalSaStringTArray(c_array) val_list = [] for ptr in c_array: @@ -278,7 +317,7 @@ def unmarshalSaStringTArray(c_array): for ptr in c_array: if not ptr: break - val_list.append(ptr) + val_list.append(str(ptr)) return val_list diff --git a/python/pyosaf/saAmf.py b/python/pyosaf/saAmf.py index 5d2fca628..ff9265d22 100644 --- a/python/pyosaf/saAmf.py +++ b/python/pyosaf/saAmf.py @@ -19,7 +19,7 @@ from ctypes import POINTER, Structure, CFUNCTYPE, CDLL, Union from pyosaf.saAis import SaAisErrorT, SaInvocationT, SaNameT, SaUint64T, \ SaUint32T, SaTimeT, SaUint8T, SaInt64T, SaInt32T, SaDispatchFlagsT, \ SaVersionT, SaSelectionObjectT, SaEnumT, Enumeration, SaInt8T, \ - SaUint16T, Const, BYREF + SaUint16T, Const, BYREF, PY3 from pyosaf.saNtf import SaNtfIdentifierT, SaNtfCorrelationIdsT # Only mirrors API calls implemented in osaf/libs/agents/saf/ava/ava_api.c @@ -61,7 +61,11 @@ class SaAmfHealthcheckKeyT(Structure): def __init__(self, key=''): """Construct instance with contents of 'key'. """ - super(SaAmfHealthcheckKeyT, self).__init__(key, len(key)) + if PY3: + key = key.encode('utf-8') + super(SaAmfHealthcheckKeyT, self).__init__(key, len(key)) + else: + super(SaAmfHealthcheckKeyT, self).__init__(key, len(key)) SaAmfHAStateT = SaEnumT eSaAmfHAStateT = Enumeration(( diff --git a/python/pyosaf/saImm.py b/python/pyosaf/saImm.py index e464dc17e..f167a4e4f 100644 --- a/python/pyosaf/saImm.py +++ b/python/pyosaf/saImm.py @@ -24,7 +24,7 @@ from ctypes import cast, pointer, POINTER, Structure, Union from pyosaf.saAis import SaStringT, SaEnumT, SaInt32T, SaUint32T, SaInt64T, \ SaUint64T, SaTimeT, SaNameT, SaFloatT, SaDoubleT, SaStringT, SaAnyT from pyosaf.saEnumConst import Enumeration, Const -from pyosaf.saAis import SaVoidPtr +from pyosaf.saAis import SaVoidPtr, PY3 saImm = Const() @@ -72,6 +72,8 @@ def unmarshalSaImmValue(void_ptr, value_type): if val_ptr and void_ptr: if val_ptr == SaNameT: return str(cast(void_ptr, POINTER(val_ptr))[0]) + elif val_ptr == SaStringT and PY3: + return str(cast(void_ptr, POINTER(val_ptr))[0]) return cast(void_ptr, POINTER(val_ptr))[0] return None diff --git a/python/pyosaf/saLog.py b/python/pyosaf/saLog.py index ad24b219b..039a47d4a 100644 --- a/python/pyosaf/saLog.py +++ b/python/pyosaf/saLog.py @@ -20,7 +20,7 @@ from ctypes import POINTER, CDLL, Structure, CFUNCTYPE, create_string_buffer, \ from pyosaf.saAis import SaUint64T, Const, SaUint16T, SaVersionT, SaStringT, \ SaUint32T, SaBoolT, SaEnumT, Enumeration, SaInvocationT, SaAisErrorT, \ BYREF, SaDispatchFlagsT, SaNameT, SaTimeT, SaSelectionObjectT, \ - SaUint8T, SaSizeT, SaInt8T, SaLimitValueT + SaUint8T, SaSizeT, SaInt8T, SaLimitValueT, PY3 from pyosaf import saNtf # Only mirrors API calls implemented in osaf/libs/agents/saf/lga/lga_api.c @@ -66,6 +66,8 @@ class SaLogBufferT(Structure): _fields_ = [('logBufSize', SaSizeT), ('logBuf', POINTER(SaInt8T))] def __init__(self, buf=''): + if PY3: + buf = buf.encode('utf-8') super(SaLogBufferT, self).__init__(len(buf), create_string_buffer(buf) if buf else None) diff --git a/python/pyosaf/utils/immoi/agent.py b/python/pyosaf/utils/immoi/agent.py index 74bd1330d..e0697b1ef 100644 --- a/python/pyosaf/utils/immoi/agent.py +++ b/python/pyosaf/utils/immoi/agent.py @@ -356,7 +356,7 @@ class OiAgent(object): """ _, class_desc = self.imm_om.get_class_description(class_name) attr_desc = [attr for attr in class_desc if - attr.attrName == attribute][0] + str(attr.attrName) == attribute][0] return attr_desc.attrValueType diff --git a/python/pyosaf/utils/immom/accessor.py b/python/pyosaf/utils/immom/accessor.py index bed08d5fa..93ed84c85 100644 --- a/python/pyosaf/utils/immom/accessor.py +++ b/python/pyosaf/utils/immom/accessor.py @@ -121,11 +121,11 @@ class ImmOmAccessor(agent.OmAgentManager): attr_list = unmarshalNullArray(attributes) for attr in attr_list: attr_range = list(range(attr.attrValuesNumber)) - attrs[attr.attrName] = [attr.attrValueType, - [unmarshalSaImmValue( - attr.attrValues[val], - attr.attrValueType) - for val in attr_range]] + attrs[str(attr.attrName)] = [ + attr.attrValueType, + [unmarshalSaImmValue(attr.attrValues[val], + attr.attrValueType) + for val in attr_range]] if 'SaImmAttrClassName' not in attrs and class_name: attrs['SaImmAttrClassName'] = class_name imm_obj = ImmObject(dn=object_name, attributes=attrs) diff --git a/python/pyosaf/utils/immom/agent.py b/python/pyosaf/utils/immom/agent.py index dc91fc6ea..0413f1bd1 100644 --- a/python/pyosaf/utils/immom/agent.py +++ b/python/pyosaf/utils/immom/agent.py @@ -23,7 +23,7 @@ from ctypes import pointer from pyosaf import saImmOm, saImm from pyosaf.saAis import saAis, SaVersionT, SaNameT, SaAisErrorT, \ eSaAisErrorT, eSaBoolT, unmarshalNullArray -from pyosaf.saImm import eSaImmScopeT +from pyosaf.saImm import eSaImmScopeT, SaImmClassNameT, SaImmAttrNameT from pyosaf.utils import decorate, initialize_decorate, log_err # Decorate pure saImmOm* API's with error-handling retry and exception raising @@ -211,7 +211,8 @@ class ImmOmAgent(OmAgentManager): def attr_def_copy(attr_def): """ Deep copy attributes """ attr_def_cpy = saImm.SaImmAttrDefinitionT_2() - attr_def_cpy.attrName = attr_def.attrName[:] + attr_def_cpy.attrName = SaImmAttrNameT( + deepcopy(str(attr_def.attrName))) attr_def_cpy.attrValueType = attr_def.attrValueType attr_def_cpy.attrFlags = attr_def.attrFlags @@ -220,7 +221,9 @@ class ImmOmAgent(OmAgentManager): class_attrs = [] attr_defs = pointer(pointer(saImm.SaImmAttrDefinitionT_2())) category = saImm.SaImmClassCategoryT() - rc = saImmOmClassDescriptionGet_2(self.handle, class_name, category, + rc = saImmOmClassDescriptionGet_2(self.handle, + SaImmClassNameT(class_name), + category, attr_defs) if rc != eSaAisErrorT.SA_AIS_OK: log_err("saImmOmClassDescriptionGet_2 FAILED - %s" % @@ -253,7 +256,7 @@ class ImmOmAgent(OmAgentManager): else: for attr_desc in class_attrs: if attr_desc.attrFlags & saImm.saImm.SA_IMM_ATTR_RDN: - return attr_desc.attrName + return str(attr_desc.attrName) def invoke_admin_operation(self, dn, op_id, params=None): """ Invoke admin op for dn diff --git a/python/pyosaf/utils/immom/ccb.py b/python/pyosaf/utils/immom/ccb.py index 8edd526b1..a23f777d3 100644 --- a/python/pyosaf/utils/immom/ccb.py +++ b/python/pyosaf/utils/immom/ccb.py @@ -22,7 +22,8 @@ from ctypes import c_void_p, pointer, cast, POINTER from pyosaf.saAis import eSaAisErrorT, SaNameT, SaStringT, SaFloatT, \ unmarshalNullArray, SaDoubleT, SaTimeT, SaUint64T, SaInt64T, SaUint32T, \ SaInt32T -from pyosaf.saImm import eSaImmScopeT, eSaImmValueTypeT, SaImmAttrValuesT_2 +from pyosaf.saImm import eSaImmScopeT, eSaImmValueTypeT, SaImmAttrValuesT_2, \ + SaImmAttrNameT, SaImmClassNameT from pyosaf import saImm from pyosaf import saImmOm from pyosaf.utils.immom import agent @@ -44,13 +45,13 @@ def _value_to_ctype_ptr(value_type, value): if value_type is eSaImmValueTypeT.SA_IMM_ATTR_SAINT32T: ctypeptr = cast(pointer(SaInt32T(value)), c_void_p) elif value_type is eSaImmValueTypeT.SA_IMM_ATTR_SAUINT32T: - ctypeptr = cast(pointer(SaUint32T(long(value))), c_void_p) + ctypeptr = cast(pointer(SaUint32T(value)), c_void_p) elif value_type is eSaImmValueTypeT.SA_IMM_ATTR_SAINT64T: - ctypeptr = cast(pointer(SaInt64T(long(value))), c_void_p) + ctypeptr = cast(pointer(SaInt64T(value)), c_void_p) elif value_type is eSaImmValueTypeT.SA_IMM_ATTR_SAUINT64T: - ctypeptr = cast(pointer(SaUint64T(long(value))), c_void_p) + ctypeptr = cast(pointer(SaUint64T(value)), c_void_p) elif value_type is eSaImmValueTypeT.SA_IMM_ATTR_SATIMET: - ctypeptr = cast(pointer(SaTimeT(long(value))), c_void_p) + ctypeptr = cast(pointer(SaTimeT(value)), c_void_p) elif value_type is eSaImmValueTypeT.SA_IMM_ATTR_SANAMET: ctypeptr = cast(pointer(SaNameT(value)), c_void_p) elif value_type is eSaImmValueTypeT.SA_IMM_ATTR_SAFLOATT: @@ -172,7 +173,7 @@ class Ccb(ImmOmAgent): for attr_name, type_values in obj.attrs.items(): values = type_values[1] attr = SaImmAttrValuesT_2() - attr.attrName = attr_name + attr.attrName = SaImmAttrNameT(attr_name) attr.attrValueType = type_values[0] attr.attrValuesNumber = len(values) @@ -180,7 +181,7 @@ class Ccb(ImmOmAgent): attr_values.append(attr) rc = agent.saImmOmCcbObjectCreate_2(self.ccb_handle, - obj.class_name, + SaImmClassNameT(obj.class_name), parent_name, attr_values) if rc != eSaAisErrorT.SA_AIS_OK: @@ -255,7 +256,7 @@ class Ccb(ImmOmAgent): _, attr_def_list = self.get_class_description(class_name) value_type = None for attr_def in attr_def_list: - if attr_def.attrName == attr_name: + if str(attr_def.attrName) == attr_name: value_type = attr_def.attrValueType break if value_type: @@ -271,7 +272,7 @@ class Ccb(ImmOmAgent): attr_mod = saImmOm.SaImmAttrModificationT_2() attr_mod.modType = mod_type attr_mod.modAttr = SaImmAttrValuesT_2() - attr_mod.modAttr.attrName = attr_name + attr_mod.modAttr.attrName = SaImmAttrNameT(attr_name) attr_mod.modAttr.attrValueType = value_type attr_mod.modAttr.attrValuesNumber = len(values) attr_mod.modAttr.attrValues = marshal_c_array(value_type, diff --git a/python/pyosaf/utils/immom/iterator.py b/python/pyosaf/utils/immom/iterator.py index 7402c9427..91c5751c0 100644 --- a/python/pyosaf/utils/immom/iterator.py +++ b/python/pyosaf/utils/immom/iterator.py @@ -105,10 +105,11 @@ class SearchIterator(agent.OmAgentManager, Iterator): attr_list = unmarshalNullArray(attributes) for attr in attr_list: attr_range = list(range(attr.attrValuesNumber)) - attrs[attr.attrName] = [attr.attrValueType, - [unmarshalSaImmValue(attr.attrValues[val], - attr.attrValueType) - for val in attr_range]] + attrs[str(attr.attrName)] = [ + attr.attrValueType, + [unmarshalSaImmValue(attr.attrValues[val], + attr.attrValueType) + for val in attr_range]] return ImmObject(str(obj_name), attrs) @bad_handle_retry diff --git a/python/pyosaf/utils/immom/object.py b/python/pyosaf/utils/immom/object.py index 0cef920cc..6e80abfae 100644 --- a/python/pyosaf/utils/immom/object.py +++ b/python/pyosaf/utils/immom/object.py @@ -82,7 +82,7 @@ class ImmObject(object): SaImmAttrNameT: Attribute value type """ for attr_def in self.class_desc[self.class_name]: - if attr_def.attrName == attr_name: + if str(attr_def.attrName) == attr_name: return attr_def.attrValueType def __attr_is_multi_value(self, attr_name): diff --git a/python/pyosaf/utils/ntf/producer.py b/python/pyosaf/utils/ntf/producer.py index 1d5422536..b9a0ebf9e 100644 --- a/python/pyosaf/utils/ntf/producer.py +++ b/python/pyosaf/utils/ntf/producer.py @@ -19,7 +19,8 @@ import ctypes from pyosaf import saNtf -from pyosaf.saAis import eSaBoolT, eSaAisErrorT, SaVoidPtr +from pyosaf.saNtf import eSaNtfValueTypeT +from pyosaf.saAis import eSaBoolT, eSaAisErrorT, SaVoidPtr, SaNameT, PY3 from pyosaf.utils import log_warn, log_err, bad_handle_retry from pyosaf.utils.ntf import agent as ntf @@ -87,6 +88,8 @@ class NtfProducer(ntf.NtfAgent): elif value_type == saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_LDAP_NAME \ or value_type == saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_STRING \ or value_type == saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_IPADDRESS: + if PY3: + value = value.encode('utf-8') len_value = len(value) dest_ptr = SaVoidPtr() rc = ntf.saNtfPtrValAllocate(ntf_handle, len_value + 1, dest_ptr, @@ -300,14 +303,10 @@ class NtfProducer(ntf.NtfAgent): """ header.eventType.contents.value = self.ntf_info.event_type - header.notificationObject.contents.value = \ - self.ntf_info.notification_object - header.notificationObject.contents.length = \ - len(self.ntf_info.notification_object) + header.notificationObject[0] = \ + SaNameT(self.ntf_info.notification_object) - header.notifyingObject.contents.value = self.ntf_info.notifying_object - header.notifyingObject.contents.length = \ - len(self.ntf_info.notifying_object) + header.notifyingObject[0] = SaNameT(self.ntf_info.notifying_object) header.notificationClassId.contents.vendorId = \ self.ntf_info.ntf_class_id.vendorId @@ -318,10 +317,13 @@ class NtfProducer(ntf.NtfAgent): header.eventTime.contents.value = self.ntf_info.event_time - header.lengthAdditionalText = len(self.ntf_info.additional_text) + additional_text = self.ntf_info.additional_text + if PY3: + additional_text = self.ntf_info.additional_text.encode('utf-8') + header.lengthAdditionalText = len(additional_text) ctypes.memmove(header.additionalText, - self.ntf_info.additional_text, - len(self.ntf_info.additional_text) + 1) + additional_text, + len(additional_text) + 1) if self.ntf_info.additional_info: for i, add_info in enumerate(self.ntf_info.additional_info): diff --git a/src/imm/tools/immxml-merge b/src/imm/tools/immxml-merge index 3a9edda9b..9a03d3a9b 100755 --- a/src/imm/tools/immxml-merge +++ b/src/imm/tools/immxml-merge @@ -28,9 +28,19 @@ from datetime import datetime from baseimm import BaseOptions, BaseImmDocument, trace, retrieve_file_names, \ print_info_stderr, abort_script, verify_input_file_read_access +PY3 = True if sys.version_info[0] == 3 else False + + +def bytes_to_str(bytes_obj, encoding): + """ Convert bytes object to string in python3 """ + if PY3 and isinstance(bytes_obj, bytes): + return bytes_obj.decode(encoding) + + return bytes_obj + class Options(BaseOptions): - """ immxml-merge options""" + """ immxml-merge options """ keepCommentElements = False ignoreVariants = False ignoreMissingClass = False @@ -366,19 +376,25 @@ class MergedImmDocument(BaseImmDocument): heading = "<?xml version=\"1.0\"?>" file_object.write(heading) - file_object.write( - self.imm_content_element.toxml(encoding).replace("/>", ">") + "\n") + string = bytes_to_str(self.imm_content_element.toxml(encoding), + encoding) + file_object.write(string.replace("/>", ">") + "\n") for class_element_tuple in self.classList: if Options.keepCommentElements: for textNode in class_element_tuple[1][0]: - file_object.write(textNode.toxml(encoding) + "\n") - file_object.write(class_element_tuple[1][1].toxml(encoding) + "\n") + string = bytes_to_str(textNode.toxml(encoding), encoding) + file_object.write(string + "\n") + string = bytes_to_str(class_element_tuple[1][1].toxml(encoding), + encoding) + file_object.write(string + "\n") for object_element_tuple in self.objectList: if Options.keepCommentElements: for textNode in object_element_tuple[1][0]: - file_object.write(textNode.toxml(encoding) + "\n") - file_object.write( - object_element_tuple[1][1].toxml(encoding) + "\n") + string = bytes_to_str(textNode.toxml(encoding), encoding) + file_object.write(string + "\n") + string = bytes_to_str(object_element_tuple[1][1].toxml(encoding), + encoding) + file_object.write(string + "\n") file_object.write("</imm:IMM-contents>") file_object.close() trace("Stored resulting xml document in tmp file: %s", -- 2.17.1 _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel