Skip to content

Commit 0042510

Browse files
orenmnserhiy-storchaka
authored andcommitted
bpo-29730: replace some calls to PyNumber_Check and improve some error messages (python#650)
1 parent b7c9150 commit 0042510

File tree

5 files changed

+39
-25
lines changed

5 files changed

+39
-25
lines changed

Modules/_io/_iomodule.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -549,14 +549,15 @@ _PyIO_ConvertSsize_t(PyObject *obj, void *result) {
549549
if (obj == Py_None) {
550550
limit = -1;
551551
}
552-
else if (PyNumber_Check(obj)) {
552+
else if (PyIndex_Check(obj)) {
553553
limit = PyNumber_AsSsize_t(obj, PyExc_OverflowError);
554-
if (limit == -1 && PyErr_Occurred())
554+
if (limit == -1 && PyErr_Occurred()) {
555555
return 0;
556+
}
556557
}
557558
else {
558559
PyErr_Format(PyExc_TypeError,
559-
"integer argument expected, got '%.200s'",
560+
"argument should be integer or None, not '%.200s'",
560561
Py_TYPE(obj)->tp_name);
561562
return 0;
562563
}

Modules/_io/bytesio.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -578,12 +578,18 @@ _io_BytesIO_truncate_impl(bytesio *self, PyObject *arg)
578578
/* Truncate to current position if no argument is passed. */
579579
size = self->pos;
580580
}
581-
else {
581+
else if (PyIndex_Check(arg)) {
582582
size = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
583583
if (size == -1 && PyErr_Occurred()) {
584584
return NULL;
585585
}
586586
}
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+
}
587593

588594
if (size < 0) {
589595
PyErr_Format(PyExc_ValueError,

Modules/_io/stringio.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -458,17 +458,19 @@ _io_StringIO_truncate_impl(stringio *self, PyObject *arg)
458458
CHECK_INITIALIZED(self);
459459
CHECK_CLOSED(self);
460460

461-
if (PyNumber_Check(arg)) {
461+
if (PyIndex_Check(arg)) {
462462
size = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
463-
if (size == -1 && PyErr_Occurred())
463+
if (size == -1 && PyErr_Occurred()) {
464464
return NULL;
465+
}
465466
}
466467
else if (arg == Py_None) {
467468
/* Truncate to current position if no argument is passed. */
468469
size = self->pos;
469470
}
470471
else {
471-
PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
472+
PyErr_Format(PyExc_TypeError,
473+
"argument should be integer or None, not '%.200s'",
472474
Py_TYPE(arg)->tp_name);
473475
return NULL;
474476
}

Modules/mmapmodule.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -247,14 +247,15 @@ mmap_convert_ssize_t(PyObject *obj, void *result) {
247247
if (obj == Py_None) {
248248
limit = -1;
249249
}
250-
else if (PyNumber_Check(obj)) {
250+
else if (PyIndex_Check(obj)) {
251251
limit = PyNumber_AsSsize_t(obj, PyExc_OverflowError);
252-
if (limit == -1 && PyErr_Occurred())
252+
if (limit == -1 && PyErr_Occurred()) {
253253
return 0;
254+
}
254255
}
255256
else {
256257
PyErr_Format(PyExc_TypeError,
257-
"integer argument expected, got '%.200s'",
258+
"argument should be integer or None, not '%.200s'",
258259
Py_TYPE(obj)->tp_name);
259260
return 0;
260261
}

Objects/bytes_methods.c

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -399,12 +399,15 @@ _Py_bytes_maketrans(Py_buffer *frm, Py_buffer *to)
399399
#include "stringlib/find.h"
400400

401401
/*
402-
Wraps stringlib_parse_args_finds() and additionally checks whether the
403-
first argument is an integer in range(0, 256).
402+
Wraps stringlib_parse_args_finds() and additionally checks the first
403+
argument type.
404404
405-
If this is the case, writes the integer value to the byte parameter
406-
and sets subobj to NULL. Otherwise, sets the first argument to subobj
407-
and doesn't touch byte. The other parameters are similar to those of
405+
In case the first argument is a bytes-like object, sets it to subobj,
406+
and doesn't touch the byte parameter.
407+
In case it is an integer in range(0, 256), writes the integer value
408+
to byte, and sets subobj to NULL.
409+
410+
The other parameters are similar to those of
408411
stringlib_parse_args_finds().
409412
*/
410413

@@ -415,27 +418,28 @@ parse_args_finds_byte(const char *function_name, PyObject *args,
415418
{
416419
PyObject *tmp_subobj;
417420
Py_ssize_t ival;
418-
PyObject *err;
419421

420422
if(!stringlib_parse_args_finds(function_name, args, &tmp_subobj,
421423
start, end))
422424
return 0;
423425

424-
if (!PyNumber_Check(tmp_subobj)) {
426+
if (PyObject_CheckBuffer(tmp_subobj)) {
425427
*subobj = tmp_subobj;
426428
return 1;
427429
}
428430

429-
ival = PyNumber_AsSsize_t(tmp_subobj, PyExc_OverflowError);
430-
if (ival == -1) {
431-
err = PyErr_Occurred();
432-
if (err && !PyErr_GivenExceptionMatches(err, PyExc_OverflowError)) {
433-
PyErr_Clear();
434-
*subobj = tmp_subobj;
435-
return 1;
436-
}
431+
if (!PyIndex_Check(tmp_subobj)) {
432+
PyErr_Format(PyExc_TypeError,
433+
"argument should be integer or bytes-like object, "
434+
"not '%.200s'",
435+
Py_TYPE(tmp_subobj)->tp_name);
436+
return 0;
437437
}
438438

439+
ival = PyNumber_AsSsize_t(tmp_subobj, NULL);
440+
if (ival == -1 && PyErr_Occurred()) {
441+
return 0;
442+
}
439443
if (ival < 0 || ival > 255) {
440444
PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");
441445
return 0;

0 commit comments

Comments
 (0)