summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorRobert Collins <robertc@robertcollins.net>2013-08-25 02:07:59 +1200
committerRobert Collins <robertc@robertcollins.net>2013-08-25 02:07:59 +1200
commit02c2174ec17411b839fd5ff2b04efe42d98c21bf (patch)
tree5b04d294c378a9115f44ed3f023fa0c8ec6466a0 /python
parent273a4c27aba153af19925c0e7f293d2d696fad7b (diff)
downloadsubunit-git-02c2174ec17411b839fd5ff2b04efe42d98c21bf.tar.gz
* Memoryview and struct were mutually incompatible in 2.7.3 and 3.2.
(Robert Collins, #1216163)
Diffstat (limited to 'python')
-rw-r--r--python/subunit/v2.py25
1 files changed, 15 insertions, 10 deletions
diff --git a/python/subunit/v2.py b/python/subunit/v2.py
index 1f5bfc1..e710346 100644
--- a/python/subunit/v2.py
+++ b/python/subunit/v2.py
@@ -331,26 +331,35 @@ class ByteStreamToStreamResult(object):
eof=True, file_name="Parser Error",
file_bytes=(error.args[0]).encode('utf8'))
+ def _to_bytes(self, data, pos, length):
+ """Return a slice of data from pos for length as bytes."""
+ # memoryview in 2.7.3 and 3.2 isn't directly usable with struct :(.
+ # see https://bugs.launchpad.net/subunit/+bug/1216163
+ result = data[pos:pos+length]
+ if type(result) is not bytes:
+ return result.tobytes()
+ return result
+
def _parse_varint(self, data, pos, max_3_bytes=False):
# because the only incremental IO we do is at the start, and the 32 bit
# CRC means we can always safely read enough to cover any varint, we
# can be sure that there should be enough data - and if not it is an
# error not a normal situation.
- data_0 = struct.unpack(FMT_8, data[pos:pos+1])[0]
+ data_0 = struct.unpack(FMT_8, self._to_bytes(data, pos, 1))[0]
typeenum = data_0 & 0xc0
value_0 = data_0 & 0x3f
if typeenum == 0x00:
return value_0, 1
elif typeenum == 0x40:
- data_1 = struct.unpack(FMT_8, data[pos+1:pos+2])[0]
+ data_1 = struct.unpack(FMT_8, self._to_bytes(data, pos+1, 1))[0]
return (value_0 << 8) | data_1, 2
elif typeenum == 0x80:
- data_1 = struct.unpack(FMT_16, data[pos+1:pos+3])[0]
+ data_1 = struct.unpack(FMT_16, self._to_bytes(data, pos+1, 2))[0]
return (value_0 << 16) | data_1, 3
else:
if max_3_bytes:
raise ParseError('3 byte maximum given but 4 byte value found.')
- data_1, data_2 = struct.unpack(FMT_24, data[pos+1:pos+4])
+ data_1, data_2 = struct.unpack(FMT_24, self._to_bytes(data, pos+1, 3))
result = (value_0 << 24) | data_1 << 8 | data_2
return result, 4
@@ -385,16 +394,14 @@ class ByteStreamToStreamResult(object):
% (crc, packet_crc))
if safe_hasattr(builtins, 'memoryview'):
body = memoryview(packet[-1])
- view = True
else:
body = packet[-1]
- view = False
# Discard CRC-32
body = body[:-4]
# One packet could have both file and status data; the Python API
# presents these separately (perhaps it shouldn't?)
if flags & FLAG_TIMESTAMP:
- seconds = struct.unpack(FMT_32, body[pos:pos+4])[0]
+ seconds = struct.unpack(FMT_32, self._to_bytes(body, pos, 4))[0]
nanoseconds, consumed = self._parse_varint(body, pos+4)
pos = pos + 4 + consumed
timestamp = EPOCH + datetime.timedelta(
@@ -422,9 +429,7 @@ class ByteStreamToStreamResult(object):
file_name, pos = self._read_utf8(body, pos)
content_length, consumed = self._parse_varint(body, pos)
pos += consumed
- file_bytes = body[pos:pos+content_length]
- if view:
- file_bytes = file_bytes.tobytes()
+ file_bytes = self._to_bytes(body, pos, content_length)
if len(file_bytes) != content_length:
raise ParseError('File content extends past end of packet: '
'claimed %d bytes, %d available' % (