class DataTests(unittest.TestCase): FIELD_TBL_ENCODED = ( b'\x00\x00\x00\xbb\x07longvall\x00\x00\x00\x01\x00\x00\x00\x00' b'\x06intvalI\x00\x00\x00\x01\x07dictvalF\x00\x00' b'\x00\x0c\x03fooS\x00\x00\x00\x03bar\x07unicodeS' b'\x00\x00\x00\x08utf8=\xe2\x9c\x93\x05arrayA\x00' b'\x00\x00\x0fI\x00\x00\x00\x01I\x00\x00\x00\x02I' b'\x00\x00\x00\x03\x04nullV\x06strvalS\x00\x00\x00' b'\x04Test\x0ctimestampvalT\x00\x00\x00\x00Ec)\x92' b'\x07decimalD\x02\x00\x00\x01:\x07boolvalt\x01' b'\x0bdecimal_tooD\x00\x00\x00\x00d') FIELD_TBL_VALUE = OrderedDict([ ('longval', long(4294967296)), ('intval', 1), ('dictval', { 'foo': 'bar' }), ('unicode', u'utf8=✓'), ('array', [1, 2, 3]), ('null', None), ('strval', 'Test'), ('timestampval', datetime.datetime(2006, 11, 21, 16, 30, 10)), ('decimal', decimal.Decimal('3.14')), ('boolval', True), ('decimal_too', decimal.Decimal('100')), ]) @unittest.skipIf(platform.python_implementation() == 'PyPy', 'pypy sort order issue') def test_encode_table(self): result = [] data.encode_table(result, self.FIELD_TBL_VALUE) print(b''.join(result)) print(self.FIELD_TBL_ENCODED) self.assertEqual(b''.join(result), self.FIELD_TBL_ENCODED) def test_encode_table_bytes(self): result = [] byte_count = data.encode_table(result, self.FIELD_TBL_VALUE) self.assertEqual(byte_count, 191) def test_decode_table(self): value, byte_count = data.decode_table(self.FIELD_TBL_ENCODED, 0) self.assertDictEqual(value, self.FIELD_TBL_VALUE) def test_decode_table_bytes(self): value, byte_count = data.decode_table(self.FIELD_TBL_ENCODED, 0) self.assertEqual(byte_count, 191) def test_encode_raises(self): self.assertRaises(exceptions.UnsupportedAMQPFieldException, data.encode_table, [], {'foo': set([1, 2, 3])}) def test_decode_raises(self): self.assertRaises(exceptions.InvalidFieldTypeException, data.decode_table, b'\x00\x00\x00\t\x03fooZ\x00\x00\x04\xd2', 0)
class DataTests(unittest.TestCase): FIELD_TBL_ENCODED = ( b'\x00\x00\x00\xcb' b'\x05arrayA\x00\x00\x00\x0fI\x00\x00\x00\x01I' b'\x00\x00\x00\x02I\x00\x00\x00\x03' b'\x07boolvalt\x01' b'\x07decimalD\x02\x00\x00\x01:' b'\x0bdecimal_tooD\x00\x00\x00\x00d' b'\x07dictvalF\x00\x00\x00\x0c\x03fooS\x00\x00\x00\x03bar' b'\x06intvalI\x00\x00\x00\x01' b'\x06bigint\x6c\x00\x00\x00\x00\x9a\x7e\xc8\x00' b'\x07longval\x6c\x00\x00\x00\x00\x36\x65\x26\x55' b'\x04nullV' b'\x06strvalS\x00\x00\x00\x04Test' b'\x0ctimestampvalT\x00\x00\x00\x00Ec)\x92' b'\x07unicodeS\x00\x00\x00\x08utf8=\xe2\x9c\x93') FIELD_TBL_VALUE = OrderedDict([('array', [1, 2, 3]), ('boolval', True), ('decimal', decimal.Decimal('3.14')), ('decimal_too', decimal.Decimal('100')), ('dictval', { 'foo': 'bar' }), ('intval', 1), ('bigint', 2592000000), ('longval', long(912598613)), ('null', None), ('strval', 'Test'), ('timestampval', datetime.datetime(2006, 11, 21, 16, 30, 10)), ('unicode', u'utf8=✓')]) def test_encode_table(self): result = [] data.encode_table(result, self.FIELD_TBL_VALUE) self.assertEqual(b''.join(result), self.FIELD_TBL_ENCODED) def test_encode_table_bytes(self): result = [] byte_count = data.encode_table(result, self.FIELD_TBL_VALUE) self.assertEqual(byte_count, 207) def test_decode_table(self): value, byte_count = data.decode_table(self.FIELD_TBL_ENCODED, 0) self.assertDictEqual(value, self.FIELD_TBL_VALUE) def test_decode_table_bytes(self): value, byte_count = data.decode_table(self.FIELD_TBL_ENCODED, 0) self.assertEqual(byte_count, 207) def test_encode_raises(self): self.assertRaises(exceptions.UnsupportedAMQPFieldException, data.encode_table, [], {'foo': {1, 2, 3}}) def test_decode_raises(self): self.assertRaises(exceptions.InvalidFieldTypeException, data.decode_table, b'\x00\x00\x00\t\x03fooZ\x00\x00\x04\xd2', 0)
def decode_value(encoded, offset): """Decode the value passed in returning the decoded value and the number of bytes read in addition to the starting offset. :param str encoded: The binary encoded data to decode :param int offset: The starting byte offset :rtype: tuple :raises: pika.exceptions.InvalidFieldTypeException """ # slice to get bytes in Python 3 and str in Python 2 kind = encoded[offset:offset + 1] offset += 1 # Bool if kind == b't': value = struct.unpack_from('>B', encoded, offset)[0] value = bool(value) offset += 1 # Short-Short Int elif kind == b'b': value = struct.unpack_from('>B', encoded, offset)[0] offset += 1 # Short-Short Unsigned Int elif kind == b'B': value = struct.unpack_from('>b', encoded, offset)[0] offset += 1 # Short Int elif kind == b'U': value = struct.unpack_from('>h', encoded, offset)[0] offset += 2 # Short Unsigned Int elif kind == b'u': value = struct.unpack_from('>H', encoded, offset)[0] offset += 2 # Long Int elif kind == b'I': value = struct.unpack_from('>i', encoded, offset)[0] offset += 4 # Long Unsigned Int elif kind == b'i': value = struct.unpack_from('>I', encoded, offset)[0] offset += 4 # Long-Long Int elif kind == b'L': value = long(struct.unpack_from('>q', encoded, offset)[0]) offset += 8 # Long-Long Unsigned Int elif kind == b'l': value = long(struct.unpack_from('>Q', encoded, offset)[0]) offset += 8 # Float elif kind == b'f': value = long(struct.unpack_from('>f', encoded, offset)[0]) offset += 4 # Double elif kind == b'd': value = long(struct.unpack_from('>d', encoded, offset)[0]) offset += 8 # Decimal elif kind == b'D': decimals = struct.unpack_from('B', encoded, offset)[0] offset += 1 raw = struct.unpack_from('>i', encoded, offset)[0] offset += 4 value = decimal.Decimal(raw) * (decimal.Decimal(10)**-decimals) # Short String elif kind == b's': value, offset = decode_short_string(encoded, offset) # Long String elif kind == b'S': length = struct.unpack_from('>I', encoded, offset)[0] offset += 4 value = encoded[offset:offset + length].decode('utf8') offset += length # Field Array elif kind == b'A': length = struct.unpack_from('>I', encoded, offset)[0] offset += 4 offset_end = offset + length value = [] while offset < offset_end: v, offset = decode_value(encoded, offset) value.append(v) # Timestamp elif kind == b'T': value = datetime.utcfromtimestamp( struct.unpack_from('>Q', encoded, offset)[0]) offset += 8 # Field Table elif kind == b'F': (value, offset) = decode_table(encoded, offset) # Null / Void elif kind == b'V': value = None else: raise exceptions.InvalidFieldTypeException(kind) return value, offset
def decode_value(encoded, offset): """Decode the value passed in returning the decoded value and the number of bytes read in addition to the starting offset. :param str encoded: The binary encoded data to decode :param int offset: The starting byte offset :rtype: tuple :raises: pika.exceptions.InvalidFieldTypeException """ # slice to get bytes in Python 3 and str in Python 2 kind = encoded[offset:offset + 1] offset += 1 # Bool if kind == b't': value = struct.unpack_from('>B', encoded, offset)[0] value = bool(value) offset += 1 # Short-Short Int elif kind == b'b': value = struct.unpack_from('>B', encoded, offset)[0] offset += 1 # Short-Short Unsigned Int elif kind == b'B': value = struct.unpack_from('>b', encoded, offset)[0] offset += 1 # Short Int elif kind == b'U': value = struct.unpack_from('>h', encoded, offset)[0] offset += 2 # Short Unsigned Int elif kind == b'u': value = struct.unpack_from('>H', encoded, offset)[0] offset += 2 # Long Int elif kind == b'I': value = struct.unpack_from('>i', encoded, offset)[0] offset += 4 # Long Unsigned Int elif kind == b'i': value = struct.unpack_from('>I', encoded, offset)[0] offset += 4 # Long-Long Int elif kind == b'L': value = long(struct.unpack_from('>q', encoded, offset)[0]) offset += 8 # Long-Long Unsigned Int elif kind == b'l': value = long(struct.unpack_from('>Q', encoded, offset)[0]) offset += 8 # Float elif kind == b'f': value = long(struct.unpack_from('>f', encoded, offset)[0]) offset += 4 # Double elif kind == b'd': value = long(struct.unpack_from('>d', encoded, offset)[0]) offset += 8 # Decimal elif kind == b'D': decimals = struct.unpack_from('B', encoded, offset)[0] offset += 1 raw = struct.unpack_from('>i', encoded, offset)[0] offset += 4 value = decimal.Decimal(raw) * (decimal.Decimal(10) ** -decimals) # Short String elif kind == b's': length = struct.unpack_from('B', encoded, offset)[0] offset += 1 value = encoded[offset:offset + length].decode('utf8') offset += length # Long String elif kind == b'S': length = struct.unpack_from('>I', encoded, offset)[0] offset += 4 value = encoded[offset:offset + length].decode('utf8') offset += length # Field Array elif kind == b'A': length = struct.unpack_from('>I', encoded, offset)[0] offset += 4 offset_end = offset + length value = [] while offset < offset_end: v, offset = decode_value(encoded, offset) value.append(v) # Timestamp elif kind == b'T': value = datetime.utcfromtimestamp(struct.unpack_from('>Q', encoded, offset)[0]) offset += 8 # Field Table elif kind == b'F': (value, offset) = decode_table(encoded, offset) # Null / Void elif kind == b'V': value = None else: raise exceptions.InvalidFieldTypeException(kind) return value, offset
def test_long_repr(self): value = long(912598613) self.assertEqual(repr(value), '912598613L')
def encode_value(pieces, value): # pylint: disable=R0911 """Encode the value passed in and append it to the pieces list returning the the size of the encoded value. :param list pieces: Already encoded values :param any value: The value to encode :rtype: int """ if PY2: if isinstance(value, basestring): if isinstance(value, unicode_type): value = value.encode('utf-8') pieces.append(struct.pack('>cI', b'S', len(value))) pieces.append(value) return 5 + len(value) else: # support only str on Python 3 if isinstance(value, basestring): value = value.encode('utf-8') pieces.append(struct.pack('>cI', b'S', len(value))) pieces.append(value) return 5 + len(value) if isinstance(value, bytes): pieces.append(struct.pack('>cI', b'x', len(value))) pieces.append(value) return 5 + len(value) if isinstance(value, bool): pieces.append(struct.pack('>cB', b't', int(value))) return 2 if isinstance(value, long): pieces.append(struct.pack('>cq', b'l', value)) return 9 elif isinstance(value, int): with warnings.catch_warnings(): warnings.filterwarnings('error') try: packed = struct.pack('>ci', b'I', value) pieces.append(packed) return 5 except (struct.error, DeprecationWarning): packed = struct.pack('>cq', b'l', long(value)) pieces.append(packed) return 9 elif isinstance(value, decimal.Decimal): value = value.normalize() if value.as_tuple().exponent < 0: decimals = -value.as_tuple().exponent raw = int(value * (decimal.Decimal(10)**decimals)) pieces.append(struct.pack('>cBi', b'D', decimals, raw)) else: # per spec, the "decimals" octet is unsigned (!) pieces.append(struct.pack('>cBi', b'D', 0, int(value))) return 6 elif isinstance(value, datetime): pieces.append( struct.pack('>cQ', b'T', calendar.timegm(value.utctimetuple()))) return 9 elif isinstance(value, dict): pieces.append(struct.pack('>c', b'F')) return 1 + encode_table(pieces, value) elif isinstance(value, list): list_pieces = [] for val in value: encode_value(list_pieces, val) piece = b''.join(list_pieces) pieces.append(struct.pack('>cI', b'A', len(piece))) pieces.append(piece) return 5 + len(piece) elif value is None: pieces.append(struct.pack('>c', b'V')) return 1 else: raise exceptions.UnsupportedAMQPFieldException(pieces, value)
def test_headers_repr(self): hdr = 'timestamp_in_ms' v = long(912598613) h = { hdr : v } p = spec.BasicProperties(content_type='text/plain', headers=h) self.assertEqual(repr(p.headers[hdr]), '912598613L')