Skip to content

Commit 762bf40

Browse files
bpo-29852: Argument Clinic Py_ssize_t converter now supports None (#716)
if pass `accept={int, NoneType}`.
1 parent ea720fe commit 762bf40

20 files changed

+98
-200
lines changed

Include/abstract.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,6 +1097,9 @@ PyAPI_FUNC(void) _Py_add_one_to_index_F(int nd, Py_ssize_t *index,
10971097
const Py_ssize_t *shape);
10981098
PyAPI_FUNC(void) _Py_add_one_to_index_C(int nd, Py_ssize_t *index,
10991099
const Py_ssize_t *shape);
1100+
1101+
/* Convert Python int to Py_ssize_t. Do nothing if the argument is None. */
1102+
PyAPI_FUNC(int) _Py_convert_optional_to_ssize_t(PyObject *, void *);
11001103
#endif /* !Py_LIMITED_API */
11011104

11021105

Modules/_io/_iomodule.c

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -541,30 +541,6 @@ PyNumber_AsOff_t(PyObject *item, PyObject *err)
541541
}
542542

543543

544-
/* Basically the "n" format code with the ability to turn None into -1. */
545-
int
546-
_PyIO_ConvertSsize_t(PyObject *obj, void *result) {
547-
Py_ssize_t limit;
548-
if (obj == Py_None) {
549-
limit = -1;
550-
}
551-
else if (PyIndex_Check(obj)) {
552-
limit = PyNumber_AsSsize_t(obj, PyExc_OverflowError);
553-
if (limit == -1 && PyErr_Occurred()) {
554-
return 0;
555-
}
556-
}
557-
else {
558-
PyErr_Format(PyExc_TypeError,
559-
"argument should be integer or None, not '%.200s'",
560-
Py_TYPE(obj)->tp_name);
561-
return 0;
562-
}
563-
*((Py_ssize_t *)result) = limit;
564-
return 1;
565-
}
566-
567-
568544
_PyIO_State *
569545
_PyIO_get_module_state(void)
570546
{

Modules/_io/_iomodule.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ PyAPI_DATA(PyObject *) _PyWindowsConsoleIO_Type;
2727
#endif /* MS_WINDOWS */
2828
#endif /* Py_LIMITED_API */
2929

30-
extern int _PyIO_ConvertSsize_t(PyObject *, void *);
31-
3230
/* These functions are used as METH_NOARGS methods, are normally called
3331
* with args=NULL, and return a new reference.
3432
* BUT when args=Py_True is passed, they return a borrowed reference.

Modules/_io/bufferedio.c

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,6 @@ class _io.BufferedRandom "buffered *" "&PyBufferedRandom_Type"
2424
[clinic start generated code]*/
2525
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=59460b9c5639984d]*/
2626

27-
/*[python input]
28-
class io_ssize_t_converter(CConverter):
29-
type = 'Py_ssize_t'
30-
converter = '_PyIO_ConvertSsize_t'
31-
[python start generated code]*/
32-
/*[python end generated code: output=da39a3ee5e6b4b0d input=d0a811d3cbfd1b33]*/
33-
3427
_Py_IDENTIFIER(close);
3528
_Py_IDENTIFIER(_dealloc_warn);
3629
_Py_IDENTIFIER(flush);
@@ -892,13 +885,13 @@ _io__Buffered_peek_impl(buffered *self, Py_ssize_t size)
892885

893886
/*[clinic input]
894887
_io._Buffered.read
895-
size as n: io_ssize_t = -1
888+
size as n: Py_ssize_t(accept={int, NoneType}) = -1
896889
/
897890
[clinic start generated code]*/
898891

