Source code for PyPlcnextRsc.common.objects.rsc_variant

# Copyright (c) 2021 Phoenix Contact. All rights reserved.
# Licensed under the MIT. See LICENSE file in the project root for full license information.
from PyPlcnextRsc.common.exceptions import InvalidOperationException
from PyPlcnextRsc.common.objects import RscStructMeta, RscStructBuilder, RscSequence, isRscStructInstance
from PyPlcnextRsc.common.tag_type import RscType
from PyPlcnextRsc.common.types.rsc_types import RscTpIntEnum

__all__ = [
    'RscVariant'
]

from PyPlcnextRsc.common.serviceDefinition.marshal import Marshal


[docs]class RscVariant: """ This is used to represent an data-object (py-value with its' RscType) Create a RscVariant object by providing both the definite :py:class:`~PyPlcnextRsc.common.tag_type.RscType` and python value :param value: Python value which to be wrapped in. :param rscType: the definite type of the value. .. note:: If you are just make RscVariant object mapped to *IEC61131*, use :py:class:`~PyPlcnextRsc.common.tag_type.IecType` is more concrete :type rscType: :py:class:`~PyPlcnextRsc.common.tag_type.RscType` """ def __class_getitem__(cls, item): """ for Annotation """ if type(item) == int: from PyPlcnextRsc.common.types import RscTpAnnotate return RscTpAnnotate[cls, Marshal(maxStringSize=item)] else: raise ValueError()
[docs] @classmethod def of(cls, value): """ Create RscVariant from some special python object that :py:class:`~PyPlcnextRsc.common.tag_type.RscType` is clearly to tell from .. warning:: This is not suitable for some value that is ambiguous , for example you give number 100 use this method, but for this method it is not possible to know which `INT` (or in other word, which :py:class:`~PyPlcnextRsc.common.tag_type.RscType`)you are talking about: it shell be :py:const:`PyPlcnextRsc.common.tag_type.RscType.Uint8` ? :py:const:`PyPlcnextRsc.common.tag_type.RscType.Int16` ? or :py:const:`PyPlcnextRsc.common.tag_type.RscType.Int64` ...? So in this case, you must use :py:func:`~PyPlcnextRsc.common.objects.rsc_variant.RscVariant.__init__` to give the :py:class:`~PyPlcnextRsc.common.tag_type.RscType` explicitly. - bool value : the :py:const:`PyPlcnextRsc.common.tag_type.RscType.Bool` will be filled - str value : the :py:const:`PyPlcnextRsc.common.tag_type.RscType.Utf8String` will be filled - :py:class:`~PyPlcnextRsc.common.objects.rsc_sequence.RscTuple` or :py:class:`~PyPlcnextRsc.common.objects.rsc_sequence.RscList` : the :py:const:`PyPlcnextRsc.common.tag_type.RscType.Array` will be filled - :py:class:`~PyPlcnextRsc.common.objects.rsc_struct.RscStructMeta` or :py:class:`~PyPlcnextRsc.common.objects.rsc_struct.RscStructBuilder` :the :py:const:`PyPlcnextRsc.common.tag_type.RscType.Struct` will be filled :return: RscVariant instance """ _type = type(value) if _type == bool: return cls(value, RscType.Bool) elif _type == str: return cls(value, RscType.Utf8String) elif isinstance(value, RscSequence): return cls(value, RscType.Array) elif isinstance(value, RscStructMeta): return cls(value, RscType.Struct) elif isRscStructInstance(value) or isinstance(value, RscStructBuilder): return cls(RscStructMeta.fromInstance(value), rscType=RscType.Struct) # TODO ... else: raise InvalidOperationException("Use __init__ to create RscVariant with its' RscType instead !")
@classmethod def ofEnum(cls, item): if not isinstance(item, RscTpIntEnum): raise InvalidOperationException("Use __init__ to create RscVariant with its' RscType instead !") from PyPlcnextRsc.common.transport.rsc_datatag_ctx import _GetMarshalFromEnum _t = type(item) return cls(item.value, rscType=_GetMarshalFromEnum(_t).rscType) def __init__(self, value, rscType: RscType): self._type = rscType self._value = value def __repr__(self): return f"Variant<{self._type.name}>({str(self._value)})" __str__ = __repr__
[docs] def GetValue(self) -> any: """ Get the python value in this RscVariant object. :return: any python value that represent the corresponding value from PLC .. note:: Special case of :py:class:`~PyPlcnextRsc.common.tag_type.RscType` - :py:const:`PyPlcnextRsc.common.tag_type.RscType.Array` : the value type might be :py:class:`~PyPlcnextRsc.common.objects.rsc_sequence.RscList` - :py:const:`PyPlcnextRsc.common.tag_type.RscType.Struct`: the value type might be :py:class:`~PyPlcnextRsc.common.objects.rsc_struct.RscStructMeta` """ return self._value
# def GetValueAsEnum(self,enum): # # TODO
[docs] def GetType(self) -> RscType: """ Get the :py:class:`~PyPlcnextRsc.common.tag_type.RscType` corresponding to the contained value. :rtype: RscType """ return self._type
[docs] def GetArrayElementCtx(self): """This method is mainly for internal use, to get the element context while this object contains *Array*""" if self._type == RscType.Array: if isinstance(self._value, RscSequence): return self._value.getElementContext() else: raise InvalidOperationException("only array type value ( RscList or RscTuple ) support, but is " + str(self._value)) else: raise InvalidOperationException("only array type support , but is " + str(self._type))
[docs] def GetFieldCount(self): """This method is mainly for internal use, to get the field counts while this object contain *Struct*""" if self._type == RscType.Struct: if isinstance(self._value, RscStructMeta): return len(self._value) else: raise InvalidOperationException("only struct type value ( RscStructMeta ) support, but is " + str(self._value)) else: raise InvalidOperationException("only struct type support , but is " + str(self._type))
def __eq__(self, other): if type(other) == RscVariant: return self.GetType() == other.GetType() and self.GetValue() == other.GetValue() else: return False