mirror of
https://github.com/JoelBender/bacpypes
synced 2025-09-28 22:15:23 +08:00
merge (#149)
This commit is contained in:
parent
200a9321db
commit
48cc40deae
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user