Skip to content

Commit

Permalink
Add Python3 support to txdbus.
Browse files Browse the repository at this point in the history
  • Loading branch information
geertj committed Aug 21, 2013
1 parent d5412cd commit b2a40db
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 52 deletions.
41 changes: 23 additions & 18 deletions gruvi/txdbus/marshal.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,15 +242,14 @@ def sigFromPy( pobj ):
return sig

elif isinstance(pobj, int): return 'i'
elif isinstance(pobj, long): return 'x'
elif isinstance(pobj, float): return 'd'
elif isinstance(pobj, basestring): return 's'
elif isinstance(pobj, str): return 's'

elif isinstance(pobj, list):
return 'a' + sigFromPy(pobj[0])

elif isinstance(pobj, dict):
return 'a{' + sigFromPy(pobj.keys()[0]) + sigFromPy(pobj.values()[0]) + '}'
return 'a{' + sigFromPy(next(iter(pobj.keys()))) + sigFromPy(next(iter(pobj.values()))) + '}'

else:
raise MarshallingError('Invalid Python type for variant: ' + repr(pobj))
Expand All @@ -262,14 +261,14 @@ def sigFromPy( pobj ):
# - All data types must be padded to the correct alignment
# - All padding bytes must be nul
#
padding = { 0 : '\0' * 0,
1 : '\0' * 1,
2 : '\0' * 2,
3 : '\0' * 3,
4 : '\0' * 4,
5 : '\0' * 5,
6 : '\0' * 6,
7 : '\0' * 7 }
padding = { 0 : b'\0' * 0,
1 : b'\0' * 1,
2 : b'\0' * 2,
3 : b'\0' * 3,
4 : b'\0' * 4,
5 : b'\0' * 5,
6 : b'\0' * 6,
7 : b'\0' * 7 }

def genpad( align ):
return lambda x : padding[ x % align and (align - x%align) or 0 ]
Expand Down Expand Up @@ -404,11 +403,13 @@ def marshal_double( ct, var, start_byte, lendian ):
# 3 - terminating nul byte
#
def marshal_string( ct, var, start_byte, lendian ):
if not isinstance(var, basestring):
if isinstance(var, six.text_type):
var = var.encode('utf8')
elif not isinstance(var, six.binary_type):
raise MarshallingError('Required string. Received: ' + repr(var))
if var.find('\0') != -1:
if var.find(b'\0') != -1:
raise MarshallingError('Embedded nul characters are not allowed within DBus strings')
return 4 + len(var) + 1, [ struct.pack( lendian and '<I' or '>I', len(var)), var, '\0' ]
return 4 + len(var) + 1, [ struct.pack( lendian and '<I' or '>I', len(var)), var, b'\0' ]


# OBJECT_PATH:
Expand All @@ -429,7 +430,11 @@ def marshal_object_path( ct, var, start_byte, lendian ):
# 3 - terminating nul byte
def marshal_signature( ct, var, start_byte, lendian ):
# XXX validate signature
return 2 + len(var), [struct.pack(lendian and '<B' or '>B', len(var)), var, '\0']
if isinstance(var, six.text_type):
var = var.encode('ascii')
elif not isinstance(var, six.binary_type):
raise MarshallingError('Required string. Received: ' + repr(var))
return 2 + len(var), [struct.pack(lendian and '<B' or '>B', len(var)), var, b'\0']


# ARRAY:
Expand All @@ -455,7 +460,7 @@ def marshal_array( ct, var, start_byte, lendian ):
if isinstance(var, (list, tuple)):
arr_list = var
elif isinstance(var, dict):
arr_list = [ tpl for tpl in var.iteritems() ]
arr_list = [ tpl for tpl in var.items() ]
else:
raise MarshallingError('List, Tuple, or Dictionary required for DBus array. Received: ' + repr(var))

