Skip to content

Commit 59ad110

Browse files
jdemeyermethane
authored andcommitted
bpo-37547: add _PyObject_CallMethodOneArg (GH-14685)
1 parent 2a3d4d9 commit 59ad110

23 files changed

+104
-93
lines changed

Doc/c-api/object.rst

+12
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,18 @@ Object Protocol
375375
.. versionadded:: 3.9
376376
377377
378+
.. c:function:: PyObject* _PyObject_CallMethodOneArg(PyObject *obj, PyObject *name, PyObject *arg)
379+
380+
Call a method of the Python object *obj* with a single positional argument
381+
*arg*, where the name of the method is given as a Python string object in
382+
*name*.
383+
384+
Return the result of the call on success, or raise an exception and return
385+
*NULL* on failure.
386+
387+
.. versionadded:: 3.9
388+
389+
378390
.. c:function:: PyObject* _PyObject_Vectorcall(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames)
379391
380392
Call a callable Python object *callable*, using

Include/cpython/abstract.h

+18
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,15 @@ _PyObject_CallMethodNoArgs(PyObject *self, PyObject *name)
163163
1 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
164164
}
165165

166+
static inline PyObject *
167+
_PyObject_CallMethodOneArg(PyObject *self, PyObject *name, PyObject *arg)
168+
{
169+
assert(arg != NULL);
170+
PyObject *args[2] = {self, arg};
171+
return _PyObject_VectorcallMethod(name, args,
172+
2 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
173+
}
174+
166175
/* Like PyObject_CallMethod(), but expect a _Py_Identifier*
167176
as the method name. */
168177
PyAPI_FUNC(PyObject *) _PyObject_CallMethodId(PyObject *obj,
@@ -198,6 +207,15 @@ _PyObject_CallMethodIdNoArgs(PyObject *self, _Py_Identifier *name)
198207
1 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
199208
}
200209

210+
static inline PyObject *
211+
_PyObject_CallMethodIdOneArg(PyObject *self, _Py_Identifier *name, PyObject *arg)
212+
{
213+
assert(arg != NULL);
214+
PyObject *args[2] = {self, arg};
215+
return _PyObject_VectorcallMethodId(name, args,
216+
2 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
217+
}
218+
201219
PyAPI_FUNC(int) _PyObject_HasLen(PyObject *o);
202220

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

Modules/_abc.c

+8-15
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,6 @@ _abc__abc_instancecheck_impl(PyObject *module, PyObject *self,
480480
/*[clinic end generated code: output=b8b5148f63b6b56f input=a4f4525679261084]*/
481481
{
482482
PyObject *subtype, *result = NULL, *subclass = NULL;
483-
PyObject *margs[2];
484483
_abc_data *impl = _get_impl(self);
485484
if (impl == NULL) {
486485
return NULL;
@@ -515,16 +514,12 @@ _abc__abc_instancecheck_impl(PyObject *module, PyObject *self,
515514
}
516515
}
517516
/* Fall back to the subclass check. */
518-
margs[0] = self;
519-
margs[1] = subclass;
520-
result = _PyObject_VectorcallMethodId(&PyId___subclasscheck__, margs,
521-
2 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
517+
result = _PyObject_CallMethodIdOneArg(self, &PyId___subclasscheck__,
518+
subclass);
522519
goto end;
523520
}
524-
margs[0] = self;
525-
margs[1] = subclass;
526-
result = _PyObject_VectorcallMethodId(&PyId___subclasscheck__, margs,
527-
2 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
521+
result = _PyObject_CallMethodIdOneArg(self, &PyId___subclasscheck__,
522+
subclass);
528523
if (result == NULL) {
529524
goto end;
530525
}
@@ -536,10 +531,8 @@ _abc__abc_instancecheck_impl(PyObject *module, PyObject *self,
536531
break;
537532
case 0:
538533
Py_DECREF(result);
539-
margs[0] = self;
540-
margs[1] = subtype;
541-
result = _PyObject_VectorcallMethodId(&PyId___subclasscheck__, margs,
542-
2 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
534+
result = _PyObject_CallMethodIdOneArg(self, &PyId___subclasscheck__,
535+
subtype);
543536
break;
544537
case 1: // Nothing to do.
545538
break;
@@ -620,8 +613,8 @@ _abc__abc_subclasscheck_impl(PyObject *module, PyObject *self,
620613
}
621614

622615
/* 3. Check the subclass hook. */
623-
ok = _PyObject_CallMethodIdObjArgs((PyObject *)self, &PyId___subclasshook__,
624-
subclass, NULL);
616+
ok = _PyObject_CallMethodIdOneArg((PyObject *)self, &PyId___subclasshook__,
617+
subclass);
625618
if (ok == NULL) {
626619
goto end;
627620
}

Modules/_asynciomodule.c

+6-8
Original file line numberDiff line numberDiff line change
@@ -1842,8 +1842,8 @@ register_task(PyObject *task)
18421842
{
18431843
_Py_IDENTIFIER(add);
18441844

1845-
PyObject *res = _PyObject_CallMethodIdObjArgs(
1846-
all_tasks, &PyId_add, task, NULL);
1845+
PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
1846+
&PyId_add, task);
18471847
if (res == NULL) {
18481848
return -1;
18491849
}
@@ -1857,8 +1857,8 @@ unregister_task(PyObject *task)
18571857
{
18581858
_Py_IDENTIFIER(discard);
18591859

1860-
PyObject *res = _PyObject_CallMethodIdObjArgs(
1861-
all_tasks, &PyId_discard, task, NULL);
1860+
PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
1861+
&PyId_discard, task);
18621862
if (res == NULL) {
18631863
return -1;
18641864
}
@@ -2611,13 +2611,11 @@ task_step_impl(TaskObj *task, PyObject *exc)
26112611
result = _PyGen_Send((PyGenObject*)coro, Py_None);
26122612
}
26132613
else {
2614-
result = _PyObject_CallMethodIdObjArgs(coro, &PyId_send,
2615-
Py_None, NULL);
2614+
result = _PyObject_CallMethodIdOneArg(coro, &PyId_send, Py_None);
26162615
}
26172616
}
26182617
else {
2619-
result = _PyObject_CallMethodIdObjArgs(coro, &PyId_throw,
2620-
exc, NULL);
2618+
result = _PyObject_CallMethodIdOneArg(coro, &PyId_throw, exc);
26212619
if (clear_exc) {
26222620
/* We created 'exc' during this call */
26232621
Py_DECREF(exc);

Modules/_ctypes/callproc.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1699,7 +1699,7 @@ unpickle(PyObject *self, PyObject *args)
16991699

17001700
if (!PyArg_ParseTuple(args, "OO!", &typ, &PyTuple_Type, &state))
17011701
return NULL;
1702-
obj = _PyObject_CallMethodIdObjArgs(typ, &PyId___new__, typ, NULL);
1702+
obj = _PyObject_CallMethodIdOneArg(typ, &PyId___new__, typ);
17031703
if (obj == NULL)
17041704
return NULL;
17051705

Modules/_datetimemodule.c

+6-9
Original file line numberDiff line numberDiff line change
@@ -1237,8 +1237,7 @@ call_tzname(PyObject *tzinfo, PyObject *tzinfoarg)
12371237
if (tzinfo == Py_None)
12381238
Py_RETURN_NONE;
12391239

1240-
result = _PyObject_CallMethodIdObjArgs(tzinfo, &PyId_tzname,
1241-
tzinfoarg, NULL);
1240+
result = _PyObject_CallMethodIdOneArg(tzinfo, &PyId_tzname, tzinfoarg);
12421241

12431242
if (result == NULL || result == Py_None)
12441243
return result;
@@ -1693,8 +1692,7 @@ build_struct_time(int y, int m, int d, int hh, int mm, int ss, int dstflag)
16931692
return NULL;
16941693
}
16951694

1696-
result = _PyObject_CallMethodIdObjArgs(time, &PyId_struct_time,
1697-
args, NULL);
1695+
result = _PyObject_CallMethodIdOneArg(time, &PyId_struct_time, args);
16981696
Py_DECREF(time);
16991697
Py_DECREF(args);
17001698
return result;
@@ -2894,8 +2892,7 @@ date_today(PyObject *cls, PyObject *dummy)
28942892
* time.time() delivers; if someone were gonzo about optimization,
28952893
* date.today() could get away with plain C time().
28962894
*/
2897-
result = _PyObject_CallMethodIdObjArgs(cls, &PyId_fromtimestamp,
2898-
time, NULL);
2895+
result = _PyObject_CallMethodIdOneArg(cls, &PyId_fromtimestamp, time);
28992896
Py_DECREF(time);
29002897
return result;
29012898
}
@@ -3209,8 +3206,8 @@ date_format(PyDateTime_Date *self, PyObject *args)
32093206
if (PyUnicode_GetLength(format) == 0)
32103207
return PyObject_Str((PyObject *)self);
32113208

3212-
return _PyObject_CallMethodIdObjArgs((PyObject *)self, &PyId_strftime,
3213-
format, NULL);
3209+
return _PyObject_CallMethodIdOneArg((PyObject *)self, &PyId_strftime,
3210+
format);
32143211
}
32153212

32163213
/* ISO methods. */
@@ -5960,7 +5957,7 @@ datetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
59605957

59615958
temp = (PyObject *)result;
59625959
result = (PyDateTime_DateTime *)
5963-
_PyObject_CallMethodIdObjArgs(tzinfo, &PyId_fromutc, temp, NULL);
5960+
_PyObject_CallMethodIdOneArg(tzinfo, &PyId_fromutc, temp);
59645961
Py_DECREF(temp);
59655962

59665963
return result;

Modules/_elementtree.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -2679,7 +2679,7 @@ treebuilder_add_subelement(PyObject *element, PyObject *child)
26792679
}
26802680
else {
26812681
PyObject *res;
2682-
res = _PyObject_CallMethodIdObjArgs(element, &PyId_append, child, NULL);
2682+
res = _PyObject_CallMethodIdOneArg(element, &PyId_append, child);
26832683
if (res == NULL)
26842684
return -1;
26852685
Py_DECREF(res);

Modules/_io/bufferedio.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -439,8 +439,8 @@ buffered_dealloc_warn(buffered *self, PyObject *source)
439439
{
440440
if (self->ok && self->raw) {
441441
PyObject *r;
442-
r = _PyObject_CallMethodIdObjArgs(self->raw, &PyId__dealloc_warn,
443-
source, NULL);
442+
r = _PyObject_CallMethodIdOneArg(self->raw, &PyId__dealloc_warn,
443+
source);
444444
if (r)
445445
Py_DECREF(r);
446446
else
@@ -1323,7 +1323,7 @@ _io__Buffered_truncate_impl(buffered *self, PyObject *pos)
13231323
goto end;
13241324
Py_CLEAR(res);
13251325
}
1326-
res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1326+
res = _PyObject_CallMethodOneArg(self->raw, _PyIO_str_truncate, pos);
13271327
if (res == NULL)
13281328
goto end;
13291329
/* Reset cached position */
@@ -1467,7 +1467,7 @@ _bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
14671467
raised (see issue #10956).
14681468
*/
14691469
do {
1470-
res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1470+
res = _PyObject_CallMethodOneArg(self->raw, _PyIO_str_readinto, memobj);
14711471
} while (res == NULL && _PyIO_trap_eintr());
14721472
Py_DECREF(memobj);
14731473
if (res == NULL)
@@ -1815,7 +1815,7 @@ _bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
18151815
*/
18161816
do {
18171817
errno = 0;
1818-
res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1818+
res = _PyObject_CallMethodOneArg(self->raw, _PyIO_str_write, memobj);
18191819
errnum = errno;
18201820
} while (res == NULL && _PyIO_trap_eintr());
18211821
Py_DECREF(memobj);

Modules/_io/fileio.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,8 @@ _io_FileIO_close_impl(fileio *self)
145145
PyObject *exc, *val, *tb;
146146
int rc;
147147
_Py_IDENTIFIER(close);
148-
res = _PyObject_CallMethodIdObjArgs((PyObject*)&PyRawIOBase_Type,
149-
&PyId_close, self, NULL);
148+
res = _PyObject_CallMethodIdOneArg((PyObject*)&PyRawIOBase_Type,
149+
&PyId_close, (PyObject *)self);
150150
if (!self->closefd) {
151151
self->fd = -1;
152152
return res;

Modules/_io/textio.c

+17-20
Original file line numberDiff line numberDiff line change
@@ -977,8 +977,8 @@ _textiowrapper_fix_encoder_state(textio *self)
977977

978978
if (cmp == 0) {
979979
self->encoding_start_of_stream = 0;
980-
PyObject *res = PyObject_CallMethodObjArgs(
981-
self->encoder, _PyIO_str_setstate, _PyLong_Zero, NULL);
980+
PyObject *res = _PyObject_CallMethodOneArg(
981+
self->encoder, _PyIO_str_setstate, _PyLong_Zero);
982982
if (res == NULL) {
983983
return -1;
984984
}
@@ -1155,8 +1155,8 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,
11551155
PyObject *locale_module = _PyIO_get_locale_module(state);
11561156
if (locale_module == NULL)
11571157
goto catch_ImportError;
1158-
self->encoding = _PyObject_CallMethodIdObjArgs(
1159-
locale_module, &PyId_getpreferredencoding, Py_False, NULL);
1158+
self->encoding = _PyObject_CallMethodIdOneArg(
1159+
locale_module, &PyId_getpreferredencoding, Py_False);
11601160
Py_DECREF(locale_module);
11611161
if (self->encoding == NULL) {
11621162
catch_ImportError:
@@ -1597,8 +1597,7 @@ _textiowrapper_writeflush(textio *self)
15971597

15981598
PyObject *ret;
15991599
do {
1600-
ret = PyObject_CallMethodObjArgs(self->buffer,
1601-
_PyIO_str_write, b, NULL);
1600+
ret = _PyObject_CallMethodOneArg(self->buffer, _PyIO_str_write, b);
16021601
} while (ret == NULL && _PyIO_trap_eintr());
16031602
Py_DECREF(b);
16041603
if (ret == NULL)
@@ -1668,8 +1667,7 @@ _io_TextIOWrapper_write_impl(textio *self, PyObject *text)
16681667
self->encoding_start_of_stream = 0;
16691668
}
16701669
else
1671-
b = PyObject_CallMethodObjArgs(self->encoder,
1672-
_PyIO_str_encode, text, NULL);
1670+
b = _PyObject_CallMethodOneArg(self->encoder, _PyIO_str_encode, text);
16731671

16741672
Py_DECREF(text);
16751673
if (b == NULL)
@@ -1851,9 +1849,9 @@ textiowrapper_read_chunk(textio *self, Py_ssize_t size_hint)
18511849
if (chunk_size == NULL)
18521850
goto fail;
18531851

1854-
input_chunk = PyObject_CallMethodObjArgs(self->buffer,
1852+
input_chunk = _PyObject_CallMethodOneArg(self->buffer,
18551853
(self->has_read1 ? _PyIO_str_read1: _PyIO_str_read),
1856-
chunk_size, NULL);
1854+
chunk_size);
18571855
Py_DECREF(chunk_size);
18581856
if (input_chunk == NULL)
18591857
goto fail;
@@ -2414,8 +2412,8 @@ _textiowrapper_encoder_reset(textio *self, int start_of_stream)
24142412
self->encoding_start_of_stream = 1;
24152413
}
24162414
else {
2417-
res = PyObject_CallMethodObjArgs(self->encoder, _PyIO_str_setstate,
2418-
_PyLong_Zero, NULL);
2415+
res = _PyObject_CallMethodOneArg(self->encoder, _PyIO_str_setstate,
2416+
_PyLong_Zero);
24192417
self->encoding_start_of_stream = 0;
24202418
}
24212419
if (res == NULL)
@@ -2554,8 +2552,7 @@ _io_TextIOWrapper_seek_impl(textio *self, PyObject *cookieObj, int whence)
25542552
posobj = PyLong_FromOff_t(cookie.start_pos);
25552553
if (posobj == NULL)
25562554
goto fail;
2557-
res = PyObject_CallMethodObjArgs(self->buffer,
2558-
_PyIO_str_seek, posobj, NULL);
2555+
res = _PyObject_CallMethodOneArg(self->buffer, _PyIO_str_seek, posobj);
25592556
Py_DECREF(posobj);
25602557
if (res == NULL)
25612558
goto fail;
@@ -2837,7 +2834,7 @@ _io_TextIOWrapper_tell_impl(textio *self)
28372834
}
28382835

28392836
finally:
2840-
res = _PyObject_CallMethodIdObjArgs(self->decoder, &PyId_setstate, saved_state, NULL);
2837+
res = _PyObject_CallMethodIdOneArg(self->decoder, &PyId_setstate, saved_state);
28412838
Py_DECREF(saved_state);
28422839
if (res == NULL)
28432840
return NULL;
@@ -2851,7 +2848,7 @@ _io_TextIOWrapper_tell_impl(textio *self)
28512848
if (saved_state) {
28522849
PyObject *type, *value, *traceback;
28532850
PyErr_Fetch(&type, &value, &traceback);
2854-
res = _PyObject_CallMethodIdObjArgs(self->decoder, &PyId_setstate, saved_state, NULL);
2851+
res = _PyObject_CallMethodIdOneArg(self->decoder, &PyId_setstate, saved_state);
28552852
_PyErr_ChainExceptions(type, value, traceback);
28562853
Py_DECREF(saved_state);
28572854
Py_XDECREF(res);
@@ -2878,7 +2875,7 @@ _io_TextIOWrapper_truncate_impl(textio *self, PyObject *pos)
28782875
return NULL;
28792876
Py_DECREF(res);
28802877

2881-
return PyObject_CallMethodObjArgs(self->buffer, _PyIO_str_truncate, pos, NULL);
2878+
return _PyObject_CallMethodOneArg(self->buffer, _PyIO_str_truncate, pos);
28822879
}
28832880

28842881
static PyObject *
@@ -3055,9 +3052,9 @@ _io_TextIOWrapper_close_impl(textio *self)
30553052
else {
30563053
PyObject *exc = NULL, *val, *tb;
30573054
if (self->finalizing) {
3058-
res = _PyObject_CallMethodIdObjArgs(self->buffer,
3059-
&PyId__dealloc_warn,
3060-
self, NULL);
3055+
res = _PyObject_CallMethodIdOneArg(self->buffer,
3056+
&PyId__dealloc_warn,
3057+
(PyObject *)self);
30613058
if (res)
30623059
Py_DECREF(res);
30633060
else

Modules/_io/winconsoleio.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,8 @@ _io__WindowsConsoleIO_close_impl(winconsoleio *self)
204204
PyObject *exc, *val, *tb;
205205
int rc;
206206
_Py_IDENTIFIER(close);
207-
res = _PyObject_CallMethodIdObjArgs((PyObject*)&PyRawIOBase_Type,
208-
&PyId_close, self, NULL);
207+
res = _PyObject_CallMethodIdOneArg((PyObject*)&PyRawIOBase_Type,
208+
&PyId_close, self);
209209
if (!self->closehandle) {
210210
self->handle = INVALID_HANDLE_VALUE;
211211
return res;

Modules/_pickle.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -5773,7 +5773,7 @@ instantiate(PyObject *cls, PyObject *args)
57735773
return NULL;
57745774
}
57755775
if (func == NULL) {
5776-
return _PyObject_CallMethodIdObjArgs(cls, &PyId___new__, cls, NULL);
5776+
return _PyObject_CallMethodIdOneArg(cls, &PyId___new__, cls);
57775777
}
57785778
Py_DECREF(func);
57795779
}

0 commit comments

Comments
 (0)