Skip to content

Commit 7400254

Browse files
orenmnserhiy-storchaka
authored andcommitted
bpo-29741: Clean up C implementations of BytesIO and StringIO. (python#606)
Some BytesIO methods now accept not just int subclasses but other int-like types.
1 parent 7e52c3e commit 7400254

File tree

4 files changed

+68
-120
lines changed

4 files changed

+68
-120
lines changed

Modules/_io/bytesio.c

Lines changed: 23 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ class _io.BytesIO "bytesio *" "&PyBytesIO_Type"
88
[clinic start generated code]*/
99
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=7f50ec034f5c0b26]*/
1010

11+
/*[python input]
12+
class io_ssize_t_converter(CConverter):
13+
type = 'Py_ssize_t'
14+
converter = '_PyIO_ConvertSsize_t'
15+
[python start generated code]*/
16+
/*[python end generated code: output=da39a3ee5e6b4b0d input=d0a811d3cbfd1b33]*/
17+
1118
typedef struct {
1219
PyObject_HEAD
1320
PyObject *buf;
@@ -374,7 +381,7 @@ read_bytes(bytesio *self, Py_ssize_t size)
374381

375382
/*[clinic input]
376383
_io.BytesIO.read
377-
size as arg: object = None
384+
size: io_ssize_t = -1
378385
/
379386
380387
Read at most size bytes, returned as a bytes object.
@@ -384,28 +391,13 @@ Return an empty bytes object at EOF.
384391
[clinic start generated code]*/
385392

386393
static PyObject *
387-
_io_BytesIO_read_impl(bytesio *self, PyObject *arg)
388-
/*[clinic end generated code: output=85dacb535c1e1781 input=cc7ba4a797bb1555]*/
394+
_io_BytesIO_read_impl(bytesio *self, Py_ssize_t size)
395+
/*[clinic end generated code: output=9cc025f21c75bdd2 input=c81ec53b8f2cc3cf]*/
389396
{
390-
Py_ssize_t size, n;
397+
Py_ssize_t n;
391398

392399
CHECK_CLOSED(self);
393400

394-
if (PyLong_Check(arg)) {
395-
size = PyLong_AsSsize_t(arg);
396-
if (size == -1 && PyErr_Occurred())
397-
return NULL;
398-
}
399-
else if (arg == Py_None) {
400-
/* Read until EOF is reached, by default. */
401-
size = -1;
402-
}
403-
else {
404-
PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
405-
Py_TYPE(arg)->tp_name);
406-
return NULL;
407-
}
408-
409401
/* adjust invalid sizes */
410402
n = self->string_size - self->pos;
411403
if (size < 0 || size > n) {
@@ -420,7 +412,7 @@ _io_BytesIO_read_impl(bytesio *self, PyObject *arg)
420412

421413
/*[clinic input]
422414
_io.BytesIO.read1
423-
size: object(c_default="Py_None") = -1
415+
size: io_ssize_t = -1
424416
/
425417
426418
Read at most size bytes, returned as a bytes object.
@@ -430,15 +422,15 @@ Return an empty bytes object at EOF.
430422
[clinic start generated code]*/
431423

432424
static PyObject *
433-
_io_BytesIO_read1_impl(bytesio *self, PyObject *size)
434-
/*[clinic end generated code: output=a60d80c84c81a6b8 input=0951874bafee8e80]*/
425+
_io_BytesIO_read1_impl(bytesio *self, Py_ssize_t size)
426+
/*[clinic end generated code: output=d0f843285aa95f1c input=67cf18b142111664]*/
435427
{
436428
return _io_BytesIO_read_impl(self, size);
437429
}
438430

439431
/*[clinic input]
440432
_io.BytesIO.readline
441-
size as arg: object = None
433+
size: io_ssize_t = -1
442434
/
443435
444436
Next line from the file, as a bytes object.
@@ -449,28 +441,13 @@ Return an empty bytes object at EOF.
449441
[clinic start generated code]*/
450442

451443
static PyObject *
452-
_io_BytesIO_readline_impl(bytesio *self, PyObject *arg)
453-
/*[clinic end generated code: output=1c2115534a4f9276 input=ca31f06de6eab257]*/
444+
_io_BytesIO_readline_impl(bytesio *self, Py_ssize_t size)
445+
/*[clinic end generated code: output=4bff3c251df8ffcd input=7c95bd3f9e9d1646]*/
454446
{
455-
Py_ssize_t size, n;
447+
Py_ssize_t n;
456448

457449
CHECK_CLOSED(self);
458450

459-
if (PyLong_Check(arg)) {
460-
size = PyLong_AsSsize_t(arg);
461-
if (size == -1 && PyErr_Occurred())
462-
return NULL;
463-
}
464-
else if (arg == Py_None) {
465-
/* No size limit, by default. */
466-
size = -1;
467-
}
468-
else {
469-
PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
470-
Py_TYPE(arg)->tp_name);
471-
return NULL;
472-
}
473-
474451
n = scan_eol(self, size);
475452

476453
return read_bytes(self, n);
@@ -597,19 +574,15 @@ _io_BytesIO_truncate_impl(bytesio *self, PyObject *arg)
597574
CHECK_CLOSED(self);
598575
CHECK_EXPORTS(self);
599576

600-
if (PyLong_Check(arg)) {
601-
size = PyLong_AsSsize_t(arg);
602-
if (size == -1 && PyErr_Occurred())
603-
return NULL;
604-
}
605-
else if (arg == Py_None) {
577+
if (arg == Py_None) {
606578
/* Truncate to current position if no argument is passed. */
607579
size = self->pos;
608580
}
609581
else {
610-
PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
611-
Py_TYPE(arg)->tp_name);
612-
return NULL;
582+
size = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
583+
if (size == -1 && PyErr_Occurred()) {
584+
return NULL;
585+
}
613586
}
614587

615588
if (size < 0) {

Modules/_io/clinic/bytesio.c.h

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ _io_BytesIO_tell(bytesio *self, PyObject *Py_UNUSED(ignored))
149149
}
150150

151151
PyDoc_STRVAR(_io_BytesIO_read__doc__,
152-
"read($self, size=None, /)\n"
152+
"read($self, size=-1, /)\n"
153153
"--\n"
154154
"\n"
155155
"Read at most size bytes, returned as a bytes object.\n"
@@ -161,24 +161,23 @@ PyDoc_STRVAR(_io_BytesIO_read__doc__,
161161
{"read", (PyCFunction)_io_BytesIO_read, METH_FASTCALL, _io_BytesIO_read__doc__},
162162

163163
static PyObject *
164-
_io_BytesIO_read_impl(bytesio *self, PyObject *arg);
164+
_io_BytesIO_read_impl(bytesio *self, Py_ssize_t size);
165165

166166
static PyObject *
167167
_io_BytesIO_read(bytesio *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
168168
{
169169
PyObject *return_value = NULL;
170-
PyObject *arg = Py_None;
170+
Py_ssize_t size = -1;
171171

172-
if (!_PyArg_UnpackStack(args, nargs, "read",
173-
0, 1,
174-
&arg)) {
172+
if (!_PyArg_ParseStack(args, nargs, "|O&:read",
173+
_PyIO_ConvertSsize_t, &size)) {
175174
goto exit;
176175
}
177176

178177
if (!_PyArg_NoStackKeywords("read", kwnames)) {
179178
goto exit;
180179
}
181-
return_value = _io_BytesIO_read_impl(self, arg);
180+
return_value = _io_BytesIO_read_impl(self, size);
182181

183182
exit:
184183
return return_value;
@@ -197,17 +196,16 @@ PyDoc_STRVAR(_io_BytesIO_read1__doc__,
197196
{"read1", (PyCFunction)_io_BytesIO_read1, METH_FASTCALL, _io_BytesIO_read1__doc__},
198197

199198
static PyObject *
200-
_io_BytesIO_read1_impl(bytesio *self, PyObject *size);
199+
_io_BytesIO_read1_impl(bytesio *self, Py_ssize_t size);
201200

202201
static PyObject *
203202
_io_BytesIO_read1(bytesio *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
204203
{
205204
PyObject *return_value = NULL;
206-
PyObject *size = Py_None;
205+
Py_ssize_t size = -1;
207206

208-
if (!_PyArg_UnpackStack(args, nargs, "read1",
209-
0, 1,
210-
&size)) {
207+
if (!_PyArg_ParseStack(args, nargs, "|O&:read1",
208+
_PyIO_ConvertSsize_t, &size)) {
211209
goto exit;
212210
}
213211

@@ -221,7 +219,7 @@ _io_BytesIO_read1(bytesio *self, PyObject **args, Py_ssize_t nargs, PyObject *kw
221219
}
222220

223221
PyDoc_STRVAR(_io_BytesIO_readline__doc__,
224-
"readline($self, size=None, /)\n"
222+
"readline($self, size=-1, /)\n"
225223
"--\n"
226224
"\n"
227225
"Next line from the file, as a bytes object.\n"
@@ -234,24 +232,23 @@ PyDoc_STRVAR(_io_BytesIO_readline__doc__,
234232
{"readline", (PyCFunction)_io_BytesIO_readline, METH_FASTCALL, _io_BytesIO_readline__doc__},
235233

236234
static PyObject *
237-
_io_BytesIO_readline_impl(bytesio *self, PyObject *arg);
235+
_io_BytesIO_readline_impl(bytesio *self, Py_ssize_t size);
238236

239237
static PyObject *
240238
_io_BytesIO_readline(bytesio *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
241239
{
242240
PyObject *return_value = NULL;
243-
PyObject *arg = Py_None;
241+
Py_ssize_t size = -1;
244242

245-
if (!_PyArg_UnpackStack(args, nargs, "readline",
246-
0, 1,
247-
&arg)) {
243+
if (!_PyArg_ParseStack(args, nargs, "|O&:readline",
244+
_PyIO_ConvertSsize_t, &size)) {
248245
goto exit;
249246
}
250247

251248
if (!_PyArg_NoStackKeywords("readline", kwnames)) {
252249
goto exit;
253250
}
254-
return_value = _io_BytesIO_readline_impl(self, arg);
251+
return_value = _io_BytesIO_readline_impl(self, size);
255252

256253
exit:
257254
return return_value;
@@ -472,4 +469,4 @@ _io_BytesIO___init__(PyObject *self, PyObject *args, PyObject *kwargs)
472469
exit:
473470
return return_value;
474471
}
475-
/*[clinic end generated code: output=138ee6ad6951bc84 input=a9049054013a1b77]*/
472+
/*[clinic end generated code: output=74a856733a5d55b0 input=a9049054013a1b77]*/

Modules/_io/clinic/stringio.c.h

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ _io_StringIO_tell(stringio *self, PyObject *Py_UNUSED(ignored))
3939
}
4040

4141
PyDoc_STRVAR(_io_StringIO_read__doc__,
42-
"read($self, size=None, /)\n"
42+
"read($self, size=-1, /)\n"
4343
"--\n"
4444
"\n"
4545
"Read at most size characters, returned as a string.\n"
@@ -51,31 +51,30 @@ PyDoc_STRVAR(_io_StringIO_read__doc__,
5151
{"read", (PyCFunction)_io_StringIO_read, METH_FASTCALL, _io_StringIO_read__doc__},
5252

5353
static PyObject *
54-
_io_StringIO_read_impl(stringio *self, PyObject *arg);
54+
_io_StringIO_read_impl(stringio *self, Py_ssize_t size);
5555

5656
static PyObject *
5757
_io_StringIO_read(stringio *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
5858
{
5959
PyObject *return_value = NULL;
60-
PyObject *arg = Py_None;
60+
Py_ssize_t size = -1;
6161

62-
if (!_PyArg_UnpackStack(args, nargs, "read",
63-
0, 1,
64-
&arg)) {
62+
if (!_PyArg_ParseStack(args, nargs, "|O&:read",
63+
_PyIO_ConvertSsize_t, &size)) {
6564
goto exit;
6665
}
6766

6867
if (!_PyArg_NoStackKeywords("read", kwnames)) {
6968
goto exit;
7069
}
71-
return_value = _io_StringIO_read_impl(self, arg);
70+
return_value = _io_StringIO_read_impl(self, size);
7271

7372
exit:
7473
return return_value;
7574
}
7675

7776
PyDoc_STRVAR(_io_StringIO_readline__doc__,
78-
"readline($self, size=None, /)\n"
77+
"readline($self, size=-1, /)\n"
7978
"--\n"
8079
"\n"
8180
"Read until newline or EOF.\n"
@@ -86,24 +85,23 @@ PyDoc_STRVAR(_io_StringIO_readline__doc__,
8685
{"readline", (PyCFunction)_io_StringIO_readline, METH_FASTCALL, _io_StringIO_readline__doc__},
8786

8887
static PyObject *
89-
_io_StringIO_readline_impl(stringio *self, PyObject *arg);
88+
_io_StringIO_readline_impl(stringio *self, Py_ssize_t size);
9089

9190
static PyObject *
9291
_io_StringIO_readline(stringio *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
9392
{
9493
PyObject *return_value = NULL;
95-
PyObject *arg = Py_None;
94+
Py_ssize_t size = -1;
9695

97-
if (!_PyArg_UnpackStack(args, nargs, "readline",
98-
0, 1,
99-
&arg)) {
96+
if (!_PyArg_ParseStack(args, nargs, "|O&:readline",
97+
_PyIO_ConvertSsize_t, &size)) {
10098
goto exit;
10199
}
102100

103101
if (!_PyArg_NoStackKeywords("readline", kwnames)) {
104102
goto exit;
105103
}
106-
return_value = _io_StringIO_readline_impl(self, arg);
104+
return_value = _io_StringIO_readline_impl(self, size);
107105

108106
exit:
109107
return return_value;
@@ -305,4 +303,4 @@ _io_StringIO_seekable(stringio *self, PyObject *Py_UNUSED(ignored))
305303
{
306304
return _io_StringIO_seekable_impl(self);
307305
}
308-
/*[clinic end generated code: output=ce8018ec29def422 input=a9049054013a1b77]*/
306+
/*[clinic end generated code: output=965fe9cb0d11511a input=a9049054013a1b77]*/

0 commit comments

Comments
 (0)