Expand Down Expand Up @@ -641,7 +646,7 @@ def unmarshal_double(ct, data, offset, lendian):
#
def unmarshal_string(ct, data, offset, lendian):
slen = struct.unpack_from( lendian and '<I' or '>I', data, offset)[0]
return 4 + slen + 1, data[ offset + 4 : offset + 4 + slen ]
return 4 + slen + 1, data[ offset + 4 : offset + 4 + slen ].decode('ascii')


# OBJECT_PATH:
Expand All @@ -660,7 +665,7 @@ def unmarshal_string(ct, data, offset, lendian):
# 3 - terminating nul byte
def unmarshal_signature(ct, data, offset, lendian):
slen = struct.unpack_from( lendian and '<b' or '>b', data, offset)[0]
return 1 + slen + 1, data[ offset + 1 : offset + 1 + slen ]
return 1 + slen + 1, data[ offset + 1 : offset + 1 + slen ].decode('ascii')


# ARRAY:
Expand Down
8 changes: 4 additions & 4 deletions gruvi/txdbus/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,9 @@ def _marshal(self, newSerial=True):
self.headers.append( [code, hval] )

if self.signature:
binBody = ''.join( marshal.marshal( self.signature, self.body )[1] )
binBody = b''.join( marshal.marshal( self.signature, self.body )[1] )
else:
binBody = ''
binBody = b''

self.bodyLength = len(binBody)

Expand All @@ -115,7 +115,7 @@ def _marshal(self, newSerial=True):

DBusMessage._nextSerial += 1

