diff options
| author | Robert Collins <robertc@robertcollins.net> | 2013-08-25 02:07:59 +1200 |
|---|---|---|
| committer | Robert Collins <robertc@robertcollins.net> | 2013-08-25 02:07:59 +1200 |
| commit | 02c2174ec17411b839fd5ff2b04efe42d98c21bf (patch) | |
| tree | 5b04d294c378a9115f44ed3f023fa0c8ec6466a0 /python | |
| parent | 273a4c27aba153af19925c0e7f293d2d696fad7b (diff) | |
| download | subunit-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.py | 25 |
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' % ( |