899892
static PyObject *
900893
_io__Buffered_read_impl(buffered *self, Py_ssize_t n)
901-
/*[clinic end generated code: output=f41c78bb15b9bbe9 input=c0939ec7f9e9354f]*/
894+
/*[clinic end generated code: output=f41c78bb15b9bbe9 input=7df81e82e08a68a2]*/
902895
{
903896
PyObject *res;
904897

@@ -1206,13 +1199,13 @@ _buffered_readline(buffered *self, Py_ssize_t limit)
12061199

12071200
/*[clinic input]
12081201
_io._Buffered.readline
1209-
size: io_ssize_t = -1
1202+
size: Py_ssize_t(accept={int, NoneType}) = -1
12101203
/
12111204
[clinic start generated code]*/
12121205

12131206
static PyObject *
12141207
_io__Buffered_readline_impl(buffered *self, Py_ssize_t size)
1215-
/*[clinic end generated code: output=24dd2aa6e33be83c input=ff1e0df821cb4e5c]*/
1208+
/*[clinic end generated code: output=24dd2aa6e33be83c input=673b6240e315ef8a]*/
12161209
{
12171210
CHECK_INITIALIZED(self)
12181211
return _buffered_readline(self, size);

Modules/_io/bytesio.c

Lines changed: 9 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,6 @@ 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-
1811
typedef struct {
1912
PyObject_HEAD
2013
PyObject *buf;
@@ -381,7 +374,7 @@ read_bytes(bytesio *self, Py_ssize_t size)
381374

382375
/*[clinic input]
383376
_io.BytesIO.read
384-
size: io_ssize_t = -1
377+
size: Py_ssize_t(accept={int, NoneType}) = -1
385378
/
386379
387380
Read at most size bytes, returned as a bytes object.
@@ -392,7 +385,7 @@ Return an empty bytes object at EOF.
392385

393386
static PyObject *
394387
_io_BytesIO_read_impl(bytesio *self, Py_ssize_t size)
395-
/*[clinic end generated code: output=9cc025f21c75bdd2 input=c81ec53b8f2cc3cf]*/
388+
/*[clinic end generated code: output=9cc025f21c75bdd2 input=74344a39f431c3d7]*/
396389
{
397390
Py_ssize_t n;
398391

@@ -412,7 +405,7 @@ _io_BytesIO_read_impl(bytesio *self, Py_ssize_t size)
412405

413406
/*[clinic input]
414407
_io.BytesIO.read1
415-
size: io_ssize_t = -1
408+
size: Py_ssize_t(accept={int, NoneType}) = -1
416409
/
417410
418411
Read at most size bytes, returned as a bytes object.
@@ -423,14 +416,14 @@ Return an empty bytes object at EOF.
423416

424417
static PyObject *
425418
_io_BytesIO_read1_impl(bytesio *self, Py_ssize_t size)
426-
/*[clinic end generated code: output=d0f843285aa95f1c input=67cf18b142111664]*/
419+
/*[clinic end generated code: output=d0f843285aa95f1c input=440a395bf9129ef5]*/
427420
{
428421
return _io_BytesIO_read_impl(self, size);
429422
}
430423

431424
/*[clinic input]
432425
_io.BytesIO.readline
433-
size: io_ssize_t = -1
426+
size: Py_ssize_t(accept={int, NoneType}) = -1
434427
/
435428
436429
Next line from the file, as a bytes object.
@@ -442,7 +435,7 @@ Return an empty bytes object at EOF.
442435

443436
static PyObject *
444437
_io_BytesIO_readline_impl(bytesio *self, Py_ssize_t size)
445-
/*[clinic end generated code: output=4bff3c251df8ffcd input=7c95bd3f9e9d1646]*/
438+
/*[clinic end generated code: output=4bff3c251df8ffcd input=e7c3fbd1744e2783]*/
446439
{
447440
Py_ssize_t n;
448441

@@ -556,7 +549,7 @@ _io_BytesIO_readinto_impl(bytesio *self, Py_buffer *buffer)
556549

557550
/*[clinic input]
558551
_io.BytesIO.truncate
559-
size as arg: object = None
552+
size: Py_ssize_t(accept={int, NoneType}, c_default="self->pos") = None
560553
/
561554
562555
Truncate the file to at most size bytes.
@@ -566,31 +559,12 @@ The current file position is unchanged. Returns the new size.
566559
[clinic start generated code]*/
567560

568561
static PyObject *
569-
_io_BytesIO_truncate_impl(bytesio *self, PyObject *arg)
570-
/*[clinic end generated code: output=81e6be60e67ddd66 input=11ed1966835462ba]*/
562+
_io_BytesIO_truncate_impl(bytesio *self, Py_ssize_t size)
563+
/*[clinic end generated code: output=9ad17650c15fa09b input=423759dd42d2f7c1]*/
571564
{
572-
Py_ssize_t size;
573-
574565
CHECK_CLOSED(self);
575566
CHECK_EXPORTS(self);
576567

577-
if (arg == Py_None) {
578-
/* Truncate to current position if no argument is passed. */
579-
size = self->pos;
580-
}
581-
else if (PyIndex_Check(arg)) {
582-
size = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
583-
if (size == -1 && PyErr_Occurred()) {
584-
return NULL;
585-
}
586-
}
587-
else {
588-
PyErr_Format(PyExc_TypeError,
589-
"argument should be integer or None, not '%.200s'",
590-
Py_TYPE(arg)->tp_name);
591-
return NULL;
592-
}
593-
594568
if (size < 0) {
595569
PyErr_Format(PyExc_ValueError,
596570
"negative size value %zd", size);

Modules/_io/clinic/bufferedio.c.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ _io__Buffered_read(buffered *self, PyObject **args, Py_ssize_t nargs, PyObject *
134134
Py_ssize_t n = -1;
135135

136136
if (!_PyArg_ParseStack(args, nargs, "|O&:read",
137-
_PyIO_ConvertSsize_t, &n)) {
137+
_Py_convert_optional_to_ssize_t, &n)) {
138138
goto exit;
139139
}
140140

@@ -258,7 +258,7 @@ _io__Buffered_readline(buffered *self, PyObject **args, Py_ssize_t nargs, PyObje
258258
Py_ssize_t size = -1;
259259

260260
if (!_PyArg_ParseStack(args, nargs, "|O&:readline",
261-
_PyIO_ConvertSsize_t, &size)) {
261+
_Py_convert_optional_to_ssize_t, &size)) {
262262
goto exit;
263263
}
264264

@@ -500,4 +500,4 @@ _io_BufferedRandom___init__(PyObject *self, PyObject *args, PyObject *kwargs)
500500
exit:
501501
return return_value;
502502
}
503-
/*[clinic end generated code: output=e37b969b1acaa09c input=a9049054013a1b77]*/
503+
/*[clinic end generated code: output=3cf3262c9b157dc1 input=a9049054013a1b77]*/

Modules/_io/clinic/bytesio.c.h

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ _io_BytesIO_read(bytesio *self, PyObject **args, Py_ssize_t nargs, PyObject *kwn
170170
Py_ssize_t size = -1;
171171

172172
if (!_PyArg_ParseStack(args, nargs, "|O&:read",
173-
_PyIO_ConvertSsize_t, &size)) {
173+
_Py_convert_optional_to_ssize_t, &size)) {
174174
goto exit;
175175
}
176176

@@ -205,7 +205,7 @@ _io_BytesIO_read1(bytesio *self, PyObject **args, Py_ssize_t nargs, PyObject *kw
205205
Py_ssize_t size = -1;
206206

207207
if (!_PyArg_ParseStack(args, nargs, "|O&:read1",
208-
_PyIO_ConvertSsize_t, &size)) {
208+
_Py_convert_optional_to_ssize_t, &size)) {
209209
goto exit;
210210
}
211211

@@ -241,7 +241,7 @@ _io_BytesIO_readline(bytesio *self, PyObject **args, Py_ssize_t nargs, PyObject
241241
Py_ssize_t size = -1;
242242

243243
if (!_PyArg_ParseStack(args, nargs, "|O&:readline",
244-
_PyIO_ConvertSsize_t, &size)) {
244+
_Py_convert_optional_to_ssize_t, &size)) {
245245
goto exit;
246246
}
247247

@@ -339,24 +339,23 @@ PyDoc_STRVAR(_io_BytesIO_truncate__doc__,
339339
{"truncate", (PyCFunction)_io_BytesIO_truncate, METH_FASTCALL, _io_BytesIO_truncate__doc__},
340340

341341
static PyObject *
342-
_io_BytesIO_truncate_impl(bytesio *self, PyObject *arg);
342+
_io_BytesIO_truncate_impl(bytesio *self, Py_ssize_t size);
343343

344344
static PyObject *
345345
_io_BytesIO_truncate(bytesio *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
346346
{
347347
PyObject *return_value = NULL;
348-
PyObject *arg = Py_None;
348+
Py_ssize_t size = self->pos;
349349

350-
if (!_PyArg_UnpackStack(args, nargs, "truncate",
351-
0, 1,
352-
&arg)) {
350+
if (!_PyArg_ParseStack(args, nargs, "|O&:truncate",
351+
_Py_convert_optional_to_ssize_t, &size)) {
353352
goto exit;
354353
}
355354

356355
if (!_PyArg_NoStackKeywords("truncate", kwnames)) {
357356
goto exit;
358357
}
359-
return_value = _io_BytesIO_truncate_impl(self, arg);
358+
return_value = _io_BytesIO_truncate_impl(self, size);
360359

361360
exit:
362361
return return_value;
@@ -469,4 +468,4 @@ _io_BytesIO___init__(PyObject *self, PyObject *args, PyObject *kwargs)
469468
exit:
470469
return return_value;
471470
}
472-
/*[clinic end generated code: output=74a856733a5d55b0 input=a9049054013a1b77]*/
471+
/*[clinic end generated code: output=733795434f838b71 input=a9049054013a1b77]*/

Modules/_io/clinic/fileio.c.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ _io_FileIO_read(fileio *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnam
214214
Py_ssize_t size = -1;
215215

216216
if (!_PyArg_ParseStack(args, nargs, "|O&:read",
217-
_PyIO_ConvertSsize_t, &size)) {
217+
_Py_convert_optional_to_ssize_t, &size)) {
218218
goto exit;
219219
}
220220

@@ -385,4 +385,4 @@ _io_FileIO_isatty(fileio *self, PyObject *Py_UNUSED(ignored))
385385
#ifndef _IO_FILEIO_TRUNCATE_METHODDEF
386386
#define _IO_FILEIO_TRUNCATE_METHODDEF
387387
#endif /* !defined(_IO_FILEIO_TRUNCATE_METHODDEF) */
388-
/*[clinic end generated code: output=034d782a0daa82bd input=a9049054013a1b77]*/
388+
/*[clinic end generated code: output=a4044e2d878248d0 input=a9049054013a1b77]*/

Modules/_io/clinic/iobase.c.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ _io__IOBase_readline(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject
186186
Py_ssize_t limit = -1;
187187

188188
if (!_PyArg_ParseStack(args, nargs, "|O&:readline",
189-
_PyIO_ConvertSsize_t, &limit)) {
189+
_Py_convert_optional_to_ssize_t, &limit)) {
190190
goto exit;
191191
}
192192

@@ -222,7 +222,7 @@ _io__IOBase_readlines(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObjec
222222
Py_ssize_t hint = -1;
223223

224224
if (!_PyArg_ParseStack(args, nargs, "|O&:readlines",
225-
_PyIO_ConvertSsize_t, &hint)) {
225+
_Py_convert_optional_to_ssize_t, &hint)) {
226226
goto exit;
227227
}
228228

@@ -291,4 +291,4 @@ _io__RawIOBase_readall(PyObject *self, PyObject *Py_UNUSED(ignored))
291291
{
292292
return _io__RawIOBase_readall_impl(self);
293293
}
294-
/*[clinic end generated code: output=1bcece367fc7b0cd input=a9049054013a1b77]*/
294+
/*[clinic end generated code: output=d3f59c135231baae input=a9049054013a1b77]*/

Modules/_io/clinic/stringio.c.h

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ _io_StringIO_read(stringio *self, PyObject **args, Py_ssize_t nargs, PyObject *k
6060
Py_ssize_t size = -1;
6161

6262
if (!_PyArg_ParseStack(args, nargs, "|O&:read",
63-
_PyIO_ConvertSsize_t, &size)) {
63+
_Py_convert_optional_to_ssize_t, &size)) {
6464
goto exit;
6565
}
6666

@@ -94,7 +94,7 @@ _io_StringIO_readline(stringio *self, PyObject **args, Py_ssize_t nargs, PyObjec
9494
Py_ssize_t size = -1;
9595

9696
if (!_PyArg_ParseStack(args, nargs, "|O&:readline",
97-
_PyIO_ConvertSsize_t, &size)) {
97+
_Py_convert_optional_to_ssize_t, &size)) {
9898
goto exit;
9999
}
100100

@@ -121,24 +121,23 @@ PyDoc_STRVAR(_io_StringIO_truncate__doc__,
121121
{"truncate", (PyCFunction)_io_StringIO_truncate, METH_FASTCALL, _io_StringIO_truncate__doc__},
122122

123123
static PyObject *
124-
_io_StringIO_truncate_impl(stringio *self, PyObject *arg);
124+
_io_StringIO_truncate_impl(stringio *self, Py_ssize_t size);
125125

126126
static PyObject *
127127
_io_StringIO_truncate(stringio *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
128128
{
129129
PyObject *return_value = NULL;
130-
PyObject *arg = Py_None;
130+
Py_ssize_t size = self->pos;
131131

132-
if (!_PyArg_UnpackStack(args, nargs, "truncate",
133-
0, 1,
134-
&arg)) {
132+
if (!_PyArg_ParseStack(args, nargs, "|O&:truncate",
133+
_Py_convert_optional_to_ssize_t, &size)) {
135134
goto exit;
136135
}
137136

138137
if (!_PyArg_NoStackKeywords("truncate", kwnames)) {
139138
goto exit;
140139
}
141-
return_value = _io_StringIO_truncate_impl(self, arg);
140+
return_value = _io_StringIO_truncate_impl(self, size);
142141

143142
exit:
144143
return return_value;
@@ -303,4 +302,4 @@ _io_StringIO_seekable(stringio *self, PyObject *Py_UNUSED(ignored))
303302
{
304303
return _io_StringIO_seekable_impl(self);
305304
}
306-
/*[clinic end generated code: output=965fe9cb0d11511a input=a9049054013a1b77]*/
305+
/*[clinic end generated code: output=03429d95ed7cd92f input=a9049054013a1b77]*/

0 commit comments

Comments
 (0)