binHeader = ''.join(marshal.marshal(_headerFormat,
binHeader = b''.join(marshal.marshal(_headerFormat,
[self.endian,
self._messageType,
flags,
Expand All @@ -131,7 +131,7 @@ def _marshal(self, newSerial=True):
self.rawPadding = headerPadding
self.rawBody = binBody

self.rawMessage = ''.join( [binHeader, headerPadding, binBody] )
self.rawMessage = b''.join( [binHeader, headerPadding, binBody] )

if len(self.rawMessage) > self._maxMsgLen:
raise error.MarshallingError('Marshalled message exceeds maximum message size of %d' %
Expand Down
55 changes: 26 additions & 29 deletions gruvi/txdbus/test/test_marshal.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,6 @@ def t(self, p, s):
def test_int(self):
self.t(1,'i')

def test_long(self):
self.t(long(1),'x')

def test_float(self):
self.t(1.0,'d')

Expand All @@ -59,19 +56,19 @@ class V(object):
class AlignmentTests(unittest.TestCase):

def test_no_padding(self):
self.assertEquals( m.pad['y']( 1 ), '' )
self.assertEquals( m.pad['y']( 1 ), b'' )

def test_2align(self):
self.assertEquals( m.pad['n']( 1 ), '\0')
self.assertEquals( m.pad['n']( 1 ), b'\0')

def test_8align(self):
self.assertEquals( m.pad['t']( 1 ), '\0'*7)
self.assertEquals( m.pad['t']( 1 ), b'\0'*7)

def test_0align(self):
self.assertEquals( m.pad['t']( 8 ), '')
self.assertEquals( m.pad['t']( 8 ), b'')

def test_mid_align(self):
self.assertEquals( m.pad['t']( 4 ), '\0'*4)
self.assertEquals( m.pad['t']( 4 ), b'\0'*4)



Expand Down Expand Up @@ -111,7 +108,7 @@ def check(self, sig, var_list, expected_encoding, little_endian=True):
if not isinstance(var_list, list):
var_list = [var_list]
nbytes, chunks = m.marshal( sig, var_list, 0, little_endian )
bin_str = ''.join(chunks)
bin_str = b''.join(chunks)
self.assertEquals( nbytes, len(expected_encoding), "Byte length mismatch. Expected %d. Got %d" % (len(expected_encoding), nbytes) )
self.assertEquals( bin_str, expected_encoding, "Binary encoding differs from expected value" )

Expand All @@ -120,7 +117,7 @@ def check(self, sig, var_list, expected_encoding, little_endian=True):
class TestSimpleMarshal(TestMarshal):

def test_byte(self):
self.check( 'y', 1, chr(1) )
self.check( 'y', 1, b'\1' )

def test_int16(self):
self.check( 'n', -1024, pack('h', -1024))
Expand All @@ -147,19 +144,19 @@ def test_boolean(self):
self.check( 'b', True, pack('i',1))

def test_string(self):
self.check( 's', 'Hello World', pack('i12s', 11, 'Hello World'))
self.check( 's', 'Hello World', pack('i12s', 11, b'Hello World'))

def test_string_wrong_type(self):
self.assertRaises(m.MarshallingError, self.check, 's', 1, '')
self.assertRaises(m.MarshallingError, self.check, 's', 1, b'')

def test_string_embedded_null(self):
self.assertRaises(m.MarshallingError, self.check, 's', 'Hello\0World', '')
self.assertRaises(m.MarshallingError, self.check, 's', b'Hello\0World', b'')

def test_signature1(self):
self.check( 'g', 'i', pack('BcB', 1, 'i', 0) )
self.check( 'g', 'i', pack('BcB', 1, b'i', 0) )

def test_signature2(self):
self.check( 'g', '(ii)', pack('B4sB', 4, '(ii)', 0) )
self.check( 'g', '(ii)', pack('B4sB', 4, b'(ii)', 0) )

def test_endian(self):
self.check( 'x', 70000, pack('>q', 70000), False)
Expand All @@ -179,7 +176,7 @@ def test_pad(self):
self.check('(yx)', [[1,70000]], pack('Bxxxxxxxq',1,70000))

def test_string(self):
self.check('(ysy)', [[1, 'foo', 2]], pack('Bxxxi3sxB', 1, 3, 'foo', 2))
self.check('(ysy)', [[1, 'foo', 2]], pack('Bxxxi3sxB', 1, 3, b'foo', 2))

def test_substruct(self):
self.check('(y(ii)y)', [[1, [3,4], 2]], pack('BxxxxxxxiiB', 1, 3, 4, 2))
Expand All @@ -206,7 +203,7 @@ def test_byte(self):
self.check('ay', [[1,2,3,4]], pack('iBBBB', 4, 1,2,3,4))

def test_string(self):
self.check('as', [['x', 'foo']], pack('ii2sxxi4s', 16, 1, 'x', 3, 'foo'))
self.check('as', [['x', 'foo']], pack('ii2sxxi4s', 16, 1, b'x', 3, b'foo'))

def test_struct(self):
self.check('a(ii)', [[[1,2],[3,4]]], pack('ixxxxiiii', 16, 1,2,3,4))
Expand All @@ -220,7 +217,7 @@ def test_dict(self):
def test_dict_strings(self):
self.check('a{ss}',
[[('foo','bar'), ('x','y')]],
pack('ixxxxi4si4si2sxxi2s', 30, 3, 'foo', 3, 'bar', 1, 'x', 1, 'y'))
pack('ixxxxi4si4si2sxxi2s', 30, 3, b'foo', 3, b'bar', 1, b'x', 1, b'y'))

def test_invalid_array(self):
self.assertRaises(m.MarshallingError, self.check, 'a{yy}', 1, '')
Expand All @@ -229,7 +226,7 @@ def test_invalid_array(self):
class TestVariantMarshal(TestMarshal):

def test_byte(self):
self.check('v', [1], pack('B2si', 1, 'i', 1))
self.check('v', [1], pack('B2si', 1, b'i', 1))

def test_struct(self):
class S:
Expand All @@ -240,7 +237,7 @@ def __init__(self):
self.a = 1
self.b = 2

self.check('v', [S()], pack('B5sxxii', 4, '(ii)', 1,2))
self.check('v', [S()], pack('B5sxxii', 4, b'(ii)', 1,2))


#-------------------------------------------------------------------------------
Expand Down Expand Up @@ -295,7 +292,7 @@ def check(self, sig, expected_value, encoding):
class TestSimpleUnmarshal(TestUnmarshal):

def test_byte(self):
self.check( 'y', 1, chr(1) )
self.check( 'y', 1, b'\1' )

def test_int16(self):
self.check( 'n', -1024, pack('h', -1024))
Expand All @@ -322,13 +319,13 @@ def test_boolean(self):
self.check( 'b', True, pack('i',1))

def test_string(self):
self.check( 's', 'Hello World', pack('i12s', 11, 'Hello World'))
self.check( 's', 'Hello World', pack('i12s', 11, b'Hello World'))

def test_signature1(self):
self.check( 'g', 'i', pack('BcB', 1, 'i', 0) )
self.check( 'g', 'i', pack('BcB', 1, b'i', 0) )

def test_signature2(self):
self.check( 'g', '(ii)', pack('B4sB', 4, '(ii)', 0) )
self.check( 'g', '(ii)', pack('B4sB', 4, b'(ii)', 0) )



Expand All @@ -346,7 +343,7 @@ def test_pad(self):
self.check('(yx)', [[1,70000]], pack('Bxxxxxxxq',1,70000))

def test_string(self):
self.check('(ysy)', [[1, 'foo', 2]], pack('Bxxxi3sxB', 1, 3, 'foo', 2))
self.check('(ysy)', [[1, 'foo', 2]], pack('Bxxxi3sxB', 1, 3, b'foo', 2))

def test_substruct(self):
self.check('(y(ii)y)', [[1, [3,4], 2]], pack('BxxxxxxxiiB', 1, 3, 4, 2))
Expand All @@ -360,7 +357,7 @@ def test_byte(self):
self.check('ay', [[1,2,3,4]], pack('iBBBB', 4, 1,2,3,4))

def test_string(self):
self.check('as', [['x', 'foo']], pack('ii2sxxi4s', 16, 1, 'x', 3, 'foo'))
self.check('as', [['x', 'foo']], pack('ii2sxxi4s', 16, 1, b'x', 3, b'foo'))

def test_struct(self):
self.check('a(ii)', [[[1,2],[3,4]]], pack('ixxxxiiii', 16, 1,2,3,4))
Expand All @@ -374,7 +371,7 @@ def test_dict(self):
def test_dict_strings(self):
self.check('a{ss}',
[{'foo':'bar', 'x':'y'}],
pack('ixxxxi4si4si2sxxi2s', 30, 3, 'foo', 3, 'bar', 1, 'x', 1, 'y'))
pack('ixxxxi4si4si2sxxi2s', 30, 3, b'foo', 3, b'bar', 1, b'x', 1, b'y'))

def test_bad_length(self):
self.assertRaises(m.MarshallingError, self.check, 'a(ii)', [[[1,2],[3,4]]], pack('ixxxxiiii', 15, 1,2,3,4))
Expand All @@ -383,10 +380,10 @@ def test_bad_length(self):
class TestVariantUnmarshal(TestUnmarshal):

def test_byte(self):
self.check('v', [1], pack('B2si', 1, 'i', 1))
self.check('v', [1], pack('B2si', 1, b'i', 1))

def test_struct(self):
self.check('v', [[1,2]], pack('B5sxxii', 4, '(ii)', 1,2))
self.check('v', [[1,2]], pack('B5sxxii', 4, b'(ii)', 1,2))



Expand Down
2 changes: 1 addition & 1 deletion gruvi/txdbus/test/test_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class E(message.ErrorMessage):
try:
message.parseMessage(E('foo.bar', 5).rawMessage)
self.assertTrue(False)
except Exception, e:
except Exception as e:
self.assertEquals(str(e), 'Unknown Message Type: 99')


0 comments on commit b2a40db

Please sign in to comment.