Skip to content

Commit 338f557

Browse files
committed
bpo-37337: Add _PyObject_CallMethodNoArgs()
1 parent d1bd6e7 commit 338f557

37 files changed

+156
-132
lines changed

Doc/c-api/object.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,17 @@ Object Protocol
353353
*NULL* on failure.
354354
355355
356+
.. c:function:: PyObject* _PyObject_CallMethodNoArgs(PyObject *obj, PyObject *name)
357+
358+
Call a method of the Python object *obj* without arguments,
359+
where the name of the method is given as a Python string object in *name*.
360+
361+
Return the result of the call on success, or raise an exception and return
362+
*NULL* on failure.
363+
364+
.. versionadded:: 3.9
365+
366+
356367
.. c:function:: PyObject* _PyObject_Vectorcall(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames)
357368
358369
Call a callable Python object *callable*, using

Include/cpython/abstract.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,14 @@ PyAPI_FUNC(PyObject *) _PyObject_VectorcallMethod(
162162
PyObject *name, PyObject *const *args,
163163
size_t nargsf, PyObject *kwnames);
164164

165+
static inline PyObject *
166+
_PyObject_CallMethodNoArgs(PyObject *self, PyObject *name)
167+
{
168+
PyObject *args[1] = {self};
169+
return _PyObject_VectorcallMethod(name, args,
170+
1 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
171+
}
172+
165173
/* Like PyObject_CallMethod(), but expect a _Py_Identifier*
166174
as the method name. */
167175
PyAPI_FUNC(PyObject *) _PyObject_CallMethodId(PyObject *obj,
@@ -190,6 +198,14 @@ _PyObject_VectorcallMethodId(
190198
return _PyObject_VectorcallMethod(oname, args, nargsf, kwnames);
191199
}
192200

201+
static inline PyObject *
202+
_PyObject_CallMethodIdNoArgs(PyObject *self, _Py_Identifier *name)
203+
{
204+
PyObject *args[1] = {self};
205+
return _PyObject_VectorcallMethodId(name, args,
206+
1 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
207+
}
208+
193209
PyAPI_FUNC(int) _PyObject_HasLen(PyObject *o);
194210

195211
/* Guess the size of object 'o' using len(o) or o.__length_hint__().
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
Add :c:func:`_PyObject_VectorcallMethod` for fast calling of methods.
1+
Add fast functions for calling methods: :c:func:`_PyObject_VectorcallMethod`
2+
and :c:func:`_PyObject_CallMethodNoArgs`

Modules/_asynciomodule.c

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ get_event_loop(void)
333333
return NULL;
334334
}
335335

336-
loop = _PyObject_CallMethodId(policy, &PyId_get_event_loop, NULL);
336+
loop = _PyObject_CallMethodIdNoArgs(policy, &PyId_get_event_loop);
337337
Py_DECREF(policy);
338338
return loop;
339339
}
@@ -494,7 +494,7 @@ future_init(FutureObj *fut, PyObject *loop)
494494
}
495495
fut->fut_loop = loop;
496496

497-
res = _PyObject_CallMethodId(fut->fut_loop, &PyId_get_debug, NULL);
497+
res = _PyObject_CallMethodIdNoArgs(fut->fut_loop, &PyId_get_debug);
498498
if (res == NULL) {
499499
return -1;
500500
}
@@ -1297,9 +1297,8 @@ FutureObj_repr(FutureObj *fut)
12971297

12981298
ENSURE_FUTURE_ALIVE(fut)
12991299

1300-
PyObject *rinfo = _PyObject_CallMethodIdObjArgs((PyObject*)fut,
1301-
&PyId__repr_info,
1302-
NULL);
1300+
PyObject *rinfo = _PyObject_CallMethodIdNoArgs((PyObject*)fut,
1301+
&PyId__repr_info);
13031302
if (rinfo == NULL) {
13041303
return NULL;
13051304
}
@@ -2200,8 +2199,7 @@ _asyncio_Task_cancel_impl(TaskObj *self)
22002199
PyObject *res;
22012200
int is_true;
22022201

2203-
res = _PyObject_CallMethodId(
2204-
self->task_fut_waiter, &PyId_cancel, NULL);
2202+
res = _PyObject_CallMethodIdNoArgs(self->task_fut_waiter, &PyId_cancel);
22052203
if (res == NULL) {
22062204
return NULL;
22072205
}
@@ -2738,7 +2736,7 @@ task_step_impl(TaskObj *task, PyObject *exc)
27382736
if (task->task_must_cancel) {
27392737
PyObject *r;
27402738
int is_true;
2741-
r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
2739+
r = _PyObject_CallMethodIdNoArgs(result, &PyId_cancel);
27422740
if (r == NULL) {
27432741
return NULL;
27442742
}
@@ -2829,7 +2827,7 @@ task_step_impl(TaskObj *task, PyObject *exc)
28292827
if (task->task_must_cancel) {
28302828
PyObject *r;
28312829
int is_true;
2832-
r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
2830+
r = _PyObject_CallMethodIdNoArgs(result, &PyId_cancel);
28332831
if (r == NULL) {
28342832
return NULL;
28352833
}

Modules/_collectionsmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2040,7 +2040,7 @@ defdict_reduce(defdictobject *dd, PyObject *Py_UNUSED(ignored))
20402040
args = PyTuple_Pack(1, dd->default_factory);
20412041
if (args == NULL)
20422042
return NULL;
2043-
items = _PyObject_CallMethodId((PyObject *)dd, &PyId_items, NULL);
2043+
items = _PyObject_CallMethodIdNoArgs((PyObject *)dd, &PyId_items);
20442044
if (items == NULL) {
20452045
Py_DECREF(args);
20462046
return NULL;

Modules/_ctypes/_ctypes.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3974,7 +3974,7 @@ _build_result(PyObject *result, PyObject *callargs,
39743974
_Py_IDENTIFIER(__ctypes_from_outparam__);
39753975

39763976
v = PyTuple_GET_ITEM(callargs, i);
3977-
v = _PyObject_CallMethodId(v, &PyId___ctypes_from_outparam__, NULL);
3977+
v = _PyObject_CallMethodIdNoArgs(v, &PyId___ctypes_from_outparam__);
39783978
if (v == NULL || numretvals == 1) {
39793979
Py_DECREF(callargs);
39803980
return v;

Modules/_cursesmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2906,7 +2906,7 @@ _curses_getwin(PyObject *module, PyObject *file)
29062906
if (_Py_set_inheritable(fileno(fp), 0, NULL) < 0)
29072907
goto error;
29082908

2909-
data = _PyObject_CallMethodId(file, &PyId_read, NULL);
2909+
data = _PyObject_CallMethodIdNoArgs(file, &PyId_read);
29102910
if (data == NULL)
29112911
goto error;
29122912
if (!PyBytes_Check(data)) {

Modules/_datetimemodule.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1659,7 +1659,7 @@ time_time(void)
16591659
if (time != NULL) {
16601660
_Py_IDENTIFIER(time);
16611661

1662-
result = _PyObject_CallMethodId(time, &PyId_time, NULL);
1662+
result = _PyObject_CallMethodIdNoArgs(time, &PyId_time);
16631663
Py_DECREF(time);
16641664
}
16651665
return result;
@@ -1918,7 +1918,7 @@ get_float_as_integer_ratio(PyObject *floatobj)
19181918
PyObject *ratio;
19191919

19201920
assert(floatobj && PyFloat_Check(floatobj));
1921-
ratio = _PyObject_CallMethodId(floatobj, &PyId_as_integer_ratio, NULL);
1921+
ratio = _PyObject_CallMethodIdNoArgs(floatobj, &PyId_as_integer_ratio);
19221922
if (ratio == NULL) {
19231923
return NULL;
19241924
}
@@ -3162,7 +3162,7 @@ date_isoformat(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored))
31623162
static PyObject *
31633163
date_str(PyDateTime_Date *self)
31643164
{
3165-
return _PyObject_CallMethodId((PyObject *)self, &PyId_isoformat, NULL);
3165+
return _PyObject_CallMethodIdNoArgs((PyObject *)self, &PyId_isoformat);
31663166
}
31673167

31683168

@@ -3188,7 +3188,7 @@ date_strftime(PyDateTime_Date *self, PyObject *args, PyObject *kw)
31883188
&format))
31893189
return NULL;
31903190

3191-
tuple = _PyObject_CallMethodId((PyObject *)self, &PyId_timetuple, NULL);
3191+
tuple = _PyObject_CallMethodIdNoArgs((PyObject *)self, &PyId_timetuple);
31923192
if (tuple == NULL)
31933193
return NULL;
31943194
result = wrap_strftime((PyObject *)self, format, tuple,
@@ -4175,7 +4175,7 @@ time_repr(PyDateTime_Time *self)
41754175
static PyObject *
41764176
time_str(PyDateTime_Time *self)
41774177
{
4178-
return _PyObject_CallMethodId((PyObject *)self, &PyId_isoformat, NULL);
4178+
return _PyObject_CallMethodIdNoArgs((PyObject *)self, &PyId_isoformat);
41794179
}
41804180

41814181
static PyObject *

Modules/_dbmmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ static PyObject *
370370
dbm__exit__(PyObject *self, PyObject *args)
371371
{
372372
_Py_IDENTIFIER(close);
373-
return _PyObject_CallMethodId(self, &PyId_close, NULL);
373+
return _PyObject_CallMethodIdNoArgs(self, &PyId_close);
374374
}
375375

376376

Modules/_gdbmmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ static PyObject *
497497
dbm__exit__(PyObject *self, PyObject *args)
498498
{
499499
_Py_IDENTIFIER(close);
500-
return _PyObject_CallMethodId(self, &PyId_close, NULL);
500+
return _PyObject_CallMethodIdNoArgs(self, &PyId_close);
501501
}
502502

503503
static PyMethodDef dbm_methods[] = {

Modules/_io/_iomodule.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode,
400400

401401
/* buffering */
402402
if (buffering < 0) {
403-
PyObject *res = _PyObject_CallMethodId(raw, &PyId_isatty, NULL);
403+
PyObject *res = _PyObject_CallMethodIdNoArgs(raw, &PyId_isatty);
404404
if (res == NULL)
405405
goto error;
406406
isatty = PyLong_AsLong(res);
@@ -494,7 +494,7 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode,
494494
if (result != NULL) {
495495
PyObject *exc, *val, *tb, *close_result;
496496
PyErr_Fetch(&exc, &val, &tb);
497-
close_result = _PyObject_CallMethodId(result, &PyId_close, NULL);
497+
close_result = _PyObject_CallMethodIdNoArgs(result, &PyId_close);
498498
_PyErr_ChainExceptions(exc, val, tb);
499499
Py_XDECREF(close_result);
500500
Py_DECREF(result);

Modules/_io/bufferedio.c

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ static PyObject *
461461
buffered_simple_flush(buffered *self, PyObject *args)
462462
{
463463
CHECK_INITIALIZED(self)
464-
return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);
464+
return _PyObject_CallMethodNoArgs(self->raw, _PyIO_str_flush);
465465
}
466466

467467
static int
@@ -513,15 +513,15 @@ buffered_close(buffered *self, PyObject *args)
513513
}
514514
/* flush() will most probably re-take the lock, so drop it first */
515515
LEAVE_BUFFERED(self)
516-
res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
516+
res = _PyObject_CallMethodNoArgs((PyObject *)self, _PyIO_str_flush);
517517
if (!ENTER_BUFFERED(self))
518518
return NULL;
519519
if (res == NULL)
520520
PyErr_Fetch(&exc, &val, &tb);
521521
else
522522
Py_DECREF(res);
523523

524-
res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
524+
res = _PyObject_CallMethodNoArgs(self->raw, _PyIO_str_close);
525525

526526
if (self->buffer) {
527527
PyMem_Free(self->buffer);
@@ -545,7 +545,7 @@ buffered_detach(buffered *self, PyObject *Py_UNUSED(ignored))
545545
{
546546
PyObject *raw, *res;
547547
CHECK_INITIALIZED(self)
548-
res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
548+
res = _PyObject_CallMethodNoArgs((PyObject *)self, _PyIO_str_flush);
549549
if (res == NULL)
550550
return NULL;
551551
Py_DECREF(res);
@@ -562,21 +562,21 @@ static PyObject *
562562
buffered_seekable(buffered *self, PyObject *Py_UNUSED(ignored))
563563
{
564564
CHECK_INITIALIZED(self)
565-
return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
565+
return _PyObject_CallMethodNoArgs(self->raw, _PyIO_str_seekable);
566566
}
567567

568568
static PyObject *
569569
buffered_readable(buffered *self, PyObject *Py_UNUSED(ignored))
570570
{
571571
CHECK_INITIALIZED(self)
572-
return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
572+
return _PyObject_CallMethodNoArgs(self->raw, _PyIO_str_readable);
573573
}
574574

575575
static PyObject *
576576
buffered_writable(buffered *self, PyObject *Py_UNUSED(ignored))
577577
{
578578
CHECK_INITIALIZED(self)
579-
return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
579+
return _PyObject_CallMethodNoArgs(self->raw, _PyIO_str_writable);
580580
}
581581

582582
static PyObject *
@@ -599,14 +599,14 @@ static PyObject *
599599
buffered_fileno(buffered *self, PyObject *Py_UNUSED(ignored))
600600
{
601601
CHECK_INITIALIZED(self)
602-
return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
602+
return _PyObject_CallMethodNoArgs(self->raw, _PyIO_str_fileno);
603603
}
604604

605605
static PyObject *
606606
buffered_isatty(buffered *self, PyObject *Py_UNUSED(ignored))
607607
{
608608
CHECK_INITIALIZED(self)
609-
return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
609+
return _PyObject_CallMethodNoArgs(self->raw, _PyIO_str_isatty);
610610
}
611611

612612
/* Forward decls */
@@ -670,7 +670,7 @@ _buffered_raw_tell(buffered *self)
670670
{
671671
Py_off_t n;
672672
PyObject *res;
673-
res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
673+
res = _PyObject_CallMethodNoArgs(self->raw, _PyIO_str_tell);
674674
if (res == NULL)
675675
return -1;
676676
n = PyNumber_AsOff_t(res, PyExc_ValueError);
@@ -1350,8 +1350,8 @@ buffered_iternext(buffered *self)
13501350
line = _buffered_readline(self, -1);
13511351
}
13521352
else {
1353-
line = PyObject_CallMethodObjArgs((PyObject *)self,
1354-
_PyIO_str_readline, NULL);
1353+
line = _PyObject_CallMethodNoArgs((PyObject *)self,
1354+
_PyIO_str_readline);
13551355
if (line && !PyBytes_Check(line)) {
13561356
PyErr_Format(PyExc_OSError,
13571357
"readline() should have returned a bytes object, "
@@ -1566,7 +1566,7 @@ _bufferedreader_read_all(buffered *self)
15661566
}
15671567

15681568
/* Read until EOF or until read() would block. */
1569-
data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1569+
data = _PyObject_CallMethodNoArgs(self->raw, _PyIO_str_read);
15701570
if (data == NULL)
15711571
goto cleanup;
15721572
if (data != Py_None && !PyBytes_Check(data)) {

Modules/_io/iobase.c

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ _io__IOBase_close_impl(PyObject *self)
235235
Py_RETURN_NONE;
236236
}
237237

238-
res = PyObject_CallMethodObjArgs(self, _PyIO_str_flush, NULL);
238+
res = _PyObject_CallMethodNoArgs(self, _PyIO_str_flush);
239239

240240
PyErr_Fetch(&exc, &val, &tb);
241241
rc = _PyObject_SetAttrId(self, &PyId___IOBase_closed, Py_True);
@@ -281,8 +281,7 @@ iobase_finalize(PyObject *self)
281281
finalization process. */
282282
if (_PyObject_SetAttrId(self, &PyId__finalizing, Py_True))
283283
PyErr_Clear();
284-
res = PyObject_CallMethodObjArgs((PyObject *) self, _PyIO_str_close,
285-
NULL);
284+
res = _PyObject_CallMethodNoArgs((PyObject *)self, _PyIO_str_close);
286285
/* Silencing I/O errors is bad, but printing spurious tracebacks is
287286
equally as bad, and potentially more frequent (because of
288287
shutdown issues). */
@@ -383,7 +382,7 @@ _io__IOBase_seekable_impl(PyObject *self)
383382
PyObject *
384383
_PyIOBase_check_seekable(PyObject *self, PyObject *args)
385384
{
386-
PyObject *res = PyObject_CallMethodObjArgs(self, _PyIO_str_seekable, NULL);
385+
PyObject *res = _PyObject_CallMethodNoArgs(self, _PyIO_str_seekable);
387386
if (res == NULL)
388387
return NULL;
389388
if (res != Py_True) {
@@ -416,7 +415,7 @@ _io__IOBase_readable_impl(PyObject *self)
416415
PyObject *
417416
_PyIOBase_check_readable(PyObject *self, PyObject *args)
418417
{
419-
PyObject *res = PyObject_CallMethodObjArgs(self, _PyIO_str_readable, NULL);
418+
PyObject *res = _PyObject_CallMethodNoArgs(self, _PyIO_str_readable);
420419
if (res == NULL)
421420
return NULL;
422421
if (res != Py_True) {
@@ -449,7 +448,7 @@ _io__IOBase_writable_impl(PyObject *self)
449448
PyObject *
450449
_PyIOBase_check_writable(PyObject *self, PyObject *args)
451450
{
452-
PyObject *res = PyObject_CallMethodObjArgs(self, _PyIO_str_writable, NULL);
451+
PyObject *res = _PyObject_CallMethodNoArgs(self, _PyIO_str_writable);
453452
if (res == NULL)
454453
return NULL;
455454
if (res != Py_True) {
@@ -478,7 +477,7 @@ iobase_enter(PyObject *self, PyObject *args)
478477
static PyObject *
479478
iobase_exit(PyObject *self, PyObject *args)
480479
{
481-
return PyObject_CallMethodObjArgs(self, _PyIO_str_close, NULL);
480+
return _PyObject_CallMethodNoArgs(self, _PyIO_str_close);
482481
}
483482

484483
/* Lower-level APIs */
@@ -656,7 +655,7 @@ iobase_iter(PyObject *self)
656655
static PyObject *
657656
iobase_iternext(PyObject *self)
658657
{
659-
PyObject *line = PyObject_CallMethodObjArgs(self, _PyIO_str_readline, NULL);
658+
PyObject *line = _PyObject_CallMethodNoArgs(self, _PyIO_str_readline);
660659

661660
if (line == NULL)
662661
return NULL;
@@ -921,7 +920,7 @@ _io__RawIOBase_read_impl(PyObject *self, Py_ssize_t n)
921920
if (n < 0) {
922921
_Py_IDENTIFIER(readall);
923922

924-
return _PyObject_CallMethodId(self, &PyId_readall, NULL);
923+
return _PyObject_CallMethodIdNoArgs(self, &PyId_readall);
925924
}
926925

927926
/* TODO: allocate a bytes object directly instead and manually construct

0 commit comments

Comments
 (0)