Skip to content

Commit 3ab64bf

Browse files
Merge pull request #62 from benoit-pierre/fix_python3_buffer_abstraction
protocol/display: fix Python 3 buffer abstraction
2 parents 9ffdb29 + 95ba513 commit 3ab64bf

2 files changed

Lines changed: 59 additions & 8 deletions

File tree

Xlib/protocol/display.py

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,36 @@
4242
from . import event
4343

4444
if PY3:
45-
def buffer(object, offset=None, size=None):
46-
if offset is None:
47-
offset = 0
45+
46+
class bytesview(object):
47+
48+
def __init__(self, data, offset=0, size=None):
49+
if size is None:
50+
size = len(data)-offset
51+
if isinstance(data, bytes):
52+
view = memoryview(data)
53+
elif isinstance(data, bytesview):
54+
view = data.view
55+
else:
56+
raise TypeError('unsupported type: {}'.format(type(data)))
57+
self.view = view[offset:offset+size]
58+
59+
def __len__(self):
60+
return len(self.view)
61+
62+
def __getitem__(self, key):
63+
if isinstance(key, slice):
64+
return bytes(self.view[key])
65+
return self.view[key]
66+
67+
else:
68+
69+
def bytesview(data, offset=0, size=None):
70+
if not isinstance(data, (bytes, buffer)):
71+
raise TypeError('unsupported type: {}'.format(type(data)))
4872
if size is None:
49-
size = len(object)-offset
50-
return memoryview(object)[offset:offset+size]
73+
size = len(data)-offset
74+
return buffer(data, offset, size)
5175

5276

5377
class Display(object):
@@ -706,7 +730,7 @@ def parse_error_response(self, request):
706730
estruct = self.error_classes.get(code, error.XError)
707731

708732
e = estruct(self, self.data_recv[:32])
709-
self.data_recv = buffer(self.data_recv, 32)
733+
self.data_recv = bytesview(self.data_recv, 32)
710734

711735
# print 'recv Error:', e
712736

@@ -760,7 +784,7 @@ def parse_request_response(self, request):
760784
req._parse_response(self.data_recv[:self.recv_packet_len])
761785
# print 'recv Request:', req
762786

763-
self.data_recv = buffer(self.data_recv, self.recv_packet_len)
787+
self.data_recv = bytesview(self.data_recv, self.recv_packet_len)
764788
self.recv_packet_len = 0
765789

766790

@@ -797,7 +821,7 @@ def parse_event_response(self, etype):
797821
if etype == ge.GenericEventCode:
798822
self.recv_packet_len = 0
799823

800-
self.data_recv = buffer(self.data_recv, length)
824+
self.data_recv = bytesview(self.data_recv, length)
801825

802826
# Drop all requests having an error handler,
803827
# but which obviously succeded.

test/test_bytesview.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
2+
import unittest
3+
4+
# Python 2/3 compatibility.
5+
from six import indexbytes, text_type
6+
7+
from Xlib.protocol.display import bytesview
8+
9+
10+
class BytesViewTest(unittest.TestCase):
11+
12+
def test(self):
13+
with self.assertRaises(TypeError):
14+
bytesview(text_type('foobar'))
15+
data = b'0123456789ABCDEF'
16+
view = bytesview(data)
17+
self.assertEqual(len(view), 16)
18+
self.assertEqual(view[:], data)
19+
self.assertIsInstance(view[:], bytes)
20+
self.assertEqual(view[5:-6], b'56789')
21+
self.assertEqual(indexbytes(view, 7), ord('7'))
22+
view = bytesview(view, 5)
23+
self.assertEqual(view[:], b'56789ABCDEF')
24+
self.assertEqual(indexbytes(view, 4), ord('9'))
25+
view = bytesview(view, 0, 5)
26+
self.assertEqual(view[:], b'56789')
27+
self.assertEqual(indexbytes(view, 1), ord('6'))

0 commit comments

Comments
 (0)