Skip to content

Commit

Permalink
fields: length: make getval() usable for non-integral fields
Browse files Browse the repository at this point in the history
This will actually change behavior for cases where the multiplier
was used previously.  The multiplier may just be a specific
instance of the new specialization hooks that have now been added
and should be considered a candidate for removal in the future.

This change relates to #18

Signed-off-by: Paul Osborne <Paul.Osborne@digi.com>
  • Loading branch information
posborne committed Nov 5, 2015
1 parent 529b9a4 commit dcd5ecd
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 3 deletions.
5 changes: 2 additions & 3 deletions suitcase/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -451,8 +451,7 @@ def bytes_required(self):
return self.length_field.bytes_required

def getval(self):
length_value = self.get_length(self.length_field)
return length_value
return self.length_field.getval()

def setval(self, value):
raise SuitcaseProgrammingError("Cannot set the value of a LengthField")
Expand Down Expand Up @@ -480,7 +479,7 @@ def unpack(self, data):
return self.length_field.unpack(data)

def get_adjusted_length(self):
return self.getval() * self.multiplier
return self.get_length(self.length_field) * self.multiplier


class TypeField(BaseField):
Expand Down
44 changes: 44 additions & 0 deletions suitcase/test/test_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,50 @@ class SuperChild(Structure):
remaining = VariableRawPayload(length)


# See https://github.com/digidotcom/python-suitcase/issues/18
#
# This field is setup to test a LengthField with logic for getting/setting
# the length out of a complicated field (in this case a BitField).
def _set_length(field, length):
field.length = length


class BGAPIFrame(Structure):
head = LengthField(
BitField(16,
is_event=BitBool(),
technology_type=BitNum(4),
length=BitNum(11)),
get_length=lambda f: f.length,
set_length=_set_length)
class_id = UBInt8()
command_id = UBInt8()
payload = Payload(head)


class TestCustomSetGetLengthField(unittest.TestCase):

def test_unpack(self):
frame = BGAPIFrame.from_data(b'\x00\x00\x00\x01')
self.assertEqual(frame.head.is_event, False)
self.assertEqual(frame.head.technology_type, 0)
self.assertEqual(frame.head.length, 0)
self.assertEqual(frame.class_id, 0)
self.assertEqual(frame.command_id, 1)
self.assertEqual(frame.payload, b"")

def test_pack(self):
frame = BGAPIFrame()
frame.head.is_event = True
frame.head.technology_type = 0b1101
frame.class_id = 0x10
frame.command_id = 0xFE
frame.payload = b"Hello, world!"
self.assertEqual(frame.pack(), b'\xe8\r\x10\xfeHello, world!')
frame_readback = BGAPIFrame.from_data(frame.pack())
self.assertEqual(frame_readback.head.length, len(frame.payload))


# Message containing every field
class SuperMessage(Structure):
magic = Magic(b'\xAA\xAA')
Expand Down

0 comments on commit dcd5ecd

Please sign in to comment.