Skip to content

Commit de50360

Browse files
orenmnzooba
authored andcommitted
bpo-29741: Update some methods in the _pyio module to also accept integer types. Patch by Oren Milman. (#560)
1 parent 13614e3 commit de50360

File tree

3 files changed

+68
-14
lines changed

3 files changed

+68
-14
lines changed

Lib/_pyio.py

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -504,8 +504,13 @@ def nreadahead():
504504
return 1
505505
if size is None:
506506
size = -1
507-
elif not isinstance(size, int):
508-
raise TypeError("size must be an integer")
507+
else:
508+
try:
509+
size_index = size.__index__
510+
except AttributeError:
511+
raise TypeError(f"{size!r} is not an integer")
512+
else:
513+
size = size_index()
509514
res = bytearray()
510515
while size < 0 or len(res) < size:
511516
b = self.read(nreadahead())
@@ -868,6 +873,13 @@ def read(self, size=-1):
868873
raise ValueError("read from closed file")
869874
if size is None:
870875
size = -1
876+
else:
877+
try:
878+
size_index = size.__index__
879+
except AttributeError:
880+
raise TypeError(f"{size!r} is not an integer")
881+
else:
882+
size = size_index()
871883
if size < 0:
872884
size = len(self._buffer)
873885
if len(self._buffer) <= self._pos:
@@ -905,9 +917,11 @@ def seek(self, pos, whence=0):
905917
if self.closed:
906918
raise ValueError("seek on closed file")
907919
try:
908-
pos.__index__
909-
except AttributeError as err:
910-
raise TypeError("an integer is required") from err
920+
pos_index = pos.__index__
921+
except AttributeError:
922+
raise TypeError(f"{pos!r} is not an integer")
923+
else:
924+
pos = pos_index()
911925
if whence == 0:
912926
if pos < 0:
913927
raise ValueError("negative seek position %r" % (pos,))
@@ -932,9 +946,11 @@ def truncate(self, pos=None):
932946
pos = self._pos
933947
else:
934948
try:
935-
pos.__index__
936-
except AttributeError as err:
937-
raise TypeError("an integer is required") from err
949+
pos_index = pos.__index__
950+
except AttributeError:
951+
raise TypeError(f"{pos!r} is not an integer")
952+
else:
953+
pos = pos_index()
938954
if pos < 0:
939955
raise ValueError("negative truncate position %r" % (pos,))
940956
del self._buffer[pos:]
@@ -2378,11 +2394,14 @@ def read(self, size=None):
23782394
self._checkReadable()
23792395
if size is None:
23802396
size = -1
2397+
else:
2398+
try:
2399+
size_index = size.__index__
2400+
except AttributeError:
2401+
raise TypeError(f"{size!r} is not an integer")
2402+
else:
2403+
size = size_index()
23812404
decoder = self._decoder or self._get_decoder()
2382-
try:
2383-
size.__index__
2384-
except AttributeError as err:
2385-
raise TypeError("an integer is required") from err
23862405
if size < 0:
23872406
# Read everything.
23882407
result = (self._get_decoded_chars() +
@@ -2413,8 +2432,13 @@ def readline(self, size=None):
24132432
raise ValueError("read from closed file")
24142433
if size is None:
24152434
size = -1
2416-
elif not isinstance(size, int):
2417-
raise TypeError("size must be an integer")
2435+
else:
2436+
try:
2437+
size_index = size.__index__
2438+
except AttributeError:
2439+
raise TypeError(f"{size!r} is not an integer")
2440+
else:
2441+
size = size_index()
24182442

24192443
# Grab all the decoded text (we will rewind any extra bits later).
24202444
line = self._get_decoded_chars()

Lib/test/test_memoryio.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@
1111
import pickle
1212
import sys
1313

14+
class IntLike:
15+
def __init__(self, num):
16+
self._num = num
17+
def __index__(self):
18+
return self._num
19+
__int__ = __index__
20+
1421
class MemorySeekTestMixin:
1522

1623
def testInit(self):
@@ -116,7 +123,10 @@ def test_truncate(self):
116123
memio = self.ioclass(buf)
117124

118125
self.assertRaises(ValueError, memio.truncate, -1)
126+
self.assertRaises(ValueError, memio.truncate, IntLike(-1))
119127
memio.seek(6)
128+
self.assertEqual(memio.truncate(IntLike(8)), 8)
129+
self.assertEqual(memio.getvalue(), buf[:8])
120130
self.assertEqual(memio.truncate(), 6)
121131
self.assertEqual(memio.getvalue(), buf[:6])
122132
self.assertEqual(memio.truncate(4), 4)
@@ -131,6 +141,7 @@ def test_truncate(self):
131141
self.assertRaises(TypeError, memio.truncate, '0')
132142
memio.close()
133143
self.assertRaises(ValueError, memio.truncate, 0)
144+
self.assertRaises(ValueError, memio.truncate, IntLike(0))
134145

135146
def test_init(self):
136147
buf = self.buftype("1234567890")
@@ -154,12 +165,19 @@ def test_read(self):
154165
self.assertEqual(memio.read(900), buf[5:])
155166
self.assertEqual(memio.read(), self.EOF)
156167
memio.seek(0)
168+
self.assertEqual(memio.read(IntLike(0)), self.EOF)
169+
self.assertEqual(memio.read(IntLike(1)), buf[:1])
170+
self.assertEqual(memio.read(IntLike(4)), buf[1:5])
171+
self.assertEqual(memio.read(IntLike(900)), buf[5:])
172+
memio.seek(0)
157173
self.assertEqual(memio.read(), buf)
158174
self.assertEqual(memio.read(), self.EOF)
159175
self.assertEqual(memio.tell(), 10)
160176
memio.seek(0)
161177
self.assertEqual(memio.read(-1), buf)
162178
memio.seek(0)
179+
self.assertEqual(memio.read(IntLike(-1)), buf)
180+
memio.seek(0)
163181
self.assertEqual(type(memio.read()), type(buf))
164182
memio.seek(100)
165183
self.assertEqual(type(memio.read()), type(buf))
@@ -169,6 +187,8 @@ def test_read(self):
169187
memio.seek(len(buf) + 1)
170188
self.assertEqual(memio.read(1), self.EOF)
171189
memio.seek(len(buf) + 1)
190+
self.assertEqual(memio.read(IntLike(1)), self.EOF)
191+
memio.seek(len(buf) + 1)
172192
self.assertEqual(memio.read(), self.EOF)
173193
memio.close()
174194
self.assertRaises(ValueError, memio.read)
@@ -178,6 +198,7 @@ def test_readline(self):
178198
memio = self.ioclass(buf * 2)
179199

180200
self.assertEqual(memio.readline(0), self.EOF)
201+
self.assertEqual(memio.readline(IntLike(0)), self.EOF)
181202
self.assertEqual(memio.readline(), buf)
182203
self.assertEqual(memio.readline(), buf)
183204
self.assertEqual(memio.readline(), self.EOF)
@@ -186,9 +207,16 @@ def test_readline(self):
186207
self.assertEqual(memio.readline(5), buf[5:10])
187208
self.assertEqual(memio.readline(5), buf[10:15])
188209
memio.seek(0)
210+
self.assertEqual(memio.readline(IntLike(5)), buf[:5])
211+
self.assertEqual(memio.readline(IntLike(5)), buf[5:10])
212+
self.assertEqual(memio.readline(IntLike(5)), buf[10:15])
213+
memio.seek(0)
189214
self.assertEqual(memio.readline(-1), buf)
190215
memio.seek(0)
216+
self.assertEqual(memio.readline(IntLike(-1)), buf)
217+
memio.seek(0)
191218
self.assertEqual(memio.readline(0), self.EOF)
219+
self.assertEqual(memio.readline(IntLike(0)), self.EOF)
192220
# Issue #24989: Buffer overread
193221
memio.seek(len(buf) * 2 + 1)
194222
self.assertEqual(memio.readline(), self.EOF)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Update some methods in the _pyio module to also accept integer types. Patch
2+
by Oren Milman.

0 commit comments

Comments
 (0)