Commit 1449ba53 authored by oroulet's avatar oroulet Committed by oroulet

revert and fix Variant array

parent 100a711b
......@@ -458,7 +458,7 @@ class NodeManagementService:
def _add_node_attr(self, item, nodedata, name, vtype=None, add_timestamps=False, is_array=False):
if item.SpecifiedAttributes & getattr(ua.NodeAttributesMask, name):
dv = ua.DataValue(
ua.Variant(getattr(item, name), vtype, Dimensions=[0] if is_array else None),
ua.Variant(getattr(item, name), vtype, is_array=is_array),
SourceTimestamp=datetime.utcnow() if add_timestamps else None,
)
nodedata.attributes[getattr(ua.AttributeIds, name)] = AttributeValue(dv)
......
......@@ -434,19 +434,20 @@ def variant_to_binary(var):
def variant_from_binary(data):
dimensions = None
array = False
encoding = ord(data.read(1))
int_type = encoding & 0b00111111
vtype = ua.datatype_to_varianttype(int_type)
if test_bit(encoding, 7):
value = unpack_uatype_array(vtype, data)
dimensions = [0]
array = True
else:
value = unpack_uatype(vtype, data)
if test_bit(encoding, 6):
dimensions = unpack_uatype_array(ua.VariantType.Int32, data)
if value is not None:
value = _reshape(value, dimensions)
return ua.Variant(value, vtype, dimensions)
return ua.Variant(value, vtype, dimensions, is_array=array)
def _reshape(flat, dims):
......
......@@ -3,7 +3,7 @@ implement ua datatypes
"""
import sys
from typing import Optional, Any, Union, Generic
from typing import Optional, Any, Union, Generic, List
import collections
import logging
from enum import Enum, IntEnum
......@@ -780,22 +780,29 @@ class Variant:
:ivar VariantType:
:vartype VariantType: VariantType
:ivar Dimension:
:vartype Dimensions: The length of each dimensions. Usually guessed from value. [0] mean 1D array without length limit
:vartype Dimensions: The length of each dimensions. Make the variant a Matrix
:ivar is_array:
:vartype is_array: If the variant is an array. Always True if Dimension is specificied
"""
# FIXME: typing is wrong here
Value: Any = None
VariantType: VariantType = None
Dimensions: Optional[Int32] = None
Dimensions: Optional[List[Int32]] = None
is_array: Optional[bool] = None
def __post_init__(self):
if self.is_array is None:
if isinstance(self.Value, (list, tuple)) or self.Dimensions :
object.__setattr__(self, "is_array", True)
else:
object.__setattr__(self, "is_array", False)
if isinstance(self.Value, Variant):
object.__setattr__(self, "VariantType", self.Value.VariantType)
object.__setattr__(self, "Value", self.Value.Value)
if self.Dimensions is None and isinstance(self.Value, (list, tuple)):
dims = get_shape(self.Value)
object.__setattr__(self, "Dimensions", dims)
if not isinstance(self.VariantType, (VariantType, VariantTypeCustom)):
if self.VariantType is None:
object.__setattr__(self, "VariantType", self._guess_type(self.Value))
......@@ -820,9 +827,10 @@ class Variant:
f"Non array Variant of type {self.VariantType} cannot have value None"
)
@property
def is_array(self):
return self.Dimensions is not None
if self.Dimensions is None and isinstance(self.Value, (list, tuple)):
dims = get_shape(self.Value)
if len(dims) > 1:
object.__setattr__(self, "Dimensions", dims)
def __eq__(self, other):
if (
......
......@@ -30,35 +30,44 @@ EXAMPLE_BSD_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), "exam
def test_variant_array_none():
v = ua.Variant(None, VariantType=ua.VariantType.Int32, Dimensions=[0])
v = ua.Variant(None, VariantType=ua.VariantType.Int32, is_array=True)
data = variant_to_binary(v)
v2 = variant_from_binary(ua.utils.Buffer(data))
assert v == v2
assert v2.is_array
assert v2.Dimensions == [0]
assert v2.Dimensions is None
v = ua.Variant(None, VariantType=ua.VariantType.Null, Dimensions=[0])
v = ua.Variant(None, VariantType=ua.VariantType.Null, is_array=True)
data = variant_to_binary(v)
v2 = variant_from_binary(ua.utils.Buffer(data))
assert v == v2
assert v2.is_array
assert v2.Dimensions == [0]
assert v2.Dimensions is None
v = ua.Variant(None, VariantType=ua.VariantType.Null, Dimensions=None)
v = ua.Variant(None, VariantType=ua.VariantType.Null, Dimensions=[0, 0])
data = variant_to_binary(v)
v2 = variant_from_binary(ua.utils.Buffer(data))
assert v == v2
assert not v2.is_array
assert v2.Dimensions == None
assert v2.is_array
assert v2.Dimensions == [0, 0]
def test_variant_empty_list():
v = ua.Variant([], VariantType=ua.VariantType.Int32, Dimensions=[0])
v = ua.Variant([], VariantType=ua.VariantType.Int32, is_array=True)
data = variant_to_binary(v)
v2 = variant_from_binary(ua.utils.Buffer(data))
assert v == v2
assert v2.is_array
assert v2.Dimensions is None
v = ua.Variant([], VariantType=ua.VariantType.Int32, is_array=True, Dimensions=[0])
data = variant_to_binary(v)
v2 = variant_from_binary(ua.utils.Buffer(data))
assert v == v2
assert v2.is_array
assert v2.Dimensions == [0]
def test_custom_structs(tmpdir):
......@@ -602,6 +611,7 @@ def test_variant_array():
v2 = variant_from_binary(ua.utils.Buffer(variant_to_binary(v)))
assert v.Value == v2.Value
assert v.VariantType == v2.VariantType
assert v2.Dimensions is None
now = datetime.utcnow()
v = ua.Variant([now])
......@@ -610,12 +620,16 @@ def test_variant_array():
v2 = variant_from_binary(ua.utils.Buffer(variant_to_binary(v)))
assert v.Value == v2.Value
assert v.VariantType == v2.VariantType
assert v2.Dimensions is None
def test_variant_array_dim():
v = ua.Variant([1, 2, 3, 4, 5, 6], Dimensions=[2, 3])
assert v.Value[1] == 2
assert v.Dimensions == [2, 3]
v2 = variant_from_binary(ua.utils.Buffer(variant_to_binary(v)))
assert _reshape(v.Value, (2, 3)) == v2.Value
assert v.VariantType == v2.VariantType
assert v.Dimensions == v2.Dimensions
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment