1
0
mirror of https://github.com/JoelBender/bacpypes synced 2025-09-28 22:15:23 +08:00
This commit is contained in:
Joel Bender 2018-08-11 13:53:40 -04:00
parent 200a9321db
commit 48cc40deae
9 changed files with 423 additions and 79 deletions

View File

@ -2365,7 +2365,9 @@ class PriorityValue(Choice):
, Element('datetime', DateTime, 1)
]
class PriorityArray(ArrayOf(PriorityValue)):
class PriorityArray(ArrayOf(
PriorityValue, fixed_length=16, prototype=PriorityValue(null=()),
)):
pass
class PropertyAccessResultAccessResult(Choice):

View File

@ -5,6 +5,7 @@ Constructed Data
"""
import sys
from copy import deepcopy as _deepcopy
from .errors import DecodingError, \
MissingRequiredParameter, InvalidParameterDatatype, InvalidTag
@ -677,7 +678,7 @@ def ListOf(klass):
# return this new type
return _ListOf
@bacpypes_debugging(ListOf)
bacpypes_debugging(ListOf)
#
# Array
@ -696,15 +697,33 @@ class Array(object):
_array_of_map = {}
_array_of_classes = {}
def ArrayOf(klass):
def ArrayOf(klass, fixed_length=None, prototype=None):
"""Function to return a class that can encode and decode a list of
some other type."""
global _array_of_map
global _array_of_classes, _sequence_of_classes
# check the parameters for consistency
if issubclass(klass, Atomic):
if prototype is None:
pass
elif not klass.is_valid(prototype):
raise ValueError("prototype %r not valid for %s" % (prototype, klass.__name__))
else:
if prototype is None:
### TODO This should be an error, a prototype should always be
### required for non-atomic types, even if it's only klass()
### for a default object which will be deep copied
pass
elif not isinstance(prototype, klass):
raise ValueError("prototype %r not valid for %s" % (prototype, klass.__name__))
# build a signature of the parameters
array_signature = (klass, fixed_length, prototype)
# if this has already been built, return the cached one
if klass in _array_of_map:
return _array_of_map[klass]
if array_signature in _array_of_map:
return _array_of_map[array_signature]
# no ArrayOf(ArrayOf(...)) allowed
if klass in _array_of_classes:
@ -717,23 +736,60 @@ def ArrayOf(klass):
class ArrayOf(Array):
subtype = None
fixed_length = None
prototype = None
def __init__(self, value=None):
if value is None:
self.value = [0]
if self.fixed_length is not None:
self.fix_length(self.fixed_length)
elif isinstance(value, list):
if (self.fixed_length is not None) and (len(value) != self.fixed_length):
raise ValueError("invalid array length")
self.value = [len(value)]
self.value.extend(value)
else:
raise TypeError("invalid constructor datatype")
def fix_length(self, new_length):
if len(self.value) > new_length + 1:
# trim off the excess
del self.value[new_length + 1:]
elif len(self.value) < new_length + 1:
# how many do we need
element_count = new_length - len(self.value) + 1
# extend or append
if issubclass(self.subtype, Atomic):
if self.prototype is None:
extend_value = self.subtype().value
else:
extend_value = self.prototype
self.value.extend( [extend_value] * element_count )
else:
for i in range(element_count):
if self.prototype is None:
append_value = self.subtype()
else:
append_value = _deepcopy(self.prototype)
self.value.append(append_value)
self.value[0] = new_length
def append(self, value):
if self.fixed_length is not None:
raise TypeError("fixed length array")
if issubclass(self.subtype, Atomic):
pass
elif issubclass(self.subtype, AnyAtomic) and not isinstance(value, Atomic):
raise TypeError("instance of an atomic type required")
elif not isinstance(value, self.subtype):
raise TypeError("%s value required" % (self.subtype.__name__,))
self.value.append(value)
self.value[0] = len(self.value) - 1
@ -754,23 +810,19 @@ def ArrayOf(klass):
# special length handling for index 0
if item == 0:
if value < self.value[0]:
# trim
self.value = self.value[0:value + 1]
elif value > self.value[0]:
# extend
if issubclass(self.subtype, Atomic):
self.value.extend( [self.subtype().value] * (value - self.value[0]) )
else:
for i in range(value - self.value[0]):
self.value.append(self.subtype())
else:
if (self.fixed_length is not None):
if (value != self.value[0]):
raise TypeError("fixed length array")
return
self.value[0] = value
self.fix_length(value)
else:
self.value[item] = value
def __delitem__(self, item):
if self.fixed_length is not None:
raise TypeError("fixed length array")
# no wrapping index
if (item < 1) or (item > self.value[0]):
raise IndexError("index out of range")
@ -792,6 +844,9 @@ def ArrayOf(klass):
raise ValueError("%r not in array" % (value,))
def remove(self, item):
if self.fixed_length is not None:
raise TypeError("fixed length array")
# find the index of the item and delete it
indx = self.index(item)
self.__delitem__(indx)
@ -820,7 +875,7 @@ def ArrayOf(klass):
if _debug: ArrayOf._debug("(%r)decode %r", self.__class__.__name__, taglist)
# start with an empty array
self.value = [0]
new_value = []
while len(taglist) != 0:
tag = taglist.Peek()
@ -835,7 +890,7 @@ def ArrayOf(klass):
helper = self.subtype(tag)
# save the value
self.value.append(helper.value)
new_value.append(helper.value)
else:
if _debug: ArrayOf._debug(" - building value: %r", self.subtype)
# build an element
@ -845,10 +900,15 @@ def ArrayOf(klass):
value.decode(taglist)
# save what was built
self.value.append(value)
new_value.append(value)
# check the length
if self.fixed_length is not None:
if self.fixed_length != len(new_value):
raise ValueError("invalid array length")
# update the length
self.value[0] = len(self.value) - 1
self.value = [len(new_value)] + new_value
def encode_item(self, item, taglist):
if _debug: ArrayOf._debug("(%r)encode_item %r %r", self.__class__.__name__, item, taglist)
@ -947,10 +1007,14 @@ def ArrayOf(klass):
# constrain it to a list of a specific type of item
setattr(ArrayOf, 'subtype', klass)
setattr(ArrayOf, 'fixed_length', fixed_length)
setattr(ArrayOf, 'prototype', prototype)
# update the name
ArrayOf.__name__ = 'ArrayOf' + klass.__name__
# cache this type
_array_of_map[klass] = ArrayOf
_array_of_map[array_signature] = ArrayOf
_array_of_classes[ArrayOf] = 1
# return this new type
@ -1153,7 +1217,7 @@ class Choice(object):
def dict_contents(self, use_dict=None, as_class=dict):
"""Return the contents of an object as a dict."""
if _debug: _log.debug("dict_contents use_dict=%r as_class=%r", use_dict, as_class)
if _debug: Choice._debug("dict_contents use_dict=%r as_class=%r", use_dict, as_class)
# make/extend the dictionary of content
if use_dict is None:
@ -1347,7 +1411,7 @@ bacpypes_debugging(Any)
# AnyAtomic
#
class AnyAtomic:
class AnyAtomic(Atomic):
def __init__(self, arg=None):
if _debug: AnyAtomic._debug("__init__ %r", arg)
@ -1396,3 +1460,4 @@ class AnyAtomic:
return '<' + desc + ' instance at 0x%08x' % (id(self),) + '>'
bacpypes_debugging(AnyAtomic)

View File

@ -2365,7 +2365,9 @@ class PriorityValue(Choice):
, Element('datetime', DateTime, 1)
]
class PriorityArray(ArrayOf(PriorityValue)):
class PriorityArray(ArrayOf(
PriorityValue, fixed_length=16, prototype=PriorityValue(null=()),
)):
pass
class PropertyAccessResultAccessResult(Choice):

View File

@ -5,6 +5,7 @@ Constructed Data
"""
import sys
from copy import deepcopy as _deepcopy
from .errors import DecodingError, \
MissingRequiredParameter, InvalidParameterDatatype, InvalidTag
@ -691,15 +692,33 @@ class Array(object):
_array_of_map = {}
_array_of_classes = {}
def ArrayOf(klass):
def ArrayOf(klass, fixed_length=None, prototype=None):
"""Function to return a class that can encode and decode a list of
some other type."""
global _array_of_map
global _array_of_classes, _sequence_of_classes
# check the parameters for consistency
if issubclass(klass, Atomic):
if prototype is None:
pass
elif not klass.is_valid(prototype):
raise ValueError("prototype %r not valid for %s" % (prototype, klass.__name__))
else:
if prototype is None:
### TODO This should be an error, a prototype should always be
### required for non-atomic types, even if it's only klass()
### for a default object which will be deep copied
pass
elif not isinstance(prototype, klass):
raise ValueError("prototype %r not valid for %s" % (prototype, klass.__name__))
# build a signature of the parameters
array_signature = (klass, fixed_length, prototype)
# if this has already been built, return the cached one
if klass in _array_of_map:
return _array_of_map[klass]
if array_signature in _array_of_map:
return _array_of_map[array_signature]
# no ArrayOf(ArrayOf(...)) allowed
if klass in _array_of_classes:
@ -713,23 +732,60 @@ def ArrayOf(klass):
class ArrayOf(Array):
subtype = None
fixed_length = None
prototype = None
def __init__(self, value=None):
if value is None:
self.value = [0]
if self.fixed_length is not None:
self.fix_length(self.fixed_length)
elif isinstance(value, list):
if (self.fixed_length is not None) and (len(value) != self.fixed_length):
raise ValueError("invalid array length")
self.value = [len(value)]
self.value.extend(value)
else:
raise TypeError("invalid constructor datatype")
def fix_length(self, new_length):
if len(self.value) > new_length + 1:
# trim off the excess
del self.value[new_length + 1:]
elif len(self.value) < new_length + 1:
# how many do we need
element_count = new_length - len(self.value) + 1
# extend or append
if issubclass(self.subtype, Atomic):
if self.prototype is None:
extend_value = self.subtype().value
else:
extend_value = self.prototype
self.value.extend( [extend_value] * element_count )
else:
for i in range(element_count):
if self.prototype is None:
append_value = self.subtype()
else:
append_value = _deepcopy(self.prototype)
self.value.append(append_value)
self.value[0] = new_length
def append(self, value):
if self.fixed_length is not None:
raise TypeError("fixed length array")
if issubclass(self.subtype, Atomic):
pass
elif issubclass(self.subtype, AnyAtomic) and not isinstance(value, Atomic):
raise TypeError("instance of an atomic type required")
elif not isinstance(value, self.subtype):
raise TypeError("%s value required" % (self.subtype.__name__,))
self.value.append(value)
self.value[0] = len(self.value) - 1
@ -750,23 +806,19 @@ def ArrayOf(klass):
# special length handling for index 0
if item == 0:
if value < self.value[0]:
# trim
self.value = self.value[0:value + 1]
elif value > self.value[0]:
# extend
if issubclass(self.subtype, Atomic):
self.value.extend( [self.subtype().value] * (value - self.value[0]) )
else:
for i in range(value - self.value[0]):
self.value.append(self.subtype())
else:
if (self.fixed_length is not None):
if (value != self.value[0]):
raise TypeError("fixed length array")
return
self.value[0] = value
self.fix_length(value)
else:
self.value[item] = value
def __delitem__(self, item):
if self.fixed_length is not None:
raise TypeError("fixed length array")
# no wrapping index
if (item < 1) or (item > self.value[0]):
raise IndexError("index out of range")
@ -788,6 +840,9 @@ def ArrayOf(klass):
raise ValueError("%r not in array" % (value,))
def remove(self, item):
if self.fixed_length is not None:
raise TypeError("fixed length array")
# find the index of the item and delete it
indx = self.index(item)
self.__delitem__(indx)
@ -816,7 +871,7 @@ def ArrayOf(klass):
if _debug: ArrayOf._debug("(%r)decode %r", self.__class__.__name__, taglist)
# start with an empty array
self.value = [0]
new_value = []
while len(taglist) != 0:
tag = taglist.Peek()
@ -831,7 +886,7 @@ def ArrayOf(klass):
helper = self.subtype(tag)
# save the value
self.value.append(helper.value)
new_value.append(helper.value)
else:
if _debug: ArrayOf._debug(" - building value: %r", self.subtype)
# build an element
@ -841,10 +896,15 @@ def ArrayOf(klass):
value.decode(taglist)
# save what was built
self.value.append(value)
new_value.append(value)
# check the length
if self.fixed_length is not None:
if self.fixed_length != len(new_value):
raise ValueError("invalid array length")
# update the length
self.value[0] = len(self.value) - 1
self.value = [len(new_value)] + new_value
def encode_item(self, item, taglist):
if _debug: ArrayOf._debug("(%r)encode_item %r %r", self.__class__.__name__, item, taglist)
@ -941,10 +1001,14 @@ def ArrayOf(klass):
# constrain it to a list of a specific type of item
setattr(ArrayOf, 'subtype', klass)
setattr(ArrayOf, 'fixed_length', fixed_length)
setattr(ArrayOf, 'prototype', prototype)
# update the name
ArrayOf.__name__ = 'ArrayOf' + klass.__name__
# cache this type
_array_of_map[klass] = ArrayOf
_array_of_map[array_signature] = ArrayOf
_array_of_classes[ArrayOf] = 1
# return this new type
@ -1148,7 +1212,7 @@ class Choice(object):
def dict_contents(self, use_dict=None, as_class=dict):
"""Return the contents of an object as a dict."""
if _debug: _log.debug("dict_contents use_dict=%r as_class=%r", use_dict, as_class)
if _debug: Choice._debug("dict_contents use_dict=%r as_class=%r", use_dict, as_class)
# make/extend the dictionary of content
if use_dict is None:

View File

@ -329,6 +329,8 @@ class Property:
arry[arrayIndex] = value
except IndexError:
raise ExecutionError(errorClass='property', errorCode='invalidArrayIndex')
except TypeError:
raise ExecutionError(errorClass='property', errorCode='valueOutOfRange')
# check for monitors, call each one with the old and new value
if is_monitored:

View File

@ -2365,7 +2365,9 @@ class PriorityValue(Choice):
, Element('datetime', DateTime, 1)
]
class PriorityArray(ArrayOf(PriorityValue)):
class PriorityArray(ArrayOf(
PriorityValue, fixed_length=16, prototype=PriorityValue(null=()),
)):
pass
class PropertyAccessResultAccessResult(Choice):

View File

@ -5,6 +5,7 @@ Constructed Data
"""
import sys
from copy import deepcopy as _deepcopy
from .errors import DecodingError, \
MissingRequiredParameter, InvalidParameterDatatype, InvalidTag
@ -691,15 +692,33 @@ class Array(object):
_array_of_map = {}
_array_of_classes = {}
def ArrayOf(klass):
def ArrayOf(klass, fixed_length=None, prototype=None):
"""Function to return a class that can encode and decode a list of
some other type."""
global _array_of_map
global _array_of_classes, _sequence_of_classes
# check the parameters for consistency
if issubclass(klass, Atomic):
if prototype is None:
pass
elif not klass.is_valid(prototype):
raise ValueError("prototype %r not valid for %s" % (prototype, klass.__name__))
else:
if prototype is None:
### TODO This should be an error, a prototype should always be
### required for non-atomic types, even if it's only klass()
### for a default object which will be deep copied
pass
elif not isinstance(prototype, klass):
raise ValueError("prototype %r not valid for %s" % (prototype, klass.__name__))
# build a signature of the parameters
array_signature = (klass, fixed_length, prototype)
# if this has already been built, return the cached one
if klass in _array_of_map:
return _array_of_map[klass]
if array_signature in _array_of_map:
return _array_of_map[array_signature]
# no ArrayOf(ArrayOf(...)) allowed
if klass in _array_of_classes:
@ -713,23 +732,60 @@ def ArrayOf(klass):
class ArrayOf(Array):
subtype = None
fixed_length = None
prototype = None
def __init__(self, value=None):
if value is None:
self.value = [0]
if self.fixed_length is not None:
self.fix_length(self.fixed_length)
elif isinstance(value, list):
if (self.fixed_length is not None) and (len(value) != self.fixed_length):
raise ValueError("invalid array length")
self.value = [len(value)]
self.value.extend(value)
else:
raise TypeError("invalid constructor datatype")
def fix_length(self, new_length):
if len(self.value) > new_length + 1:
# trim off the excess
del self.value[new_length + 1:]
elif len(self.value) < new_length + 1:
# how many do we need
element_count = new_length - len(self.value) + 1
# extend or append
if issubclass(self.subtype, Atomic):
if self.prototype is None:
extend_value = self.subtype().value
else:
extend_value = self.prototype
self.value.extend( [extend_value] * element_count )
else:
for i in range(element_count):
if self.prototype is None:
append_value = self.subtype()
else:
append_value = _deepcopy(self.prototype)
self.value.append(append_value)
self.value[0] = new_length
def append(self, value):
if self.fixed_length is not None:
raise TypeError("fixed length array")
if issubclass(self.subtype, Atomic):
pass
elif issubclass(self.subtype, AnyAtomic) and not isinstance(value, Atomic):
raise TypeError("instance of an atomic type required")
elif not isinstance(value, self.subtype):
raise TypeError("%s value required" % (self.subtype.__name__,))
self.value.append(value)
self.value[0] = len(self.value) - 1
@ -750,23 +806,19 @@ def ArrayOf(klass):
# special length handling for index 0
if item == 0:
if value < self.value[0]:
# trim
self.value = self.value[0:value + 1]
elif value > self.value[0]:
# extend
if issubclass(self.subtype, Atomic):
self.value.extend( [self.subtype().value] * (value - self.value[0]) )
else:
for i in range(value - self.value[0]):
self.value.append(self.subtype())
else:
if (self.fixed_length is not None):
if (value != self.value[0]):
raise TypeError("fixed length array")
return
self.value[0] = value
self.fix_length(value)
else:
self.value[item] = value
def __delitem__(self, item):
if self.fixed_length is not None:
raise TypeError("fixed length array")
# no wrapping index
if (item < 1) or (item > self.value[0]):
raise IndexError("index out of range")
@ -788,6 +840,9 @@ def ArrayOf(klass):
raise ValueError("%r not in array" % (value,))
def remove(self, item):
if self.fixed_length is not None:
raise TypeError("fixed length array")
# find the index of the item and delete it
indx = self.index(item)
self.__delitem__(indx)
@ -816,7 +871,7 @@ def ArrayOf(klass):
if _debug: ArrayOf._debug("(%r)decode %r", self.__class__.__name__, taglist)
# start with an empty array
self.value = [0]
new_value = []
while len(taglist) != 0:
tag = taglist.Peek()
@ -831,7 +886,7 @@ def ArrayOf(klass):
helper = self.subtype(tag)
# save the value
self.value.append(helper.value)
new_value.append(helper.value)
else:
if _debug: ArrayOf._debug(" - building value: %r", self.subtype)
# build an element
@ -841,10 +896,15 @@ def ArrayOf(klass):
value.decode(taglist)
# save what was built
self.value.append(value)
new_value.append(value)
# check the length
if self.fixed_length is not None:
if self.fixed_length != len(new_value):
raise ValueError("invalid array length")
# update the length
self.value[0] = len(self.value) - 1
self.value = [len(new_value)] + new_value
def encode_item(self, item, taglist):
if _debug: ArrayOf._debug("(%r)encode_item %r %r", self.__class__.__name__, item, taglist)
@ -941,10 +1001,14 @@ def ArrayOf(klass):
# constrain it to a list of a specific type of item
setattr(ArrayOf, 'subtype', klass)
setattr(ArrayOf, 'fixed_length', fixed_length)
setattr(ArrayOf, 'prototype', prototype)
# update the name
ArrayOf.__name__ = 'ArrayOf' + klass.__name__
# cache this type
_array_of_map[klass] = ArrayOf
_array_of_map[array_signature] = ArrayOf
_array_of_classes[ArrayOf] = 1
# return this new type
@ -1148,7 +1212,7 @@ class Choice(object):
def dict_contents(self, use_dict=None, as_class=dict):
"""Return the contents of an object as a dict."""
if _debug: _log.debug("dict_contents use_dict=%r as_class=%r", use_dict, as_class)
if _debug: Choice._debug("dict_contents use_dict=%r as_class=%r", use_dict, as_class)
# make/extend the dictionary of content
if use_dict is None:
@ -1340,7 +1404,7 @@ class Any:
#
@bacpypes_debugging
class AnyAtomic:
class AnyAtomic(Atomic):
def __init__(self, arg=None):
if _debug: AnyAtomic._debug("__init__ %r", arg)

View File

@ -67,10 +67,7 @@ def Commandable(datatype, presentValue='presentValue', priorityArray='priorityAr
# see if a priority array was provided
if (priorityArray not in kwargs):
new_priority_array = PriorityArray()
for i in range(16):
new_priority_array.append(PriorityValue(null=()))
setattr(self, priorityArray, new_priority_array)
setattr(self, priorityArray, PriorityArray())
# see if a present value was provided
if (relinquishDefault not in kwargs):

View File

@ -8,11 +8,11 @@ Test Array
import unittest
from bacpypes.debugging import bacpypes_debugging, ModuleLogger, xtob
from bacpypes.debugging import bacpypes_debugging, ModuleLogger
from bacpypes.errors import MissingRequiredParameter
from bacpypes.primitivedata import Integer, Tag, TagList
from bacpypes.constructeddata import Element, Sequence, ArrayOf
from bacpypes.primitivedata import TagList, Integer, Time
from bacpypes.constructeddata import ArrayOf
from bacpypes.basetypes import TimeStamp
from .helpers import SimpleSequence
@ -46,7 +46,7 @@ class TestIntegerArray(unittest.TestCase):
# create another sequence and decode the tag list
ary = IntegerArray()
ary.decode(tag_list)
if _debug: TestIntegerArray._debug(" - seq: %r", seq)
if _debug: TestIntegerArray._debug(" - ary: %r", ary)
def test_append(self):
if _debug: TestIntegerArray._debug("test_append")
@ -86,7 +86,7 @@ class TestIntegerArray(unittest.TestCase):
# not find something
with self.assertRaises(ValueError):
indx = ary.index(4)
ary.index(4)
def test_remove_item(self):
if _debug: TestIntegerArray._debug("test_remove_item")
@ -163,6 +163,132 @@ class TestIntegerArray(unittest.TestCase):
assert ary.value[1:] == ary_value
# fixed length array of integers
IntegerArray5 = ArrayOf(Integer, fixed_length=5)
@bacpypes_debugging
class TestIntegerArray5(unittest.TestCase):
def test_empty_array(self):
if _debug: TestIntegerArray5._debug("test_empty_array")
# create an empty array
ary = IntegerArray5()
if _debug: TestIntegerArray5._debug(" - ary: %r", ary)
# array sematics
assert len(ary) == 5
assert ary[0] == 5
# value correct
assert ary.value[1:] == [0, 0, 0, 0, 0]
def test_append(self):
if _debug: TestIntegerArray5._debug("test_append")
# create an empty array
ary = IntegerArray5()
if _debug: TestIntegerArray5._debug(" - ary: %r", ary)
# append an integer
with self.assertRaises(TypeError):
ary.append(2)
def test_delete_item(self):
if _debug: TestIntegerArray5._debug("test_delete_item")
# create an array
ary = IntegerArray5([1, 2, 3, 4, 5])
if _debug: TestIntegerArray5._debug(" - ary: %r", ary)
# delete something
with self.assertRaises(TypeError):
del ary[2]
def test_index_item(self):
if _debug: TestIntegerArray5._debug("test_index_item")
# create an array
ary = IntegerArray5([1, 2, 3, 4, 5])
if _debug: TestIntegerArray5._debug(" - ary: %r", ary)
# find something
assert ary.index(3) == 3
# not find something
with self.assertRaises(ValueError):
ary.index(100)
def test_remove_item(self):
if _debug: TestIntegerArray5._debug("test_remove_item")
# create an array
ary = IntegerArray5([1, 2, 3, 4, 5])
if _debug: TestIntegerArray5._debug(" - ary: %r", ary)
# remove something
with self.assertRaises(TypeError):
ary.remove(4)
def test_resize(self):
if _debug: TestIntegerArray5._debug("test_resize")
# create an array
ary = IntegerArray5([1, 2, 3, 4, 5])
if _debug: TestIntegerArray5._debug(" - ary: %r", ary)
# make it the same length (noop)
ary[0] = 5
# changing it to something else fails
with self.assertRaises(TypeError):
ary[0] = 4
def test_get_item(self):
if _debug: TestIntegerArray5._debug("test_get_item")
# create an array
ary = IntegerArray5([1, 2, 3, 4, 5])
if _debug: TestIntegerArray5._debug(" - ary: %r", ary)
# BACnet semantics
assert ary[1] == 1
def test_set_item(self):
if _debug: TestIntegerArray5._debug("test_set_item")
# create an array
ary = IntegerArray5([1, 2, 3, 4, 5])
if _debug: TestIntegerArray5._debug(" - ary: %r", ary)
# BACnet semantics, no type checking
ary[1] = 10
assert ary[1] == 10
def test_codec(self):
if _debug: TestIntegerArray5._debug("test_codec")
# test array contents
ary_value = [1, 2, 3, 4, 5]
# create an array
ary = IntegerArray5(ary_value)
if _debug: TestIntegerArray5._debug(" - ary: %r", ary)
# encode it in a tag list
tag_list = TagList()
ary.encode(tag_list)
if _debug: TestIntegerArray5._debug(" - tag_list: %r", tag_list)
# create another sequence and decode the tag list
ary = IntegerArray()
ary.decode(tag_list)
if _debug: TestIntegerArray5._debug(" - ary %r", ary)
# value matches
assert ary.value[1:] == ary_value
# array of a sequence
SimpleSequenceArray = ArrayOf(SimpleSequence)
@ -196,3 +322,23 @@ class TestSimpleSequenceArray(unittest.TestCase):
# value matches
assert ary.value[1:] == ary_value
# fixed length array of TimeStamps
ArrayOfTimeStamp = ArrayOf(TimeStamp, fixed_length=16,
prototype=TimeStamp(time=Time().value),
)
@bacpypes_debugging
class TestArrayOfTimeStamp(unittest.TestCase):
def test_empty_array(self):
if _debug: TestArrayOfTimeStamp._debug("test_empty_array")
# create an empty array
ary = ArrayOfTimeStamp()
if _debug: TestArrayOfTimeStamp._debug(" - ary: %r", ary)
# array sematics
assert len(ary) == 16
assert ary[0] == 16